From dfe438dc732a472a08490c4b7ca5c0d9fce115e8 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 18 Dec 2012 13:02:17 -0500 Subject: [PATCH 0001/1392] Initial work on the rubric input type including the most basic parsing without error handling --- common/lib/capa/capa/inputtypes.py | 99 +++++++++++++++++++ .../lib/capa/capa/templates/rubricinput.html | 5 + 2 files changed, 104 insertions(+) create mode 100644 common/lib/capa/capa/templates/rubricinput.html diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index 73056bc09e..f19f38ce96 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -783,3 +783,102 @@ class OpenEndedInput(InputTypeBase): registry.register(OpenEndedInput) #----------------------------------------------------------------------------- + +class RubricInput(InputTypeBase): + """ + This is the logic for parsing and displaying a rubric of type + """ + + template = "rubricinput.html" + tags = ['rubric'] + + # pulled out for testing + submitted_msg = ("Feedback not yet available. Reload to check again. " + "Once the problem is graded, this message will be " + "replaced with the grader's feedback.") + + @classmethod + def get_attributes(cls): + """ + Convert options to a convenient format. + """ + return [ + ] + + def _extra_context(self): + """ + Add in the various bits and pieces of the + """ + return {} + + def setup(self): + + extract_categories(self.xml) + + @staticmethod + def extract_categories(element): + ''' + Contstruct a list of categories such that the structure looks like: + [ { category: "Category 1 Name", + options: [{text: "Option 1 Name", points: 0}, {text:"Option 2 Name", points: 5}] + }, + { category: "Category 2 Name", + options: [{text: "Option 1 Name", points: 0}, + {text: "Option 2 Name", points: 1}, + {text: "Option 3 Name", points: 2]}] + + ''' + categories = [] + for category in element: + if category.tag != 'category': + raise Exception("[capa.inputtypes.extract_categories] Expected a tag: got {0} instead".format(category.tag)) + else: + categories.append(extract_category(category)) + self.categories = categories + + + @staticmethod + def extract_category(category): + ''' + construct an individual category + {category: "Category 1 Name", + options: [{text: "Option 1 text", points: 1}, + {text: "Option 2 text", points: 2}]} + + all sorting and auto-point generation occurs in this function + ''' + descriptionxml = category[0] + optionsxml = category[1:] + + # parse description + if descriptionxml.tag != 'description': + raise Exception("[extract_category: expected description tag, got {0} instead".format(descriptionxml.tag)) + + description = descriptionxml.text + + cur_points = 0 + options = [] + # parse options + for option in optionsxml: + if option.tag != 'option': + raise Exception("[extract_category: expected option tag, got {0} instead".format(option.tag)) + else: + pointstr = option.get("points") + if(pointstr): + # try to parse this into an int + try: + points = int(pointstr) + except ValueError: + raise Exception("[extract_category: expected int to have points, got {0} instead".format(pointstr)) + else: + # use the generated one + points = cur_points + cur_points = cur_points + 1 + optiontext = option.text + options.append({'text': option.text, 'points': points}) + + return {'description': description, 'options': options} + +registry.register(RubricInput) + +#----------------------------------------------------------------------------- diff --git a/common/lib/capa/capa/templates/rubricinput.html b/common/lib/capa/capa/templates/rubricinput.html new file mode 100644 index 0000000000..e78ced62db --- /dev/null +++ b/common/lib/capa/capa/templates/rubricinput.html @@ -0,0 +1,5 @@ +
+ + +
+
From 8a0dae01f06e4e3ea52b641e0808aff3fb9d2c2c Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 18 Dec 2012 14:32:10 -0500 Subject: [PATCH 0002/1392] Add in some sorting and validation of the options list --- common/lib/capa/capa/inputtypes.py | 37 +++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index f19f38ce96..ab5e71fd5a 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -852,32 +852,57 @@ class RubricInput(InputTypeBase): # parse description if descriptionxml.tag != 'description': - raise Exception("[extract_category: expected description tag, got {0} instead".format(descriptionxml.tag)) + raise Exception("[extract_category]: expected description tag, got {0} instead".format(descriptionxml.tag)) description = descriptionxml.text cur_points = 0 options = [] + autonumbering = True # parse options for option in optionsxml: if option.tag != 'option': - raise Exception("[extract_category: expected option tag, got {0} instead".format(option.tag)) + raise Exception("[extract_category]: expected option tag, got {0} instead".format(option.tag)) else: pointstr = option.get("points") - if(pointstr): + if pointstr: + autonumbering = False # try to parse this into an int try: points = int(pointstr) except ValueError: - raise Exception("[extract_category: expected int to have points, got {0} instead".format(pointstr)) - else: - # use the generated one + raise Exception("[extract_category]: expected points to have int, got {0} instead".format(pointstr)) + elif autonumbering: + # use the generated one if we're in the right mode points = cur_points cur_points = cur_points + 1 + else: + raise Exception("[extract_category]: missing points attribute. Cannot continue to auto-create points values after a points value is explicitly dfined.") optiontext = option.text options.append({'text': option.text, 'points': points}) + # sort and check for duplicates + options = sorted(options, key=lambda option: option['points']) + validate_options(options) + return {'description': description, 'options': options} + + @staticmethod + def validate_options(options): + ''' + Validates a set of options. This can and should be extended to filter out other bad edge cases + ''' + if len(options) == 0: + raise Exception("[extract_category]: no options associated with this category") + if len(options) == 1: + return + prev = options[0]['points'] + for option in options[1:]: + if prev == option['points']: + raise Exception("[extract_category]: found duplicate point values between two different options") + else: + prev = option['points'] + registry.register(RubricInput) From 11d5eea2b9110b687b0c79744185bc50b6ffabc1 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 19 Dec 2012 11:52:37 -0500 Subject: [PATCH 0003/1392] Add in CSS updates and fixes to the template so that it will work. --- common/lib/capa/capa/inputtypes.py | 18 ++++---- .../lib/capa/capa/templates/rubricinput.html | 26 +++++++++-- .../lib/xmodule/xmodule/css/capa/display.scss | 45 +++++++++++++++++++ 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index ab5e71fd5a..d4be44b772 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -803,17 +803,19 @@ class RubricInput(InputTypeBase): Convert options to a convenient format. """ return [ - ] + Attribute('height', None), + Attribute('width', None)] def _extra_context(self): """ - Add in the various bits and pieces of the + Add in the various bits and pieces that we need """ - return {} + return {'categories': self.categories, + 'view_only': False} def setup(self): - - extract_categories(self.xml) + # set the categories + self.categories = self.extract_categories(self.xml) @staticmethod def extract_categories(element): @@ -833,8 +835,8 @@ class RubricInput(InputTypeBase): if category.tag != 'category': raise Exception("[capa.inputtypes.extract_categories] Expected a tag: got {0} instead".format(category.tag)) else: - categories.append(extract_category(category)) - self.categories = categories + categories.append(RubricInput.extract_category(category)) + return categories @staticmethod @@ -883,7 +885,7 @@ class RubricInput(InputTypeBase): # sort and check for duplicates options = sorted(options, key=lambda option: option['points']) - validate_options(options) + RubricInput.validate_options(options) return {'description': description, 'options': options} diff --git a/common/lib/capa/capa/templates/rubricinput.html b/common/lib/capa/capa/templates/rubricinput.html index e78ced62db..32e7180656 100644 --- a/common/lib/capa/capa/templates/rubricinput.html +++ b/common/lib/capa/capa/templates/rubricinput.html @@ -1,5 +1,25 @@ -
+
- + % for i in range(len(categories)): + <% category = categories[i] %> + + + % for j in range(len(category['options'])): + <% option = category['options'][j] %> + + % endfor + + % endfor
${category['description']} + + % if view_only: +
+ ${option['text']} +
[${option['points']} points]
+
+ % else: + + + % endif +
-
+ diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index b25ab3d3a2..782ee5b3a3 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -20,6 +20,51 @@ h2 { color: darken($error-red, 10%); } +.rubric { + tr { + margin:10px 0px; + height: 100%; + } + td { + padding: 20px 0px; + margin: 10px 0px; + height: 100%; + } + th { + padding: 5px; + margin: 5px; + } + label, + .view-only { + margin:10px; + position: relative; + padding: 15px; + width: 175px; + height:100%; + display: inline-block; + min-height: 50px; + min-width: 50px; + background-color: #CCC; + text-size: 1.5em; + } + .grade { + position: absolute; + bottom:0px; + right:0px; + margin:10px; + } + .selected-grade { + background: #666; + color: white; + } + input[type=radio]:checked + label { + background: #666; + color: white; } + input[class='score-selection'] { + display: none; + } +} + section.problem { @media print { display: block; From 728103056d3fef4faa44307d278bd0e9e46fe720 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 19 Dec 2012 13:16:35 -0500 Subject: [PATCH 0004/1392] Move rubric into a subset of problem in CSS. --- .../lib/xmodule/xmodule/css/capa/display.scss | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index 782ee5b3a3..e7f5121b78 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -20,50 +20,6 @@ h2 { color: darken($error-red, 10%); } -.rubric { - tr { - margin:10px 0px; - height: 100%; - } - td { - padding: 20px 0px; - margin: 10px 0px; - height: 100%; - } - th { - padding: 5px; - margin: 5px; - } - label, - .view-only { - margin:10px; - position: relative; - padding: 15px; - width: 175px; - height:100%; - display: inline-block; - min-height: 50px; - min-width: 50px; - background-color: #CCC; - text-size: 1.5em; - } - .grade { - position: absolute; - bottom:0px; - right:0px; - margin:10px; - } - .selected-grade { - background: #666; - color: white; - } - input[type=radio]:checked + label { - background: #666; - color: white; } - input[class='score-selection'] { - display: none; - } -} section.problem { @media print { @@ -752,4 +708,49 @@ section.problem { } } } + + .rubric { + tr { + margin:10px 0px; + height: 100%; + } + td { + padding: 20px 0px; + margin: 10px 0px; + height: 100%; + } + th { + padding: 5px; + margin: 5px; + } + label, + .view-only { + margin:10px; + position: relative; + padding: 15px; + width: 200px; + height:100%; + display: inline-block; + min-height: 50px; + min-width: 50px; + background-color: #CCC; + text-size: 1.5em; + } + .grade { + position: absolute; + bottom:0px; + right:0px; + margin:10px; + } + .selected-grade { + background: #666; + color: white; + } + input[type=radio]:checked + label { + background: #666; + color: white; } + input[class='score-selection'] { + display: none; + } + } } From fa97a6a528411221e1b6e8636c14bfd38cd94b35 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 19 Dec 2012 16:04:47 -0500 Subject: [PATCH 0005/1392] Fix the font size --- common/lib/xmodule/xmodule/css/capa/display.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index e7f5121b78..4a973133fb 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -734,7 +734,7 @@ section.problem { min-height: 50px; min-width: 50px; background-color: #CCC; - text-size: 1.5em; + font-size: 1em; } .grade { position: absolute; From 5a211f566d16b3ef9ac398db286e6e91d172bb7f Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Fri, 11 Jan 2013 09:31:38 -0500 Subject: [PATCH 0006/1392] Make the rubric smaller so that we can accomodate more columns. --- common/lib/xmodule/xmodule/css/capa/display.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index 7fb09dbfb1..d40bdb556e 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -774,16 +774,16 @@ section.problem { } label, .view-only { - margin:10px; + margin:3px; position: relative; padding: 15px; - width: 200px; + width: 150px; height:100%; display: inline-block; min-height: 50px; min-width: 50px; background-color: #CCC; - font-size: 1em; + font-size: .9em; } .grade { position: absolute; From f3e8d01e0858b4884eb2b6d53d70d2e45067fabc Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Fri, 11 Jan 2013 17:29:39 -0500 Subject: [PATCH 0007/1392] Pull out old rubric and score selection logic and set up the new rubric --- .../lib/capa/capa/templates/rubricinput.html | 7 +- .../staff_grading_service.py | 20 +++- .../src/staff_grading/staff_grading.coffee | 106 ++++++++++++------ lms/static/sass/course/_staff_grading.scss | 45 ++++++++ lms/templates/instructor/staff_grading.html | 5 - 5 files changed, 140 insertions(+), 43 deletions(-) diff --git a/common/lib/capa/capa/templates/rubricinput.html b/common/lib/capa/capa/templates/rubricinput.html index 32e7180656..1780603d91 100644 --- a/common/lib/capa/capa/templates/rubricinput.html +++ b/common/lib/capa/capa/templates/rubricinput.html @@ -1,4 +1,10 @@
+

Rubric

+ % if view_only: +

Select the criteria you feel best represents this submission in each category.

+ % else +

The highlighted selection best matches how the student feels you performed in each category.

+ % endif % for i in range(len(categories)): <% category = categories[i] %> @@ -7,7 +13,6 @@ % for j in range(len(category['options'])): <% option = category['options'][j] %> - + %for problem in problem_list: From d4ed059975aff3b6c1818758155782c3dd8230a3 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 23 Jan 2013 16:05:25 -0500 Subject: [PATCH 0306/1392] Do some better error checking for items. --- lms/djangoapps/open_ended_grading/views.py | 35 ++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 41a3c6d9ba..2ebd8778e6 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -51,6 +51,16 @@ def _reverse_without_slash(url_name, course_id): ajax_url = reverse(url_name, kwargs={'course_id': course_id}) return ajax_url +DESCRIPTION_DICT = { + 'Peer Grading': "View all problems that require peer assessment in this particular course.", + 'Staff Grading': "View ungraded submissions submitted by students for the open ended problems in the course.", + 'Problems you have submitted': "View open ended problems that you have previously submitted for grading." + } +ALERT_DICT = { + 'Peer Grading': "New submissions to grade", + 'Staff Grading': "New submissions to grade", + 'Problems you have submitted': "New grades have been returned" + } @cache_control(no_cache=True, no_store=True, must_revalidate=True) def staff_grading(request, course_id): """ @@ -193,16 +203,6 @@ def combined_notifications(request, course_id): notification_tuples=open_ended_notifications.NOTIFICATION_TYPES notification_list = [] - description_dict = { - 'Peer Grading': "View all problems that require peer assessment in this particular course.", - 'Staff Grading': "View ungraded submissions submitted by students for the open ended problems in the course.", - 'Problems you have submitted': "View open ended problems that you have previously submitted for grading." - } - alert_dict = { - 'Peer Grading': "New submissions to grade", - 'Staff Grading': "New submissions to grade", - 'Problems you have submitted': "New grades have been returned" - } for response_num in xrange(0,len(notification_tuples)): tag=notification_tuples[response_num][0] if tag in response: @@ -211,12 +211,23 @@ def combined_notifications(request, course_id): url = _reverse_without_slash(url_name, course_id) has_img = response[tag] + # check to make sure we have descriptions and alert messages + if human_name in DESCRIPTION_DICT: + description = DESCRIPTION_DICT[human_name] + else: + description = "" + + if human_name in ALERT_DICT: + alert_message = ALERT_DICT[human_name] + else: + alert_message = "" + notification_item = { 'url' : url, 'name' : human_name, 'alert' : has_img, - 'description': description_dict[human_name], - 'alert_message': alert_dict[human_name] + 'description': description, + 'alert_message': alert_message } notification_list.append(notification_item) From ea6ce60d0bd63fc84ed5e005edd023ecd81af58d Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 23 Jan 2013 16:37:26 -0500 Subject: [PATCH 0307/1392] Use the variable and not the hex value. --- lms/static/sass/course/_open_ended_grading.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/static/sass/course/_open_ended_grading.scss b/lms/static/sass/course/_open_ended_grading.scss index b526d1adf2..c41fe58b80 100644 --- a/lms/static/sass/course/_open_ended_grading.scss +++ b/lms/static/sass/course/_open_ended_grading.scss @@ -39,7 +39,7 @@ .notification-title { text-transform: uppercase; - background: #1d9dd9; + background: $blue; color: white; padding: 5px 0px; font-size: 1.1em; From bd0b933ff2b0de7fe8d85736c776f44a11077e94 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 23 Jan 2013 17:06:29 -0500 Subject: [PATCH 0308/1392] Highlight the correct tab --- lms/djangoapps/courseware/tabs.py | 2 +- lms/templates/open_ended_problems/combined_notifications.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index b52324b360..b2267e6cf5 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -141,7 +141,7 @@ def _combined_open_ended_grading(tab, user, course, active_page): pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] - tab = [CourseTab(tab_name, link, active_page == "controller_query", pending_grading, img_path)] + tab = [CourseTab(tab_name, link, active_page == "open_ended", pending_grading, img_path)] return tab return [] diff --git a/lms/templates/open_ended_problems/combined_notifications.html b/lms/templates/open_ended_problems/combined_notifications.html index a24d150d25..9de6ef3273 100644 --- a/lms/templates/open_ended_problems/combined_notifications.html +++ b/lms/templates/open_ended_problems/combined_notifications.html @@ -8,7 +8,7 @@ <%block name="title">${course.number} Combined Notifications -<%include file="/courseware/course_navigation.html" args="active_page='combined_notifications'" /> +<%include file="/courseware/course_navigation.html" args="active_page='open_ended'" />
From 2f2b5fa7537ad2a051bf6e1334df43b03c4420b0 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 23 Jan 2013 17:34:26 -0500 Subject: [PATCH 0309/1392] Fix unicode problem --- common/lib/xmodule/xmodule/combined_open_ended_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index efb80bd204..0b1dd39d4e 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -272,7 +272,7 @@ class CombinedOpenEndedModule(XModule): 'max_score' : self._max_score, 'attempts' : 0, 'created' : True, - 'history' : [{'answer' : str(last_response)}], + 'history' : [{'answer' : last_response}], }) self.current_task = child_task_module(self.system, self.location, self.current_task_parsed_xml, self.current_task_descriptor, self.static_data, From 6425a519fd85ea23199064319106954f5bf9a079 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 24 Jan 2013 09:36:25 -0500 Subject: [PATCH 0310/1392] Fix notifications to work with cache (sync timings) --- lms/djangoapps/open_ended_grading/open_ended_notifications.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 80f17352e9..43259f3e1b 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -9,6 +9,7 @@ from courseware.models import StudentModule import logging from courseware.access import has_access from util.cache import cache +import datetime log=logging.getLogger(__name__) @@ -100,7 +101,7 @@ def combined_notifications(course, user): last_module_seen_count = last_module_seen.count() if last_module_seen_count>0: - last_time_viewed = last_module_seen[0]['modified'] + last_time_viewed = last_module_seen[0]['modified'] - datetime.timedelta(seconds=(NOTIFICATION_CACHE_TIME + 60)) else: last_time_viewed = user.last_login From a5daf1f34defc37a4d88feb6f71247f2a61fdc70 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 24 Jan 2013 13:44:48 -0500 Subject: [PATCH 0311/1392] Perhaps properly sanitize js --- common/lib/xmodule/xmodule/open_ended_module.py | 1 + common/lib/xmodule/xmodule/openendedchild.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index c17f95a360..02059dca1a 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -554,6 +554,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): # add new history element with answer and empty score and hint. self.new_history_entry(get['student_answer']) + get['student_answer'] = self.sanitize_html(get['student_answer']) self.send_to_grader(get['student_answer'], system) self.change_state(self.ASSESSING) diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index 62d203987a..f2cc2ae295 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -5,6 +5,7 @@ import json import logging from lxml import etree from lxml.html import rewrite_links +from lxml.html.clean import Cleaner from path import path import os import sys @@ -130,12 +131,18 @@ class OpenEndedChild(object): return "" return self.history[-1].get('post_assessment', "") + def sanitize_html(self, answer): + cleaner = Cleaner(style=True, links=True, add_nofollow=True, page_structure=True, safe_attrs_only=True) + clean_html = cleaner.clean_html(answer) + return clean_html + def new_history_entry(self, answer): """ Adds a new entry to the history dictionary @param answer: The student supplied answer @return: None """ + answer = self.sanitize_html(answer) self.history.append({'answer': answer}) def record_latest_score(self, score): From fde370bd92dbf173d76dfe02eef31d0ee6cefd19 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Fri, 25 Jan 2013 09:55:47 -0500 Subject: [PATCH 0312/1392] Fix notification issue, sanitize input html --- common/lib/xmodule/xmodule/open_ended_module.py | 2 +- common/lib/xmodule/xmodule/openendedchild.py | 5 +++-- lms/djangoapps/courseware/tabs.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index 02059dca1a..28dedef0b6 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -554,7 +554,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): # add new history element with answer and empty score and hint. self.new_history_entry(get['student_answer']) - get['student_answer'] = self.sanitize_html(get['student_answer']) + get['student_answer'] = OpenEndedModule.sanitize_html(get['student_answer']) self.send_to_grader(get['student_answer'], system) self.change_state(self.ASSESSING) diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index f2cc2ae295..01ab1017ff 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -131,7 +131,8 @@ class OpenEndedChild(object): return "" return self.history[-1].get('post_assessment', "") - def sanitize_html(self, answer): + @staticmethod + def sanitize_html(answer): cleaner = Cleaner(style=True, links=True, add_nofollow=True, page_structure=True, safe_attrs_only=True) clean_html = cleaner.clean_html(answer) return clean_html @@ -142,7 +143,7 @@ class OpenEndedChild(object): @param answer: The student supplied answer @return: None """ - answer = self.sanitize_html(answer) + answer = OpenEndedChild.sanitize_html(answer) self.history.append({'answer': answer}) def record_latest_score(self, score): diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index b2267e6cf5..24fb36200c 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -133,7 +133,7 @@ def _peer_grading(tab, user, course, active_page): return [] def _combined_open_ended_grading(tab, user, course, active_page): - if user.is_authenticated: + if user.is_authenticated(): link = reverse('open_ended_notifications', args=[course.id]) tab_name = "Open Ended Panel" From 9e673e8aa7c28254f62b26e56d451a22197cd5de Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Fri, 25 Jan 2013 10:04:21 -0500 Subject: [PATCH 0313/1392] Remove wrapper p tags --- common/lib/xmodule/xmodule/openendedchild.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index 01ab1017ff..7de5d9a626 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -11,6 +11,7 @@ import os import sys import hashlib import capa.xqueue_interface as xqueue_interface +import re from pkg_resources import resource_string @@ -133,8 +134,12 @@ class OpenEndedChild(object): @staticmethod def sanitize_html(answer): - cleaner = Cleaner(style=True, links=True, add_nofollow=True, page_structure=True, safe_attrs_only=True) - clean_html = cleaner.clean_html(answer) + try: + cleaner = Cleaner(style=True, links=True, add_nofollow=True, page_structure=True, safe_attrs_only=True) + clean_html = cleaner.clean_html(answer) + clean_html = re.sub(r'

$', '', re.sub(r'^

', '', clean_html)) + except: + clean_html = answer return clean_html def new_history_entry(self, answer): From 255405d0bf549030be95fdd4087e38245e68de29 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Fri, 25 Jan 2013 11:47:27 -0500 Subject: [PATCH 0314/1392] Automatically show results at certain points (when need to reset, when finished with a problem, etc) --- .../xmodule/js/src/combinedopenended/display.coffee | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee index 370ef8d136..072a772c13 100644 --- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee @@ -55,6 +55,16 @@ class @CombinedOpenEnded $: (selector) -> $(selector, @el) + show_results_current: () => + data = {'task_number' : @task_number-1} + $.postWithPrefix "#{@ajax_url}/get_results", data, (response) => + if response.success + @results_container.after(response.html).remove() + @results_container = $('div.result-container') + @submit_evaluation_button = $('.submit-evaluation-button') + @submit_evaluation_button.click @message_post + Collapsible.setCollapsibles(@results_container) + show_results: (event) => status_item = $(event.target).parent().parent() status_number = status_item.data('status-number') @@ -114,6 +124,7 @@ class @CombinedOpenEnded if @child_type=="openended" @skip_button.hide() if @allow_reset=="True" + @show_results_current @reset_button.show() @submit_button.hide() @answer_area.attr("disabled", true) @@ -149,6 +160,7 @@ class @CombinedOpenEnded if @task_number<@task_count @next_problem() else + @show_results_current() @reset_button.show() @@ -260,6 +272,7 @@ class @CombinedOpenEnded @gentle_alert "Moved to next step." else @gentle_alert "Your score did not meet the criteria to move to the next step." + @show_results_current() else @errors_area.html(response.error) else From 5d4ad4b8ca6a6d4643a1ca37a8e626136dbad3e5 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 17:15:02 -0500 Subject: [PATCH 0315/1392] Simple method to count colors in an image --- .../xmodule/combined_open_ended_module.py | 1 - .../xmodule/open_ended_image_submission.py | 29 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 common/lib/xmodule/xmodule/open_ended_image_submission.py diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 0b1dd39d4e..66426bba28 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -617,7 +617,6 @@ class CombinedOpenEndedModule(XModule): return progress_object - class CombinedOpenEndedDescriptor(XmlDescriptor, EditingDescriptor): """ Module for adding combined open ended questions diff --git a/common/lib/xmodule/xmodule/open_ended_image_submission.py b/common/lib/xmodule/xmodule/open_ended_image_submission.py new file mode 100644 index 0000000000..b802ab5aa5 --- /dev/null +++ b/common/lib/xmodule/xmodule/open_ended_image_submission.py @@ -0,0 +1,29 @@ +from PIL import Image + +TRUSTED_IMAGE_DOMAINS = [ + 'wikipedia.com', + 'wikipedia.net', + 'wikipedia.org' +] + +MAX_IMAGE_DIM = 150 +MAX_COLORS_TO_COUNT = 16 +MAX_COLORS = 5 + +class ImageProperties(object): + def __init__(self, image): + self.image = image + image_size = self.image.size + if image_size[0]> MAX_IMAGE_DIM or image_size[1] > MAX_IMAGE_DIM: + self.image = self.image.resize((MAX_IMAGE_DIM, MAX_IMAGE_DIM)) + self.image_size = self.image.size + + def count_colors(self): + colors = self.image.getcolors(MAX_COLORS_TO_COUNT) + if colors is None: + colors = MAX_COLORS_TO_COUNT + else: + colors = len(colors) + + + From 929160e1804f92681c94e0bf82fb20e37bff0b0a Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 17:29:02 -0500 Subject: [PATCH 0316/1392] Add in ability to validate images and image paths (urls) --- .../xmodule/open_ended_image_submission.py | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/open_ended_image_submission.py b/common/lib/xmodule/xmodule/open_ended_image_submission.py index b802ab5aa5..13cee1f9e1 100644 --- a/common/lib/xmodule/xmodule/open_ended_image_submission.py +++ b/common/lib/xmodule/xmodule/open_ended_image_submission.py @@ -1,4 +1,5 @@ from PIL import Image +import urlparse TRUSTED_IMAGE_DOMAINS = [ 'wikipedia.com', @@ -6,6 +7,12 @@ TRUSTED_IMAGE_DOMAINS = [ 'wikipedia.org' ] +ALLOWABLE_IMAGE_SUFFIXES = [ + 'jpg', + 'png', + 'gif' +] + MAX_IMAGE_DIM = 150 MAX_COLORS_TO_COUNT = 16 MAX_COLORS = 5 @@ -25,5 +32,56 @@ class ImageProperties(object): else: colors = len(colors) - + return colors <= MAX_COLORS + + def get_skin_ratio(self): + im = self.image + skin = sum([count for count, rgb in im.getcolors(im.size[0]*im.size[1]) if rgb[0]>60 and rgb[1]<(rgb[0]*0.85) and rgb[2]<(rgb[0]*0.7) and rgb[1]>(rgb[0]*0.4) and rgb[2]>(rgb[0]*0.2)]) + bad_color_val = float(skin)/float(im.size[0]*im.size[1]) + if bad_color_val > .4: + is_okay = False + else: + is_okay = True + return is_okay + + def run_tests(self): + image_is_okay = self.count_colors() and self.get_skin_ratio() + return image_is_okay + +class URLProperties(object): + def __init__(self, url_string): + self.url_string = url_string + + def check_if_parses(self): + success = False + try: + self.parsed_url = urlparse.urlparse(url_string) + success = True + except: + pass + + return success + + def check_suffix(self): + good_suffix = False + for suffix in ALLOWABLE_IMAGE_SUFFIXES: + if self.url_string.endswith(suffix) + good_suffix = True + break + return good_suffix + + def run_tests(self): + url_is_okay = self.check_suffix() and self.check_if_parses() + return url_is_okay + +def run_url_tests(url_string): + url_properties = URLProperties(url_string) + return url_properties.run_tests() + +def run_image_tests(image): + image_properties = ImageProperties(image) + return image_properties.run_tests() + + + From 4d1f9d2edf30f9585b1bfa3c8fba9ada2246251c Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 17:35:48 -0500 Subject: [PATCH 0317/1392] Function to upload stuff to S3 --- .../xmodule/open_ended_image_submission.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/common/lib/xmodule/xmodule/open_ended_image_submission.py b/common/lib/xmodule/xmodule/open_ended_image_submission.py index 13cee1f9e1..ae95914429 100644 --- a/common/lib/xmodule/xmodule/open_ended_image_submission.py +++ b/common/lib/xmodule/xmodule/open_ended_image_submission.py @@ -82,6 +82,27 @@ def run_image_tests(image): image_properties = ImageProperties(image) return image_properties.run_tests() +def upload_to_s3(string_to_upload, keyname): + ''' + Upload file to S3 using provided keyname. + + Returns: + public_url: URL to access uploaded file + ''' + try: + conn = S3Connection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY) + bucketname = str(AWS_STORAGE_BUCKET_NAME) + bucket = conn.create_bucket(bucketname.lower()) + + k = Key(bucket) + k.key = keyname + k.set_contents_from_string(string_to_upload) + public_url = k.generate_url(60*60*24*365) # URL timeout in seconds. + + return True, public_url + except: + return False, "Could not connect to S3." + From 9c5fe056898a391905063d28855ba5e19b0b06a6 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 18:30:49 -0500 Subject: [PATCH 0318/1392] Update reqs for pillow, work on file uploads --- .../xmodule/xmodule/combined_open_ended_module.py | 7 +++++-- .../js/src/combinedopenended/display.coffee | 4 ++++ .../xmodule/open_ended_image_submission.py | 15 ++++++++++++++- common/lib/xmodule/xmodule/open_ended_module.py | 1 + common/lib/xmodule/xmodule/openendedchild.py | 9 +++++++++ .../lib/xmodule/xmodule/self_assessment_module.py | 1 + lms/templates/open_ended.html | 2 ++ lms/templates/self_assessment_prompt.html | 3 ++- requirements.txt | 2 +- 9 files changed, 39 insertions(+), 5 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 66426bba28..90d55ae872 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -39,6 +39,7 @@ MAX_SCORE = 1 MAX_SCORE_ALLOWED = 3 IS_SCORED=False +UPLOAD_IMAGE = False class CombinedOpenEndedModule(XModule): """ @@ -141,6 +142,7 @@ class CombinedOpenEndedModule(XModule): self.allow_reset = instance_state.get('ready_to_reset', False) self.max_attempts = int(self.metadata.get('attempts', MAX_ATTEMPTS)) self.is_scored = (self.metadata.get('is_graded', IS_SCORED)=="True") + self.upload_image = (self.metadata.get('upload_image', UPLOAD_IMAGE)=="True") log.debug(self.metadata.get('is_graded', IS_SCORED)) @@ -173,7 +175,8 @@ class CombinedOpenEndedModule(XModule): 'max_attempts': self.max_attempts, 'prompt': definition['prompt'], 'rubric': definition['rubric'], - 'display_name': self.display_name + 'display_name': self.display_name, + 'accept_file_upload' : self.upload_image, } self.task_xml = definition['task_xml'] @@ -672,4 +675,4 @@ class CombinedOpenEndedDescriptor(XmlDescriptor, EditingDescriptor): for child in ['task']: add_child(child) - return elt + return elt \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee index 072a772c13..607978160f 100644 --- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee @@ -44,6 +44,7 @@ class @CombinedOpenEnded @skip_button = @$('.skip-button') @skip_button.click @skip_post_assessment + @file_upload_area = @$('.file-upload') @open_ended_child= @$('.open-ended-child') @find_assessment_elements() @@ -298,3 +299,6 @@ class @CombinedOpenEnded location.reload() else window.queuePollerID = window.setTimeout(@poll, 10000) + + setup_file_upload: => + @file_upload_area.html('') \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/open_ended_image_submission.py b/common/lib/xmodule/xmodule/open_ended_image_submission.py index ae95914429..cb7544f6f2 100644 --- a/common/lib/xmodule/xmodule/open_ended_image_submission.py +++ b/common/lib/xmodule/xmodule/open_ended_image_submission.py @@ -1,5 +1,10 @@ from PIL import Image import urlparse +import requests +from boto.s3.connection import S3Connection +from boto.s3.key import Key +from django.conf import settings +import pickle TRUSTED_IMAGE_DOMAINS = [ 'wikipedia.com', @@ -91,11 +96,12 @@ def upload_to_s3(string_to_upload, keyname): ''' try: conn = S3Connection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY) - bucketname = str(AWS_STORAGE_BUCKET_NAME) + bucketname = str(settings.AWS_STORAGE_BUCKET_NAME) bucket = conn.create_bucket(bucketname.lower()) k = Key(bucket) k.key = keyname + k.set_metadata("Content-Type", 'images/png') k.set_contents_from_string(string_to_upload) public_url = k.generate_url(60*60*24*365) # URL timeout in seconds. @@ -103,6 +109,13 @@ def upload_to_s3(string_to_upload, keyname): except: return False, "Could not connect to S3." +def get_from_s3(s3_public_url): + r = requests.get(s3_public_url, timeout=2) + data=r.text + return data + +def convert_image_to_string(image): + return image.tostring() diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index 28dedef0b6..5b6e6d4a4b 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -602,6 +602,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): 'msg': post_assessment, 'child_type': 'openended', 'correct': correct, + 'accept_file_upload' : self.accept_file_upload, } html = system.render_template('open_ended.html', context) return html diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index 7de5d9a626..7e8c5c4fdc 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -96,6 +96,7 @@ class OpenEndedChild(object): self.prompt = static_data['prompt'] self.rubric = static_data['rubric'] self.display_name = static_data['display_name'] + self.accept_file_upload = static_data['accept_file_upload'] # Used for progress / grading. Currently get credit just for # completion (doesn't matter if you self-assessed correct/incorrect). @@ -273,5 +274,13 @@ class OpenEndedChild(object): correctness = 'correct' if self.is_submission_correct(score) else 'incorrect' return correctness + def should_request_image(self): + """ + + @return: + """ + pass + + diff --git a/common/lib/xmodule/xmodule/self_assessment_module.py b/common/lib/xmodule/xmodule/self_assessment_module.py index fb1d306708..9893c14fe3 100644 --- a/common/lib/xmodule/xmodule/self_assessment_module.py +++ b/common/lib/xmodule/xmodule/self_assessment_module.py @@ -80,6 +80,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild): 'state': self.state, 'allow_reset': self._allow_reset(), 'child_type': 'selfassessment', + 'accept_file_upload' : self.accept_file_upload, } html = system.render_template('self_assessment_prompt.html', context) diff --git a/lms/templates/open_ended.html b/lms/templates/open_ended.html index f6c9f2f307..af08c16f1d 100644 --- a/lms/templates/open_ended.html +++ b/lms/templates/open_ended.html @@ -22,6 +22,8 @@ % endif +

+ diff --git a/lms/templates/self_assessment_prompt.html b/lms/templates/self_assessment_prompt.html index 2ec83ef2a7..50f5374750 100644 --- a/lms/templates/self_assessment_prompt.html +++ b/lms/templates/self_assessment_prompt.html @@ -16,6 +16,7 @@
${initial_hint}
${initial_message}
- + +
diff --git a/requirements.txt b/requirements.txt index fa4688b711..ded8f10915 100644 --- a/requirements.txt +++ b/requirements.txt @@ -48,7 +48,6 @@ sorl-thumbnail==11.12 networkx==1.7 pygraphviz==1.1 -r repo-requirements.txt -pil==1.1.7 nltk==2.0.4 django-debug-toolbar-mongo dogstatsd-python==0.2.1 @@ -59,3 +58,4 @@ Shapely==1.2.16 ipython==0.13.1 xmltodict==0.4.1 paramiko==1.9.0 +pillow From 01f218b7f82cbdda940ee15c4eca4d8ccc077ac6 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 21:36:55 -0500 Subject: [PATCH 0319/1392] Fix some tab issues from the rebase --- lms/djangoapps/courseware/tabs.py | 33 +++++++++++-------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 24fb36200c..62ebeae9d7 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -300,27 +300,16 @@ def get_static_tab_by_slug(course, tab_slug): return None +def get_static_tab_contents(request, cache, course, tab): -def get_static_tab_contents(course, tab): - """ - Given a course and a static tab config dict, load the tab contents, - returning None if not found. + loc = Location(course.location.tag, course.location.org, course.location.course, 'static_tab', tab['url_slug']) + tab_module = get_module(request.user, request, loc, cache, course.id) - Looks in tabs/{course_url_name}/{tab_slug}.html first, then tabs/{tab_slug}.html. - """ - slug = tab['url_slug'] - paths = ['tabs/{0}/{1}.html'.format(course.url_name, slug), - 'tabs/{0}.html'.format(slug)] - fs = course.system.resources_fs - for p in paths: - if fs.exists(p): - try: - with fs.open(p) as tabfile: - # TODO: redundant with module_render.py. Want to be helper methods in static_replace or something. - text = tabfile.read().decode('utf-8') - contents = replace_urls(text, course.metadata['data_dir']) - return replace_urls(contents, staticfiles_prefix='/courses/'+course.id, replace_prefix='/course/') - except (ResourceNotFoundError) as err: - log.exception("Couldn't load tab contents from '{0}': {1}".format(p, err)) - return None - return None + logging.debug('course_module = {0}'.format(tab_module)) + + html = '' + + if tab_module is not None: + html = tab_module.get_html() + + return html \ No newline at end of file From 08e06f87193672e7af96b80685060e5c4a8fcbd3 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 21:39:54 -0500 Subject: [PATCH 0320/1392] Fix some tab problems --- common/lib/xmodule/xmodule/combined_open_ended_module.py | 2 +- common/lib/xmodule/xmodule/openendedchild.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 90d55ae872..9cf768ff5c 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -176,7 +176,7 @@ class CombinedOpenEndedModule(XModule): 'prompt': definition['prompt'], 'rubric': definition['rubric'], 'display_name': self.display_name, - 'accept_file_upload' : self.upload_image, + 'accept_file_upload' : self.upload_image, } self.task_xml = definition['task_xml'] diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index 7e8c5c4fdc..43c3afb7f1 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -96,7 +96,7 @@ class OpenEndedChild(object): self.prompt = static_data['prompt'] self.rubric = static_data['rubric'] self.display_name = static_data['display_name'] - self.accept_file_upload = static_data['accept_file_upload'] + self.accept_file_upload = static_data['accept_file_upload'] # Used for progress / grading. Currently get credit just for # completion (doesn't matter if you self-assessed correct/incorrect). @@ -279,7 +279,7 @@ class OpenEndedChild(object): @return: """ - pass + pass From b730c25056b5cac9b5633eead2e1bfdf8672babc Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 21:51:48 -0500 Subject: [PATCH 0321/1392] Fix rubric rendering --- common/lib/xmodule/xmodule/combined_open_ended_rubric.py | 4 +++- common/lib/xmodule/xmodule/open_ended_module.py | 2 +- common/lib/xmodule/xmodule/self_assessment_module.py | 2 +- lms/djangoapps/open_ended_grading/grading_service.py | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py index 4380e32d5b..3159849643 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py @@ -23,15 +23,17 @@ class CombinedOpenEndedRubric(object): Output: html: the html that corresponds to the xml given ''' + success = False try: rubric_categories = self.extract_categories(rubric_xml) html = self.system.render_template('open_ended_rubric.html', {'categories' : rubric_categories, 'has_score': self.has_score, 'view_only': self.view_only}) + success = True except: raise RubricParsingError("[render_rubric] Could not parse the rubric with xml: {0}".format(rubric_xml)) - return html + return success, html def extract_categories(self, element): ''' diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index 5b6e6d4a4b..a3eeceb517 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -382,7 +382,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): feedback = self._convert_longform_feedback_to_html(response_items) if response_items['rubric_scores_complete']==True: rubric_renderer = CombinedOpenEndedRubric(system, True) - rubric_feedback = rubric_renderer.render_rubric(response_items['rubric_xml']) + success, rubric_feedback = rubric_renderer.render_rubric(response_items['rubric_xml']) if not response_items['success']: return system.render_template("open_ended_error.html", diff --git a/common/lib/xmodule/xmodule/self_assessment_module.py b/common/lib/xmodule/xmodule/self_assessment_module.py index 9893c14fe3..efc25f841b 100644 --- a/common/lib/xmodule/xmodule/self_assessment_module.py +++ b/common/lib/xmodule/xmodule/self_assessment_module.py @@ -124,7 +124,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild): return '' rubric_renderer = CombinedOpenEndedRubric(system, True) - rubric_html = rubric_renderer.render_rubric(self.rubric) + success, rubric_html = rubric_renderer.render_rubric(self.rubric) # we'll render it context = {'rubric': rubric_html, diff --git a/lms/djangoapps/open_ended_grading/grading_service.py b/lms/djangoapps/open_ended_grading/grading_service.py index f65554a9d6..63febb105f 100644 --- a/lms/djangoapps/open_ended_grading/grading_service.py +++ b/lms/djangoapps/open_ended_grading/grading_service.py @@ -116,7 +116,7 @@ class GradingService(object): if 'rubric' in response_json: rubric = response_json['rubric'] rubric_renderer = CombinedOpenEndedRubric(self.system, False) - rubric_html = rubric_renderer.render_rubric(rubric) + success, rubric_html = rubric_renderer.render_rubric(rubric) response_json['rubric'] = rubric_html return response_json # if we can't parse the rubric into HTML, From f367b7ace25dfc4d2cdf65d32c62465cb5b106d0 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 21:53:36 -0500 Subject: [PATCH 0322/1392] Change ruby version --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index e46f918393..dd472cffa2 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -1.8.7-p371 +1.8.7-p371 \ No newline at end of file From fbdc190a58cd39431931cf0a3216c9a2a28fc6cd Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 22:16:48 -0500 Subject: [PATCH 0323/1392] Add in file upload ability --- .../xmodule/combined_open_ended_module.py | 9 +++++---- .../js/src/combinedopenended/display.coffee | 18 +++++++++++++++++- lms/templates/combined_open_ended.html | 2 +- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 9cf768ff5c..d74657d923 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -39,7 +39,7 @@ MAX_SCORE = 1 MAX_SCORE_ALLOWED = 3 IS_SCORED=False -UPLOAD_IMAGE = False +ACCEPT_FILE_UPLOAD = False class CombinedOpenEndedModule(XModule): """ @@ -142,7 +142,7 @@ class CombinedOpenEndedModule(XModule): self.allow_reset = instance_state.get('ready_to_reset', False) self.max_attempts = int(self.metadata.get('attempts', MAX_ATTEMPTS)) self.is_scored = (self.metadata.get('is_graded', IS_SCORED)=="True") - self.upload_image = (self.metadata.get('upload_image', UPLOAD_IMAGE)=="True") + self.accept_file_upload = (self.metadata.get('accept_file_upload', ACCEPT_FILE_UPLOAD)=="True") log.debug(self.metadata.get('is_graded', IS_SCORED)) @@ -176,7 +176,7 @@ class CombinedOpenEndedModule(XModule): 'prompt': definition['prompt'], 'rubric': definition['rubric'], 'display_name': self.display_name, - 'accept_file_upload' : self.upload_image, + 'accept_file_upload' : self.accept_file_upload, } self.task_xml = definition['task_xml'] @@ -327,7 +327,8 @@ class CombinedOpenEndedModule(XModule): 'task_count': len(self.task_xml), 'task_number': self.current_task_number + 1, 'status': self.get_status(), - 'display_name': self.display_name + 'display_name': self.display_name , + 'accept_file_upload' : self.accept_file_upload, } return context diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee index 607978160f..9d8ee96b91 100644 --- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee @@ -12,6 +12,7 @@ class @CombinedOpenEnded @state = @el.data('state') @task_count = @el.data('task-count') @task_number = @el.data('task-number') + @accept_file_upload = @el.data('accept-file-upload') @allow_reset = @el.data('allow_reset') @reset_button = @$('.reset-button') @@ -45,6 +46,7 @@ class @CombinedOpenEnded @skip_button.click @skip_post_assessment @file_upload_area = @$('.file-upload') + @can_upload_files = false @open_ended_child= @$('.open-ended-child') @find_assessment_elements() @@ -119,6 +121,7 @@ class @CombinedOpenEnded @submit_button.show() @reset_button.hide() @next_problem_button.hide() + @hide_file_upload() @hint_area.attr('disabled', false) if @child_state == 'done' @rubric_wrapper.hide() @@ -134,8 +137,10 @@ class @CombinedOpenEnded @answer_area.attr("disabled", false) @submit_button.prop('value', 'Submit') @submit_button.click @save_answer + @setup_file_upload() else if @child_state == 'assessing' @answer_area.attr("disabled", true) + @hide_file_upload() @submit_button.prop('value', 'Submit assessment') @submit_button.click @save_assessment if @child_type == "openended" @@ -301,4 +306,15 @@ class @CombinedOpenEnded window.queuePollerID = window.setTimeout(@poll, 10000) setup_file_upload: => - @file_upload_area.html('') \ No newline at end of file + if window.File and window.FileReader and window.FileList and window.Blob + alert('File API supported.') + if @accept_file_upload == "True" + @can_upload_files = true + @file_upload_area.html('') + @file_upload_area.show() + else + @gentle_alert 'File uploads are not supported in this browser. Try the newest version of google chrome' + + hide_file_upload: => + if @accept_file_upload == "True" + @file_upload_area.hide() \ No newline at end of file diff --git a/lms/templates/combined_open_ended.html b/lms/templates/combined_open_ended.html index c99ebe21d1..4599feaa3b 100644 --- a/lms/templates/combined_open_ended.html +++ b/lms/templates/combined_open_ended.html @@ -1,4 +1,4 @@ -
+

${display_name}

From 0622dc995d9d9fdfe257dc1911a37187875d9ca5 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 29 Jan 2013 22:42:08 -0500 Subject: [PATCH 0324/1392] Javascript to handle file uploads --- .../lib/xmodule/xmodule/combined_open_ended_module.py | 6 +++--- common/lib/xmodule/xmodule/js/src/capa/display.coffee | 10 +++++----- .../xmodule/js/src/combinedopenended/display.coffee | 7 +++++-- common/lib/xmodule/xmodule/self_assessment_module.py | 1 + 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index d74657d923..1ed57fa844 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -39,7 +39,7 @@ MAX_SCORE = 1 MAX_SCORE_ALLOWED = 3 IS_SCORED=False -ACCEPT_FILE_UPLOAD = False +ACCEPT_FILE_UPLOAD = True class CombinedOpenEndedModule(XModule): """ @@ -141,8 +141,8 @@ class CombinedOpenEndedModule(XModule): #Allow reset is true if student has failed the criteria to move to the next child task self.allow_reset = instance_state.get('ready_to_reset', False) self.max_attempts = int(self.metadata.get('attempts', MAX_ATTEMPTS)) - self.is_scored = (self.metadata.get('is_graded', IS_SCORED)=="True") - self.accept_file_upload = (self.metadata.get('accept_file_upload', ACCEPT_FILE_UPLOAD)=="True") + self.is_scored = (self.metadata.get('is_graded', IS_SCORED) in [True, "True"]) + self.accept_file_upload = (self.metadata.get('accept_file_upload', ACCEPT_FILE_UPLOAD) in [True, "True"]) log.debug(self.metadata.get('is_graded', IS_SCORED)) diff --git a/common/lib/xmodule/xmodule/js/src/capa/display.coffee b/common/lib/xmodule/xmodule/js/src/capa/display.coffee index 1c0ace9e59..5890686c0e 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/capa/display.coffee @@ -140,15 +140,15 @@ class @Problem allowed_files = $(element).data("allowed_files") for file in element.files if allowed_files.length != 0 and file.name not in allowed_files - unallowed_file_submitted = true - errors.push "You submitted #{file.name}; only #{allowed_files} are allowed." + unallowed_file_submitted = true + errors.push "You submitted #{file.name}; only #{allowed_files} are allowed." if file.name in required_files - required_files.splice(required_files.indexOf(file.name), 1) + required_files.splice(required_files.indexOf(file.name), 1) if file.size > max_filesize file_too_large = true errors.push 'Your file "' + file.name '" is too large (max size: ' + max_filesize/(1000*1000) + ' MB)' fd.append(element.id, file) - if element.files.length == 0 + if element.files.length == 0 file_not_selected = true fd.append(element.id, '') # In case we want to allow submissions with no file if required_files.length != 0 @@ -157,7 +157,7 @@ class @Problem else fd.append(element.id, element.value) - + if file_not_selected errors.push 'You did not select any files to submit' diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee index 9d8ee96b91..5c307f664e 100644 --- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee @@ -179,7 +179,11 @@ class @CombinedOpenEnded save_answer: (event) => event.preventDefault() if @child_state == 'initial' - data = {'student_answer' : @answer_area.val()} + file_data = "" + if @can_upload_files == true + files = $('.file-upload-box')[0].files[0] + file_data = files + data = {'student_answer' : @answer_area.val(), 'file_data' : file_data} $.postWithPrefix "#{@ajax_url}/save_answer", data, (response) => if response.success @rubric_wrapper.html(response.rubric_html) @@ -307,7 +311,6 @@ class @CombinedOpenEnded setup_file_upload: => if window.File and window.FileReader and window.FileList and window.Blob - alert('File API supported.') if @accept_file_upload == "True" @can_upload_files = true @file_upload_area.html('') diff --git a/common/lib/xmodule/xmodule/self_assessment_module.py b/common/lib/xmodule/xmodule/self_assessment_module.py index efc25f841b..96fc4a3c86 100644 --- a/common/lib/xmodule/xmodule/self_assessment_module.py +++ b/common/lib/xmodule/xmodule/self_assessment_module.py @@ -107,6 +107,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild): if dispatch not in handlers: return 'Error' + log.debug(get) before = self.get_progress() d = handlers[dispatch](get, system) after = self.get_progress() From d06f5f779135cc6e7abb58be09e5d2ed8894671e Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 09:02:04 -0500 Subject: [PATCH 0325/1392] Fix file upload stuff, debug some image check routines --- .../js/src/combinedopenended/display.coffee | 41 +++++++++++++------ .../xmodule/open_ended_image_submission.py | 6 +-- common/lib/xmodule/xmodule/openendedchild.py | 6 ++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee index 5c307f664e..88957e3cab 100644 --- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee @@ -178,21 +178,38 @@ class @CombinedOpenEnded save_answer: (event) => event.preventDefault() + max_filesize = 2*1000*1000 #2MB if @child_state == 'initial' - file_data = "" + files = "" if @can_upload_files == true files = $('.file-upload-box')[0].files[0] - file_data = files - data = {'student_answer' : @answer_area.val(), 'file_data' : file_data} - $.postWithPrefix "#{@ajax_url}/save_answer", data, (response) => - if response.success - @rubric_wrapper.html(response.rubric_html) - @rubric_wrapper.show() - @child_state = 'assessing' - @find_assessment_elements() - @rebind() - else - @errors_area.html(response.error) + if files.size > max_filesize + @can_upload_files = false + files = "" + + fd = new FormData() + fd.append('student_answer', @answer_area.val()) + fd.append('student_file', files) + fd.append('can_upload_files', files) + + #data = {'student_answer' : @answer_area.val(), 'file_value' : file_value, 'file_id' : file_id} + settings = + type: "POST" + data: fd + processData: false + contentType: false + success: (response) => + if response.success + @rubric_wrapper.html(response.rubric_html) + @rubric_wrapper.show() + @child_state = 'assessing' + @find_assessment_elements() + @rebind() + else + @errors_area.html(response.error) + + $.ajaxWithPrefix("#{@ajax_url}/save_answer",settings) + else @errors_area.html('Problem state got out of sync. Try reloading the page.') diff --git a/common/lib/xmodule/xmodule/open_ended_image_submission.py b/common/lib/xmodule/xmodule/open_ended_image_submission.py index cb7544f6f2..7c605e9ebe 100644 --- a/common/lib/xmodule/xmodule/open_ended_image_submission.py +++ b/common/lib/xmodule/xmodule/open_ended_image_submission.py @@ -70,9 +70,9 @@ class URLProperties(object): def check_suffix(self): good_suffix = False for suffix in ALLOWABLE_IMAGE_SUFFIXES: - if self.url_string.endswith(suffix) - good_suffix = True - break + if self.url_string.endswith(suffix): + good_suffix = True + break return good_suffix def run_tests(self): diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index 43c3afb7f1..0e28676099 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -23,6 +23,7 @@ from .stringify import stringify_children from .xml_module import XmlDescriptor from xmodule.modulestore import Location from capa.util import * +import open_ended_image_submission from datetime import datetime @@ -274,12 +275,13 @@ class OpenEndedChild(object): correctness = 'correct' if self.is_submission_correct(score) else 'incorrect' return correctness - def should_request_image(self): + def upload_image_to_s3(self, image_data): """ @return: """ - pass + success = False + image_ok = run_image_checks(image) From d132f2e18a628caf972e58b4e6be1bd1ab93e3ee Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Mon, 28 Jan 2013 15:05:04 -0500 Subject: [PATCH 0326/1392] Only put data repos in STATICFILES_DIRS if we're serving them from django (which is only in dev) --- lms/envs/common.py | 20 +------------------- lms/envs/dev.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/lms/envs/common.py b/lms/envs/common.py index 16472795e0..a2d9614109 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -266,24 +266,6 @@ STATICFILES_DIRS = [ COMMON_ROOT / "static", PROJECT_ROOT / "static", ] -if os.path.isdir(DATA_DIR): - # Add the full course repo if there is no static directory - STATICFILES_DIRS += [ - # TODO (cpennington): When courses are stored in a database, this - # should no longer be added to STATICFILES - (course_dir, DATA_DIR / course_dir) - for course_dir in os.listdir(DATA_DIR) - if (os.path.isdir(DATA_DIR / course_dir) and - not os.path.isdir(DATA_DIR / course_dir / 'static')) - ] - # Otherwise, add only the static directory from the course dir - STATICFILES_DIRS += [ - # TODO (cpennington): When courses are stored in a database, this - # should no longer be added to STATICFILES - (course_dir, DATA_DIR / course_dir / 'static') - for course_dir in os.listdir(DATA_DIR) - if (os.path.isdir(DATA_DIR / course_dir / 'static')) - ] # Locale/Internationalization TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name @@ -468,7 +450,7 @@ PIPELINE_JS = { 'source_filenames': sorted( set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.coffee') + rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.coffee')) - - set(courseware_js + discussion_js + staff_grading_js + peer_grading_js) + set(courseware_js + discussion_js + staff_grading_js + peer_grading_js) ) + [ 'js/form.ext.js', 'js/my_courses_dropdown.js', diff --git a/lms/envs/dev.py b/lms/envs/dev.py index 99ee9662ee..338a31f641 100644 --- a/lms/envs/dev.py +++ b/lms/envs/dev.py @@ -106,6 +106,27 @@ VIRTUAL_UNIVERSITIES = [] COMMENTS_SERVICE_KEY = "PUT_YOUR_API_KEY_HERE" +############################## Course static files ########################## +if os.path.isdir(DATA_DIR): + # Add the full course repo if there is no static directory + STATICFILES_DIRS += [ + # TODO (cpennington): When courses are stored in a database, this + # should no longer be added to STATICFILES + (course_dir, DATA_DIR / course_dir) + for course_dir in os.listdir(DATA_DIR) + if (os.path.isdir(DATA_DIR / course_dir) and + not os.path.isdir(DATA_DIR / course_dir / 'static')) + ] + # Otherwise, add only the static directory from the course dir + STATICFILES_DIRS += [ + # TODO (cpennington): When courses are stored in a database, this + # should no longer be added to STATICFILES + (course_dir, DATA_DIR / course_dir / 'static') + for course_dir in os.listdir(DATA_DIR) + if (os.path.isdir(DATA_DIR / course_dir / 'static')) + ] + + ################################# mitx revision string ##################### MITX_VERSION_STRING = os.popen('cd %s; git describe' % REPO_ROOT).read().strip() From 89f984c08be3747e27e2ea3a2345839c6ee2c24e Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 29 Jan 2013 13:48:07 -0500 Subject: [PATCH 0327/1392] Prefix courseware urls with /static, since they are no longer served through collectstatic --- cms/djangoapps/contentstore/views.py | 2 +- lms/djangoapps/courseware/module_render.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index 816ccab091..cc26510534 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -527,7 +527,7 @@ def load_preview_module(request, preview_id, descriptor, instance_state, shared_ module.get_html = replace_static_urls( module.get_html, - module.metadata.get('data_dir', module.location.course), + '/static/' + module.metadata.get('data_dir', module.location.course), course_namespace = Location([module.location.tag, module.location.org, module.location.course, None, None]) ) save_preview_state(request, preview_id, descriptor.location.url(), diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 7ed32c8597..a641f6e94c 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -280,7 +280,7 @@ def _get_module(user, request, descriptor, student_module_cache, course_id, module.get_html = replace_static_urls( _get_html, - module.metadata['data_dir'] if 'data_dir' in module.metadata else '', + '/static/' + module.metadata['data_dir'] if 'data_dir' in module.metadata else '', course_namespace = module.location._replace(category=None, name=None)) # Allow URLs of the form '/course/' refer to the root of multicourse directory From 95f2c9e275108f7045df67c33e45b88a9b37718e Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 29 Jan 2013 14:20:01 -0500 Subject: [PATCH 0328/1392] Standardize how static urls are replaced by modules in their own html --- common/lib/xmodule/xmodule/capa_module.py | 4 ++-- lms/djangoapps/courseware/module_render.py | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index e4ab804f49..688737d883 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -355,7 +355,7 @@ class CapaModule(XModule): id=self.location.html_id(), ajax_url=self.system.ajax_url) + html + "
" # now do the substitutions which are filesystem based, e.g. '/static/' prefixes - return self.system.replace_urls(html, self.metadata['data_dir'], course_namespace=self.location) + return self.system.replace_urls(html) def handle_ajax(self, dispatch, get): ''' @@ -460,7 +460,7 @@ class CapaModule(XModule): new_answers = dict() for answer_id in answers: try: - new_answer = {answer_id: self.system.replace_urls(answers[answer_id], self.metadata['data_dir'], course_namespace=self.location)} + new_answer = {answer_id: self.system.replace_urls(answers[answer_id])} except TypeError: log.debug('Unable to perform URL substitution on answers[%s]: %s' % (answer_id, answers[answer_id])) new_answer = {answer_id: answers[answer_id]} diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index a641f6e94c..23dbc8c8a6 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -244,7 +244,11 @@ def _get_module(user, request, descriptor, student_module_cache, course_id, # TODO (cpennington): This should be removed when all html from # a module is coming through get_html and is therefore covered # by the replace_static_urls code below - replace_urls=replace_urls, + replace_urls=partial( + replace_urls, + staticfiles_prefix='/static/' + module.metadata.get('data_dir', ''), + course_namespace=module.location._replace(category=None, name=None), + ), node_path=settings.NODE_PATH, anonymous_student_id=unique_id_for_user(user), course_id=course_id, @@ -280,7 +284,7 @@ def _get_module(user, request, descriptor, student_module_cache, course_id, module.get_html = replace_static_urls( _get_html, - '/static/' + module.metadata['data_dir'] if 'data_dir' in module.metadata else '', + '/static/' + module.metadata.get('data_dir', ''), course_namespace = module.location._replace(category=None, name=None)) # Allow URLs of the form '/course/' refer to the root of multicourse directory From 9ae83338c627af75ed18d9894be265ba9a82c5b6 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 29 Jan 2013 14:20:21 -0500 Subject: [PATCH 0329/1392] Whitespace cleanup --- cms/djangoapps/contentstore/views.py | 136 +++++++++++----------- common/lib/xmodule/xmodule/capa_module.py | 6 +- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index cc26510534..9331e97fec 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -132,7 +132,7 @@ def has_access(user, location, role=STAFF_ROLE_NAME): Return True if user allowed to access this piece of data Note that the CMS permissions model is with respect to courses There is a super-admin permissions if user.is_staff is set - Also, since we're unifying the user database between LMS and CAS, + Also, since we're unifying the user database between LMS and CAS, I'm presuming that the course instructor (formally known as admin) will not be in both INSTRUCTOR and STAFF groups, so we have to cascade our queries here as INSTRUCTOR has all the rights that STAFF do @@ -154,7 +154,7 @@ def course_index(request, org, course, name): org, course, name: Attributes of the Location for the item to edit """ location = ['i4x', org, course, 'course', name] - + # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() @@ -213,7 +213,7 @@ def edit_subsection(request, location): # remove all metadata from the generic dictionary that is presented in a more normalized UI - policy_metadata = dict((key,value) for key, value in item.metadata.iteritems() + policy_metadata = dict((key,value) for key, value in item.metadata.iteritems() if key not in ['display_name', 'start', 'due', 'format'] and key not in item.system_metadata_fields) can_view_live = False @@ -292,7 +292,7 @@ def edit_unit(request, location): containing_section = modulestore().get_item(containing_section_locs[0]) # cdodge hack. We're having trouble previewing drafts via jump_to redirect - # so let's generate the link url here + # so let's generate the link url here # need to figure out where this item is in the list of children as the preview will need this index =1 @@ -303,12 +303,12 @@ def edit_unit(request, location): preview_lms_link = '//{preview}{lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}'.format( preview='preview.', - lms_base=settings.LMS_BASE, + lms_base=settings.LMS_BASE, org=course.location.org, - course=course.location.course, - course_name=course.location.name, - section=containing_section.location.name, - subsection=containing_subsection.location.name, + course=course.location.course, + course_name=course.location.name, + section=containing_section.location.name, + subsection=containing_subsection.location.name, index=index) unit_state = compute_unit_state(item) @@ -359,14 +359,14 @@ def assignment_type_update(request, org, course, category, name): location = Location(['i4x', org, course, category, name]) if not has_access(request.user, location): raise HttpResponseForbidden() - + if request.method == 'GET': - return HttpResponse(json.dumps(CourseGradingModel.get_section_grader_type(location)), + return HttpResponse(json.dumps(CourseGradingModel.get_section_grader_type(location)), mimetype="application/json") elif request.method == 'POST': # post or put, doesn't matter. - return HttpResponse(json.dumps(CourseGradingModel.update_section_grader_type(location, request.POST)), + return HttpResponse(json.dumps(CourseGradingModel.update_section_grader_type(location, request.POST)), mimetype="application/json") - + def user_author_string(user): '''Get an author string for commits by this user. Format: @@ -511,20 +511,20 @@ def load_preview_module(request, preview_id, descriptor, instance_state, shared_ error_msg=exc_info_to_str(sys.exc_info()) ).xmodule_constructor(system)(None, None) - # cdodge: Special case + # cdodge: Special case if module.location.category == 'static_tab': module.get_html = wrap_xmodule( module.get_html, module, "xmodule_tab_display.html", ) - else: + else: module.get_html = wrap_xmodule( module.get_html, module, "xmodule_display.html", ) - + module.get_html = replace_static_urls( module.get_html, '/static/' + module.metadata.get('data_dir', module.location.course), @@ -555,7 +555,7 @@ def _xmodule_recurse(item, action): _xmodule_recurse(child, action) action(item) - + @login_required @expect_json @@ -590,7 +590,7 @@ def delete_item(request): # delete_item on a vertical tries to delete the draft version leaving the # requested delete to never occur if item.location.revision is None and item.location.category=='vertical' and delete_all_versions: - modulestore('direct').delete_item(item.location) + modulestore('direct').delete_item(item.location) return HttpResponse() @@ -609,7 +609,7 @@ def save_item(request): if request.POST.get('data') is not None: data = request.POST['data'] store.update_item(item_location, data) - + # cdodge: note calling request.POST.get('children') will return None if children is an empty array # so it lead to a bug whereby the last component to be deleted in the UI was not actually # deleting the children object from the children collection @@ -699,7 +699,7 @@ def unpublish_unit(request): def clone_item(request): parent_location = Location(request.POST['parent_location']) template = Location(request.POST['template']) - + display_name = request.POST.get('display_name') if not has_access(request.user, parent_location): @@ -739,9 +739,9 @@ def upload_asset(request, org, course, coursename): location = ['i4x', org, course, 'course', coursename] if not has_access(request.user, location): return HttpResponseForbidden() - + # Does the course actually exist?!? Get anything from it to prove its existance - + try: item = modulestore().get_item(location) except: @@ -775,9 +775,9 @@ def upload_asset(request, org, course, coursename): # readback the saved content - we need the database timestamp readback = contentstore().find(content.location) - - response_payload = {'displayname' : content.name, - 'uploadDate' : get_date_display(readback.last_modified_at), + + response_payload = {'displayname' : content.name, + 'uploadDate' : get_date_display(readback.last_modified_at), 'url' : StaticContent.get_url_path_from_location(content.location), 'thumb_url' : StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_content is not None else None, 'msg' : 'Upload completed' @@ -793,7 +793,7 @@ This view will return all CMS users who are editors for the specified course @login_required @ensure_csrf_cookie def manage_users(request, location): - + # check that logged in user has permissions to this item if not has_access(request.user, location, role=INSTRUCTOR_ROLE_NAME) and not has_access(request.user, location, role=STAFF_ROLE_NAME): raise PermissionDenied() @@ -809,7 +809,7 @@ def manage_users(request, location): 'allow_actions' : has_access(request.user, location, role=INSTRUCTOR_ROLE_NAME), 'request_user_id' : request.user.id }) - + def create_json_response(errmsg = None): if errmsg is not None: @@ -831,13 +831,13 @@ def add_user(request, location): if email=='': return create_json_response('Please specify an email address.') - + # check that logged in user has admin permissions to this course if not has_access(request.user, location, role=INSTRUCTOR_ROLE_NAME): raise PermissionDenied() - + user = get_user_by_email(email) - + # user doesn't exist?!? Return error. if user is None: return create_json_response('Could not find user by email address \'{0}\'.'.format(email)) @@ -860,7 +860,7 @@ the specified course @ensure_csrf_cookie def remove_user(request, location): email = request.POST["email"] - + # check that logged in user has admin permissions on this course if not has_access(request.user, location, role=INSTRUCTOR_ROLE_NAME): raise PermissionDenied() @@ -887,7 +887,7 @@ def landing(request, org, course, coursename): def static_pages(request, org, course, coursename): location = ['i4x', org, course, 'course', coursename] - + # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() @@ -906,7 +906,7 @@ def edit_static(request, org, course, coursename): @login_required @ensure_csrf_cookie def edit_tabs(request, org, course, coursename): - location = ['i4x', org, course, 'course', coursename] + location = ['i4x', org, course, 'course', coursename] course_item = modulestore().get_item(location) static_tabs_loc = Location('i4x', org, course, 'static_tab', None) @@ -928,7 +928,7 @@ def edit_tabs(request, org, course, coursename): return render_to_response('edit-tabs.html', { 'active_tab': 'pages', - 'context_course':course_item, + 'context_course':course_item, 'components': components }) @@ -949,13 +949,13 @@ def course_info(request, org, course, name, provided_id=None): org, course, name: Attributes of the Location for the item to edit """ location = ['i4x', org, course, 'course', name] - + # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() - + course_module = modulestore().get_item(location) - + # get current updates location = ['i4x', org, course, 'course_info', "updates"] @@ -966,7 +966,7 @@ def course_info(request, org, course, name, provided_id=None): 'course_updates' : json.dumps(get_course_updates(location)), 'handouts_location': Location(['i4x', org, course, 'course_info', 'handouts']).url() }) - + @expect_json @login_required @ensure_csrf_cookie @@ -980,7 +980,7 @@ def course_info_updates(request, org, course, provided_id=None): # ??? No way to check for access permission afaik # get current updates location = ['i4x', org, course, 'course_info', "updates"] - + # Hmmm, provided_id is coming as empty string on create whereas I believe it used to be None :-( # Possibly due to my removing the seemingly redundant pattern in urls.py if provided_id == '': @@ -995,7 +995,7 @@ def course_info_updates(request, org, course, provided_id=None): real_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE'] else: real_method = request.method - + if request.method == 'GET': return HttpResponse(json.dumps(get_course_updates(location)), mimetype="application/json") elif real_method == 'DELETE': # coming as POST need to pull from Request Header X-HTTP-Method-Override DELETE @@ -1012,7 +1012,7 @@ def course_info_updates(request, org, course, provided_id=None): @ensure_csrf_cookie def module_info(request, module_location): location = Location(module_location) - + # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() @@ -1025,10 +1025,10 @@ def module_info(request, module_location): rewrite_static_links = request.GET.get('rewrite_url_links','True') in ['True', 'true'] logging.debug('rewrite_static_links = {0} {1}'.format(request.GET.get('rewrite_url_links','False'), rewrite_static_links)) - + # check that logged in user has permissions to this item if not has_access(request.user, location): - raise PermissionDenied() + raise PermissionDenied() if real_method == 'GET': return HttpResponse(json.dumps(get_module_info(get_modulestore(location), location, rewrite_static_links=rewrite_static_links)), mimetype="application/json") @@ -1046,20 +1046,20 @@ def get_course_settings(request, org, course, name): org, course, name: Attributes of the Location for the item to edit """ location = ['i4x', org, course, 'course', name] - + # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() - + course_module = modulestore().get_item(location) course_details = CourseDetails.fetch(location) - + return render_to_response('settings.html', { - 'active_tab': 'settings', + 'active_tab': 'settings', 'context_course': course_module, 'course_details' : json.dumps(course_details, cls=CourseSettingsEncoder) }) - + @expect_json @login_required @ensure_csrf_cookie @@ -1082,13 +1082,13 @@ def course_settings_updates(request, org, course, name, section): elif section == 'grading': manager = CourseGradingModel else: return - + if request.method == 'GET': # Cannot just do a get w/o knowing the course name :-( - return HttpResponse(json.dumps(manager.fetch(Location(['i4x', org, course, 'course',name])), cls=CourseSettingsEncoder), + return HttpResponse(json.dumps(manager.fetch(Location(['i4x', org, course, 'course',name])), cls=CourseSettingsEncoder), mimetype="application/json") elif request.method == 'POST': # post or put, doesn't matter. - return HttpResponse(json.dumps(manager.update_from_json(request.POST), cls=CourseSettingsEncoder), + return HttpResponse(json.dumps(manager.update_from_json(request.POST), cls=CourseSettingsEncoder), mimetype="application/json") @expect_json @@ -1101,7 +1101,7 @@ def course_grader_updates(request, org, course, name, grader_index=None): org, course: Attributes of the Location for the item to edit """ - + location = ['i4x', org, course, 'course', name] # check that logged in user has permissions to this item @@ -1112,13 +1112,13 @@ def course_grader_updates(request, org, course, name, grader_index=None): real_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE'] else: real_method = request.method - + if real_method == 'GET': # Cannot just do a get w/o knowing the course name :-( - return HttpResponse(json.dumps(CourseGradingModel.fetch_grader(Location(['i4x', org, course, 'course',name]), grader_index)), + return HttpResponse(json.dumps(CourseGradingModel.fetch_grader(Location(['i4x', org, course, 'course',name]), grader_index)), mimetype="application/json") elif real_method == "DELETE": - # ??? Shoudl this return anything? Perhaps success fail? + # ??? Shoudl this return anything? Perhaps success fail? CourseGradingModel.delete_grader(Location(['i4x', org, course, 'course',name]), grader_index) return HttpResponse() elif request.method == 'POST': # post or put, doesn't matter. @@ -1135,7 +1135,7 @@ def asset_index(request, org, course, name): org, course, name: Attributes of the Location for the item to edit """ location = ['i4x', org, course, 'course', name] - + # check that logged in user has permissions to this item if not has_access(request.user, location): raise PermissionDenied() @@ -1148,7 +1148,7 @@ def asset_index(request, org, course, name): }) course_module = modulestore().get_item(location) - + course_reference = StaticContent.compute_location(org, course, name) assets = contentstore().get_all_content_for_course(course_reference) @@ -1162,15 +1162,15 @@ def asset_index(request, org, course, name): display_info = {} display_info['displayname'] = asset['displayname'] display_info['uploadDate'] = get_date_display(asset['uploadDate']) - + asset_location = StaticContent.compute_location(id['org'], id['course'], id['name']) display_info['url'] = StaticContent.get_url_path_from_location(asset_location) - + # note, due to the schema change we may not have a 'thumbnail_location' in the result set _thumbnail_location = asset.get('thumbnail_location', None) thumbnail_location = Location(_thumbnail_location) if _thumbnail_location is not None else None display_info['thumb_url'] = StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None - + asset_display.append(display_info) return render_to_response('asset_index.html', { @@ -1189,9 +1189,9 @@ def edge(request): @expect_json def create_new_course(request): template = Location(request.POST['template']) - org = request.POST.get('org') - number = request.POST.get('number') - display_name = request.POST.get('display_name') + org = request.POST.get('org') + number = request.POST.get('number') + display_name = request.POST.get('display_name') try: dest_location = Location('i4x', org, number, 'course', Location.clean(display_name)) @@ -1237,13 +1237,13 @@ def initialize_course_tabs(course): # at least a list populated with the minimal times # @TODO: I don't like the fact that the presentation tier is away of these data related constraints, let's find a better # place for this. Also rather than using a simple list of dictionaries a nice class model would be helpful here - course.tabs = [{"type": "courseware"}, - {"type": "course_info", "name": "Course Info"}, + course.tabs = [{"type": "courseware"}, + {"type": "course_info", "name": "Course Info"}, {"type": "discussion", "name": "Discussion"}, {"type": "wiki", "name": "Wiki"}, {"type": "progress", "name": "Progress"}] - modulestore('direct').update_metadata(course.location.url(), course.own_metadata) + modulestore('direct').update_metadata(course.location.url(), course.own_metadata) @ensure_csrf_cookie @login_required @@ -1337,7 +1337,7 @@ def generate_export_course(request, org, course, name): root_dir = path(mkdtemp()) # export out to a tempdir - + logging.debug('root = {0}'.format(root_dir)) export_to_xml(modulestore('direct'), contentstore(), loc, root_dir, name) @@ -1349,7 +1349,7 @@ def generate_export_course(request, org, course, name): tf.close() # remove temp dir - shutil.rmtree(root_dir/name) + shutil.rmtree(root_dir/name) wrapper = FileWrapper(export_file) response = HttpResponse(wrapper, content_type='application/x-tgz') diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 688737d883..3947945beb 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -668,18 +668,18 @@ class CapaDescriptor(RawDescriptor): # TODO (vshnayder): do problems have any other metadata? Do they # actually use type and points? metadata_attributes = RawDescriptor.metadata_attributes + ('type', 'points') - + def get_context(self): _context = RawDescriptor.get_context(self) _context.update({'markdown': self.metadata.get('markdown', '')}) return _context - + @property def editable_metadata_fields(self): """Remove metadata from the editable fields since it has its own editor""" subset = super(CapaDescriptor,self).editable_metadata_fields if 'markdown' in subset: - subset.remove('markdown') + subset.remove('markdown') return subset From e773b8e7b126718fbc8040148ef2455790f913c4 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 29 Jan 2013 14:22:39 -0500 Subject: [PATCH 0330/1392] Fix import error --- lms/djangoapps/courseware/module_render.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 23dbc8c8a6..064fdf1210 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -3,6 +3,8 @@ import logging import pyparsing import sys +from functools import partial + from django.conf import settings from django.contrib.auth.models import User from django.core.urlresolvers import reverse From 07487a8d8f5124d5cfaa16b58b488769f7c42ac2 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 29 Jan 2013 14:27:27 -0500 Subject: [PATCH 0331/1392] Use descriptor when setting up replace_urls, as it's been created at that point --- lms/djangoapps/courseware/module_render.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 064fdf1210..22d95ef8a2 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -248,8 +248,8 @@ def _get_module(user, request, descriptor, student_module_cache, course_id, # by the replace_static_urls code below replace_urls=partial( replace_urls, - staticfiles_prefix='/static/' + module.metadata.get('data_dir', ''), - course_namespace=module.location._replace(category=None, name=None), + staticfiles_prefix='/static/' + descriptor.metadata.get('data_dir', ''), + course_namespace=descriptor.location._replace(category=None, name=None), ), node_path=settings.NODE_PATH, anonymous_student_id=unique_id_for_user(user), From 2854d7d06695a9ead9920f90678cf3807c64644f Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 29 Jan 2013 16:21:46 -0500 Subject: [PATCH 0332/1392] Point course_image.jpg at the correct place in the /static url space --- lms/djangoapps/courseware/courses.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 89a1496eca..03d5a89c64 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -83,13 +83,12 @@ def get_opt_course_with_access(user, course_id, action): return None return get_course_with_access(user, course_id, action) - + def course_image_url(course): """Try to look up the image url for the course. If it's not found, log an error and return the dead link""" if isinstance(modulestore(), XMLModuleStore): - path = course.metadata['data_dir'] + "/images/course_image.jpg" - return try_staticfiles_lookup(path) + return '/static/' + course.metadata['data_dir'] + "/images/course_image.jpg" else: loc = course.location._replace(tag='c4x', category='asset', name='images_course_image.jpg') path = StaticContent.get_url_path_from_location(loc) From 3c1c61fb19ea96c1ed51e9b274c29cb5f0252c27 Mon Sep 17 00:00:00 2001 From: cahrens Date: Wed, 30 Jan 2013 09:23:07 -0500 Subject: [PATCH 0333/1392] Fixes for https://edx.lighthouseapp.com/projects/102637/tickets/144 (progress tab not updating). --- lms/djangoapps/courseware/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index 8c529a8585..5d65d7c632 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -233,7 +233,7 @@ def index(request, course_id, chapter=None, section=None, # Specifically asked-for section doesn't exist raise Http404 - # Load all descendants of the section, because we're going to display it's + # Load all descendants of the section, because we're going to display its # html, which in general will need all of its children section_module_cache = StudentModuleCache.cache_for_descriptor_descendents( course.id, request.user, section_descriptor, depth=None) From ce8a48405b958575add205fcc73d77ca5a4ace8a Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 30 Jan 2013 09:31:20 -0500 Subject: [PATCH 0334/1392] Clean up some JS errors showing up in the xmodule jasmine tests --- common/lib/xmodule/jasmine_test_runner.html.erb | 1 - common/lib/xmodule/xmodule/js/spec/helper.coffee | 1 - 2 files changed, 2 deletions(-) diff --git a/common/lib/xmodule/jasmine_test_runner.html.erb b/common/lib/xmodule/jasmine_test_runner.html.erb index fae6c14cbe..7b078daedd 100644 --- a/common/lib/xmodule/jasmine_test_runner.html.erb +++ b/common/lib/xmodule/jasmine_test_runner.html.erb @@ -14,7 +14,6 @@ - diff --git a/common/lib/xmodule/xmodule/js/spec/helper.coffee b/common/lib/xmodule/xmodule/js/spec/helper.coffee index dc01241861..fbc89f7bd9 100644 --- a/common/lib/xmodule/xmodule/js/spec/helper.coffee +++ b/common/lib/xmodule/xmodule/js/spec/helper.coffee @@ -64,7 +64,6 @@ jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) -> if createPlayer return new VideoPlayer(video: context.video) -spyOn(window, 'onunload') # Stub jQuery.cookie $.cookie = jasmine.createSpy('jQuery.cookie').andReturn '1.0' From 4df62d968d9ad1f8b2f364e958d264cf469aa7ad Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 30 Jan 2013 09:31:42 -0500 Subject: [PATCH 0335/1392] Fix up new jasmine tests --- .../js/spec/combinedopenended/display_spec.coffee | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee index 3ccf504948..02aaa50103 100644 --- a/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee @@ -1,16 +1,15 @@ -xdescribe 'CombinedOpenEnded', -> +describe 'CombinedOpenEnded', -> beforeEach -> spyOn Logger, 'log' # load up some fixtures loadFixtures 'combined-open-ended.html' @element = $('.combined-open-ended') - describe 'constructor', -> - beforeEach -> - @combined = new CombinedOpenEnded @element - it 'set the element', -> - except(@combined.element).not.toEqual @element + describe 'constructor', -> + beforeEach -> + @combined = new CombinedOpenEnded @element + it 'set the element', -> + expect(@combined.element).toEqual @element - #it 'initialize the ajax url, state, and task count', -> From 0c0a8971271e8527940537f37655799602c011a0 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 09:36:01 -0500 Subject: [PATCH 0336/1392] Work on uploading image submission to S3 --- .../xmodule/open_ended_image_submission.py | 6 ++--- common/lib/xmodule/xmodule/openendedchild.py | 23 ++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/open_ended_image_submission.py b/common/lib/xmodule/xmodule/open_ended_image_submission.py index 7c605e9ebe..6d089607a3 100644 --- a/common/lib/xmodule/xmodule/open_ended_image_submission.py +++ b/common/lib/xmodule/xmodule/open_ended_image_submission.py @@ -87,7 +87,7 @@ def run_image_tests(image): image_properties = ImageProperties(image) return image_properties.run_tests() -def upload_to_s3(string_to_upload, keyname): +def upload_to_s3(file_to_upload, keyname): ''' Upload file to S3 using provided keyname. @@ -101,8 +101,8 @@ def upload_to_s3(string_to_upload, keyname): k = Key(bucket) k.key = keyname - k.set_metadata("Content-Type", 'images/png') - k.set_contents_from_string(string_to_upload) + k.set_metadata('filename', file_to_upload.name) + k.set_contents_from_file(file_to_upload) public_url = k.generate_url(60*60*24*365) # URL timeout in seconds. return True, public_url diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index 0e28676099..ff966dd445 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -27,6 +27,8 @@ import open_ended_image_submission from datetime import datetime +from PIL import Image + log = logging.getLogger("mitx.courseware") # Set the default number of max attempts. Should be 1 for production @@ -281,7 +283,26 @@ class OpenEndedChild(object): @return: """ success = False - image_ok = run_image_checks(image) + image = Image.open(image_data) + + try: + image_ok = open_ended_image_submission.run_image_tests(image) + success = True + except: + pass + + if success: + image_key = image_data.name + datetime.now().strftime("%Y%m%d%H%M%S") + + try: + success, public_url = open_ended_image_submission.upload_to_s3(image_data, image_key) + success = True + except: + pass + + + + From ab4fd03dd8c5b42afcaa0258e27d51245d613671 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Wed, 30 Jan 2013 09:43:27 -0500 Subject: [PATCH 0337/1392] Catch any and all save errors --- .../js/models/settings/course_details.js | 12 +++++- .../js/views/settings/main_settings_view.js | 38 +++++++++++++++---- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js index ab80179142..61e31133fd 100644 --- a/cms/static/js/models/settings/course_details.js +++ b/cms/static/js/models/settings/course_details.js @@ -68,10 +68,18 @@ CMS.Models.Settings.CourseDetails = Backbone.Model.extend({ save_videosource: function(newsource) { // newsource either is
- % if view_only:
${option['text']} diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 5c6cec17eb..b9d263867c 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -17,6 +17,10 @@ from courseware.access import has_access from util.json_request import expect_json from xmodule.course_module import CourseDescriptor from student.models import unique_id_for_user +from xmodule.x_module import ModuleSystem +from mitxmako.shortcuts import render_to_string +from capa import inputtypes +from lxml import etree log = logging.getLogger(__name__) @@ -136,6 +140,8 @@ class StaffGradingService(GradingService): # importing this file doesn't create objects that may not have the right config _service = None +module_system = ModuleSystem("", None, None, render_to_string, None) + def staff_grading_service(): """ Return a staff grading service instance--if settings.MOCK_STAFF_GRADING is True, @@ -252,12 +258,24 @@ def _get_next(course_id, grader_id, location): Implementation of get_next (also called from save_grade) -- returns a json string """ try: - return staff_grading_service().get_next(course_id, location, grader_id) + response = staff_grading_service().get_next(course_id, location, grader_id) + response_json = json.loads(response) + rubric = response_json['rubric'] + rubric_input = inputtypes.RubricInput(module_system, etree.XML(rubric), {'id': location}) + rubric_html = etree.tostring(rubric_input.get_html()) + response_json['rubric'] = rubric_html + return json.dumps(response_json) except GradingServiceError: log.exception("Error from grading service. server url: {0}" .format(staff_grading_service().url)) return json.dumps({'success': False, 'error': 'Could not connect to grading service'}) + # if we can't parse the rubric into HTML, + except etree.XMLSyntaxError: + log.exception("Cannot parse rubric string. Raw string: {0}" + .format(rubric)) + return json.dumps({'success': False, + 'error': 'Error displaying submission'}) @expect_json diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index 7039fd1358..26d604756a 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -42,14 +42,49 @@ class StaffGradingBackend The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham. ''' rubric: ''' -
    -
  • Metals tend to be good electronic conductors, meaning that they have a large number of electrons which are able to access empty (mobile) energy states within the material.
  • -
  • Sodium has a half-filled s-band, so there are a number of empty states immediately above the highest occupied energy levels within the band.
  • -
  • Magnesium has a full s-band, but the the s-band and p-band overlap in magnesium. Thus are still a large number of available energy states immediately above the s-band highest occupied energy level.
  • -
- -

Please score your response according to how many of the above components you identified:

- ''' + + + + + + + + + + + + + + + + + + +
Purpose + + + + + + + + + + + +
Organization + + + + + + + + + + + +
''' submission_id: @mock_cnt max_score: 2 + @mock_cnt % 3 ml_error_info : 'ML accuracy info: ' + @mock_cnt @@ -166,8 +201,8 @@ class StaffGrading @min_for_ml = 0 @num_graded = 0 @num_pending = 0 + @score_lst = [] - @score = null @problems = null # action handlers @@ -181,31 +216,36 @@ class StaffGrading setup_score_selection: => - # first, get rid of all the old inputs, if any. - @score_selection_container.html('Choose score: ') + @score_selection_container.html(@rubric) + $('.score-selection').click => @graded_callback() - # Now create new labels and inputs for each possible score. - for score in [0..@max_score] - id = 'score-' + score - label = """""" + graded_callback: () => + # check to see whether or not any categories have not been scored + num_categories = $('table.rubric tr').length + for i in [0..(num_categories-1)] + score = $("input[name='score-selection-#{i}']:checked").val() + if score == undefined + return + # show button if we have scores for all categories + @submit_button.show() - input = """ - - """ # " fix broken parsing in emacs - @score_selection_container.append(input + label) - # And now hook up an event handler again - $("input[name='score-selection']").change @graded_callback - set_button_text: (text) => @action_button.attr('value', text) - graded_callback: (event) => - @score = event.target.value - @state = state_graded - @message = '' - @render_view() + # finds the scores for each rubric category + get_score_list: () => + # find the number of categories: + num_categories = $('table.rubric tr').length + + score_lst = [] + # get the score for each one + for i in [0..(num_categories-1)] + score = $("input[name='score-selection-#{i}']:checked").val() + score_lst.append(score) + + return score_lst ajax_callback: (response) => # always clear out errors and messages on transition. @@ -231,7 +271,7 @@ class StaffGrading skip_and_get_next: () => data = - score: @score + rubric_scores: @get_score_list() feedback: @feedback_area.val() submission_id: @submission_id location: @location @@ -244,7 +284,7 @@ class StaffGrading submit_and_get_next: () -> data = - score: @score + rubric_scores: @get_score_list() feedback: @feedback_area.val() submission_id: @submission_id location: @location @@ -261,8 +301,6 @@ class StaffGrading @rubric = response.rubric @submission_id = response.submission_id @feedback_area.val('') - @max_score = response.max_score - @score = null @ml_error_info=response.ml_error_info @prompt_name = response.problem_name @num_graded = response.num_graded @@ -282,8 +320,6 @@ class StaffGrading @ml_error_info = null @submission_id = null @message = message - @score = null - @max_score = 0 @state = state_no_data @@ -361,8 +397,6 @@ class StaffGrading @prompt_container.html(@prompt) @prompt_name_container.html("#{@prompt_name}") @submission_container.html(@make_paragraphs(@submission)) - @rubric_container.html(@rubric) - # no submit button until user picks grade. show_submit_button = false show_action_button = false @@ -397,7 +431,7 @@ class StaffGrading # for now, just create an instance and load it... -mock_backend = false +mock_backend = true ajax_url = $('.staff-grading').data('ajax_url') backend = new StaffGradingBackend(ajax_url, mock_backend) diff --git a/lms/static/sass/course/_staff_grading.scss b/lms/static/sass/course/_staff_grading.scss index 92fa760d4a..edcd16b350 100644 --- a/lms/static/sass/course/_staff_grading.scss +++ b/lms/static/sass/course/_staff_grading.scss @@ -159,5 +159,50 @@ div.peer-grading{ } } padding: 40px; + .rubric { + tr { + margin:10px 0px; + height: 100%; + } + td { + padding: 20px 0px; + margin: 10px 0px; + height: 100%; + } + th { + padding: 5px; + margin: 5px; + } + label, + .view-only { + margin:3px; + position: relative; + padding: 15px; + width: 150px; + height:100%; + display: inline-block; + min-height: 50px; + min-width: 50px; + background-color: #CCC; + font-size: .9em; + } + .grade { + position: absolute; + bottom:0px; + right:0px; + margin:10px; + } + .selected-grade { + background: #666; + color: white; + } + input[type=radio]:checked + label { + background: #666; + color: white; } + input[class='score-selection'] { + display: none; + } + } + } diff --git a/lms/templates/instructor/staff_grading.html b/lms/templates/instructor/staff_grading.html index 085480a332..3749a63e73 100644 --- a/lms/templates/instructor/staff_grading.html +++ b/lms/templates/instructor/staff_grading.html @@ -54,11 +54,6 @@
-
-

Grading Rubric

-
-
-
From a0c0005e959f13716501f5cbc43c268c855ea0c7 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 14 Jan 2013 08:58:33 -0500 Subject: [PATCH 0008/1392] Updates to the javascript and the grading controller to handle rubric input --- .../open_ended_grading/staff_grading_service.py | 10 ++++++---- .../coffee/src/staff_grading/staff_grading.coffee | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index b9d263867c..3591ff8bed 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -115,7 +115,7 @@ class StaffGradingService(GradingService): 'grader_id': grader_id}) - def save_grade(self, course_id, grader_id, submission_id, score, feedback, skipped): + def save_grade(self, course_id, grader_id, submission_id, score, feedback, skipped, rubric_scores): """ Save a score and feedback for a submission. @@ -132,7 +132,8 @@ class StaffGradingService(GradingService): 'score': score, 'feedback': feedback, 'grader_id': grader_id, - 'skipped': skipped} + 'skipped': skipped, + 'rubric_scores': rubric_scores} return self.post(self.save_grade_url, data=data) @@ -297,7 +298,7 @@ def save_grade(request, course_id): if request.method != 'POST': raise Http404 - required = set(['score', 'feedback', 'submission_id', 'location']) + required = set(['score', 'feedback', 'submission_id', 'location', 'rubric_scores']) actual = set(request.POST.keys()) missing = required - actual if len(missing) > 0: @@ -316,7 +317,8 @@ def save_grade(request, course_id): p['submission_id'], p['score'], p['feedback'], - skipped) + skipped, + p['rubric_scores']) except GradingServiceError: log.exception("Error saving grade") return _err_response('Could not connect to grading service') diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index 26d604756a..fa405eac88 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -227,6 +227,7 @@ class StaffGrading if score == undefined return # show button if we have scores for all categories + @state = state_graded @submit_button.show() @@ -243,7 +244,7 @@ class StaffGrading # get the score for each one for i in [0..(num_categories-1)] score = $("input[name='score-selection-#{i}']:checked").val() - score_lst.append(score) + score_lst.push(score) return score_lst @@ -431,7 +432,7 @@ class StaffGrading # for now, just create an instance and load it... -mock_backend = true +mock_backend = false ajax_url = $('.staff-grading').data('ajax_url') backend = new StaffGradingBackend(ajax_url, mock_backend) From 1680336da615881f3c57e29ad692eafcf729ab73 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 14 Jan 2013 10:22:22 -0500 Subject: [PATCH 0009/1392] Fix some minor bugs in the staff grading interface --- common/lib/capa/capa/templates/rubricinput.html | 2 +- .../open_ended_grading/staff_grading_service.py | 8 +++++--- lms/static/coffee/src/staff_grading/staff_grading.coffee | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/common/lib/capa/capa/templates/rubricinput.html b/common/lib/capa/capa/templates/rubricinput.html index 1780603d91..051b9fe0e0 100644 --- a/common/lib/capa/capa/templates/rubricinput.html +++ b/common/lib/capa/capa/templates/rubricinput.html @@ -2,7 +2,7 @@

Rubric

% if view_only:

Select the criteria you feel best represents this submission in each category.

- % else + % else:

The highlighted selection best matches how the student feels you performed in each category.

% endif diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 3591ff8bed..9727336791 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -133,7 +133,8 @@ class StaffGradingService(GradingService): 'feedback': feedback, 'grader_id': grader_id, 'skipped': skipped, - 'rubric_scores': rubric_scores} + 'rubric_scores': rubric_scores, + 'rubric_scores_complete': True} return self.post(self.save_grade_url, data=data) @@ -298,7 +299,7 @@ def save_grade(request, course_id): if request.method != 'POST': raise Http404 - required = set(['score', 'feedback', 'submission_id', 'location', 'rubric_scores']) + required = set(['score', 'feedback', 'submission_id', 'location', 'rubric_scores[]']) actual = set(request.POST.keys()) missing = required - actual if len(missing) > 0: @@ -311,6 +312,7 @@ def save_grade(request, course_id): location = p['location'] skipped = 'skipped' in p + try: result_json = staff_grading_service().save_grade(course_id, grader_id, @@ -318,7 +320,7 @@ def save_grade(request, course_id): p['score'], p['feedback'], skipped, - p['rubric_scores']) + p.getlist('rubric_scores[]')) except GradingServiceError: log.exception("Error saving grade") return _err_response('Could not connect to grading service') diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index fa405eac88..d8fcb087a6 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -286,6 +286,7 @@ class StaffGrading submit_and_get_next: () -> data = rubric_scores: @get_score_list() + score: 0 feedback: @feedback_area.val() submission_id: @submission_id location: @location From 90c39d51eef89da393409dafda21ea9f87603bb9 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 14 Jan 2013 10:39:20 -0500 Subject: [PATCH 0010/1392] Fix wrong order in the text --- common/lib/capa/capa/templates/rubricinput.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/lib/capa/capa/templates/rubricinput.html b/common/lib/capa/capa/templates/rubricinput.html index 051b9fe0e0..19e67a30c1 100644 --- a/common/lib/capa/capa/templates/rubricinput.html +++ b/common/lib/capa/capa/templates/rubricinput.html @@ -1,9 +1,9 @@

Rubric

% if view_only: -

Select the criteria you feel best represents this submission in each category.

+

The highlighted selection matches how the grader feels you performed in each category.

% else: -

The highlighted selection best matches how the student feels you performed in each category.

+

Select the criteria you feel best represents this submission in each category.

% endif
% for i in range(len(categories)): From cc4095807f1b62721d8311a1f87f2545c4b5a9de Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 14 Jan 2013 13:38:44 -0500 Subject: [PATCH 0011/1392] Handle scores if they exist in the xml --- common/lib/capa/capa/inputtypes.py | 27 ++++++++++++++----- .../lib/capa/capa/templates/rubricinput.html | 19 ++++++++----- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index 826eb69e6c..3a953f25f3 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -796,6 +796,7 @@ class RubricInput(InputTypeBase): submitted_msg = ("Feedback not yet available. Reload to check again. " "Once the problem is graded, this message will be " "replaced with the grader's feedback.") + has_score = False @classmethod def get_attributes(cls): @@ -811,14 +812,14 @@ class RubricInput(InputTypeBase): Add in the various bits and pieces that we need """ return {'categories': self.categories, - 'view_only': False} + 'view_only': False, + 'has_score': self.has_score} def setup(self): # set the categories self.categories = self.extract_categories(self.xml) - @staticmethod - def extract_categories(element): + def extract_categories(self, element): ''' Contstruct a list of categories such that the structure looks like: [ { category: "Category 1 Name", @@ -835,12 +836,11 @@ class RubricInput(InputTypeBase): if category.tag != 'category': raise Exception("[capa.inputtypes.extract_categories] Expected a tag: got {0} instead".format(category.tag)) else: - categories.append(RubricInput.extract_category(category)) + categories.append(self.extract_category(category)) return categories - @staticmethod - def extract_category(category): + def extract_category(self, category): ''' construct an individual category {category: "Category 1 Name", @@ -851,6 +851,17 @@ class RubricInput(InputTypeBase): ''' descriptionxml = category[0] optionsxml = category[1:] + scorexml = category[1] + score = None + if scorexml.tag == 'score': + score_text = scorexml.text + optionsxml = category[2:] + score = int(score_text) + self.has_score = True + # if we are missing the score tag and we are expecting one + elif self.has_score: + raise Exception("[inputtypes.extract_category] Category {0} is missing a score".format(descriptionxml.text)) + # parse description if descriptionxml.tag != 'description': @@ -880,8 +891,10 @@ class RubricInput(InputTypeBase): cur_points = cur_points + 1 else: raise Exception("[extract_category]: missing points attribute. Cannot continue to auto-create points values after a points value is explicitly dfined.") + + selected = score == points optiontext = option.text - options.append({'text': option.text, 'points': points}) + options.append({'text': option.text, 'points': points, 'selected': selected}) # sort and check for duplicates options = sorted(options, key=lambda option: option['points']) diff --git a/common/lib/capa/capa/templates/rubricinput.html b/common/lib/capa/capa/templates/rubricinput.html index 19e67a30c1..3ad5f64958 100644 --- a/common/lib/capa/capa/templates/rubricinput.html +++ b/common/lib/capa/capa/templates/rubricinput.html @@ -1,7 +1,9 @@

Rubric

- % if view_only: -

The highlighted selection matches how the grader feels you performed in each category.

+ % if view_only and has_score: +

This is the rubric that was used to grade your submission.The highlighted selection matches how the grader feels you performed in each category.

+ % elif view_only: +

Use the below rubric to rate this submission.

% else:

Select the criteria you feel best represents this submission in each category.

% endif @@ -14,10 +16,15 @@ <% option = category['options'][j] %>
' + - ''); + '' + + ''); + var current_cohort_id = cohort_id; + $(".name", tr).text(item.name); $(".username", tr).text(item.username); $(".email", tr).text(item.email); + + $(".remove", tr).html('remove') + .click(function() { + remove_user_from_cohort(item.username, current_cohort_id, tr); + }); + detail_users.append(tr); }; @@ -145,7 +166,12 @@ var CohortManager = (function ($) { function adder(note, color) { return function(item) { var li = $('
  • ') - li.text(note + ' ' + item.name + ', ' + item.username + ', ' + item.email); + if (typeof item === "object") { + li.text(note + ' ' + item.name + ', ' + item.username + ', ' + item.email); + } else { + // string + li.text(note + ' ' + item); + } li.css('color', color); op_results.append(li); } @@ -153,7 +179,7 @@ var CohortManager = (function ($) { if (response && response.success) { response.added.forEach(adder("Added", "green")); response.present.forEach(adder("Already present:", "black")); - response.unknown.forEach(adder("Already present:", "red")); + response.unknown.forEach(adder("Unknown user:", "red")); } else { log_error(response.msg || "There was an error adding users"); } diff --git a/lms/templates/course_groups/cohort_management.html b/lms/templates/course_groups/cohort_management.html index 962d4de645..579d6fa48d 100644 --- a/lms/templates/course_groups/cohort_management.html +++ b/lms/templates/course_groups/cohort_management.html @@ -29,7 +29,7 @@

    Add users by username or email. One per line or comma-separated.

    - + Add cohort members
    % if view_only: -
    - ${option['text']} -
    [${option['points']} points]
    -
    + ## if this is the selected rubric block, show it + % if option['selected']: +
    + % else: +
    + % endif + ${option['text']} +
    [${option['points']} points]
    +
    % else: From bb867ba3b49f14b5d904c9f83bb820b375318318 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 14 Jan 2013 14:46:44 -0500 Subject: [PATCH 0012/1392] Use the new CombinedOpenEndedRubric class for everything related to rubric rendering. Remove the old input type. --- common/lib/capa/capa/inputtypes.py | 139 ------------------ .../lib/capa/capa/templates/rubricinput.html | 37 ----- .../xmodule/combined_open_ended_rubric.py | 83 +++++------ .../staff_grading_service.py | 7 +- lms/templates/open_ended_rubric.html | 61 ++++---- 5 files changed, 78 insertions(+), 249 deletions(-) delete mode 100644 common/lib/capa/capa/templates/rubricinput.html diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index b805084ce4..1d3646fefc 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -735,142 +735,3 @@ class ChemicalEquationInput(InputTypeBase): registry.register(ChemicalEquationInput) #----------------------------------------------------------------------------- - -class RubricInput(InputTypeBase): - """ - This is the logic for parsing and displaying a rubric of type - """ - - template = "rubricinput.html" - tags = ['rubric'] - - # pulled out for testing - submitted_msg = ("Feedback not yet available. Reload to check again. " - "Once the problem is graded, this message will be " - "replaced with the grader's feedback.") - has_score = False - - @classmethod - def get_attributes(cls): - """ - Convert options to a convenient format. - """ - return [ - Attribute('height', None), - Attribute('width', None)] - - def _extra_context(self): - """ - Add in the various bits and pieces that we need - """ - return {'categories': self.categories, - 'view_only': False, - 'has_score': self.has_score} - - def setup(self): - # set the categories - self.categories = self.extract_categories(self.xml) - - def extract_categories(self, element): - ''' - Contstruct a list of categories such that the structure looks like: - [ { category: "Category 1 Name", - options: [{text: "Option 1 Name", points: 0}, {text:"Option 2 Name", points: 5}] - }, - { category: "Category 2 Name", - options: [{text: "Option 1 Name", points: 0}, - {text: "Option 2 Name", points: 1}, - {text: "Option 3 Name", points: 2]}] - - ''' - categories = [] - for category in element: - if category.tag != 'category': - raise Exception("[capa.inputtypes.extract_categories] Expected a tag: got {0} instead".format(category.tag)) - else: - categories.append(self.extract_category(category)) - return categories - - - def extract_category(self, category): - ''' - construct an individual category - {category: "Category 1 Name", - options: [{text: "Option 1 text", points: 1}, - {text: "Option 2 text", points: 2}]} - - all sorting and auto-point generation occurs in this function - ''' - descriptionxml = category[0] - optionsxml = category[1:] - scorexml = category[1] - score = None - if scorexml.tag == 'score': - score_text = scorexml.text - optionsxml = category[2:] - score = int(score_text) - self.has_score = True - # if we are missing the score tag and we are expecting one - elif self.has_score: - raise Exception("[inputtypes.extract_category] Category {0} is missing a score".format(descriptionxml.text)) - - - # parse description - if descriptionxml.tag != 'description': - raise Exception("[extract_category]: expected description tag, got {0} instead".format(descriptionxml.tag)) - - description = descriptionxml.text - - cur_points = 0 - options = [] - autonumbering = True - # parse options - for option in optionsxml: - if option.tag != 'option': - raise Exception("[extract_category]: expected option tag, got {0} instead".format(option.tag)) - else: - pointstr = option.get("points") - if pointstr: - autonumbering = False - # try to parse this into an int - try: - points = int(pointstr) - except ValueError: - raise Exception("[extract_category]: expected points to have int, got {0} instead".format(pointstr)) - elif autonumbering: - # use the generated one if we're in the right mode - points = cur_points - cur_points = cur_points + 1 - else: - raise Exception("[extract_category]: missing points attribute. Cannot continue to auto-create points values after a points value is explicitly dfined.") - - selected = score == points - optiontext = option.text - options.append({'text': option.text, 'points': points, 'selected': selected}) - - # sort and check for duplicates - options = sorted(options, key=lambda option: option['points']) - RubricInput.validate_options(options) - - return {'description': description, 'options': options} - - @staticmethod - def validate_options(options): - ''' - Validates a set of options. This can and should be extended to filter out other bad edge cases - ''' - if len(options) == 0: - raise Exception("[extract_category]: no options associated with this category") - if len(options) == 1: - return - prev = options[0]['points'] - for option in options[1:]: - if prev == option['points']: - raise Exception("[extract_category]: found duplicate point values between two different options") - else: - prev = option['points'] - - -registry.register(RubricInput) - -#----------------------------------------------------------------------------- diff --git a/common/lib/capa/capa/templates/rubricinput.html b/common/lib/capa/capa/templates/rubricinput.html deleted file mode 100644 index 3ad5f64958..0000000000 --- a/common/lib/capa/capa/templates/rubricinput.html +++ /dev/null @@ -1,37 +0,0 @@ - -

    Rubric

    - % if view_only and has_score: -

    This is the rubric that was used to grade your submission.The highlighted selection matches how the grader feels you performed in each category.

    - % elif view_only: -

    Use the below rubric to rate this submission.

    - % else: -

    Select the criteria you feel best represents this submission in each category.

    - % endif - - % for i in range(len(categories)): - <% category = categories[i] %> - - - % for j in range(len(category['options'])): - <% option = category['options'][j] %> - - % endfor - - % endfor -
    ${category['description']} - % if view_only: - ## if this is the selected rubric block, show it - % if option['selected']: -
    - % else: -
    - % endif - ${option['text']} -
    [${option['points']} points]
    -
    - % else: - - - % endif -
    - diff --git a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py index 0b2ca1ca2c..a9fd027ddf 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py @@ -6,41 +6,48 @@ log=logging.getLogger(__name__) class CombinedOpenEndedRubric: - @staticmethod - def render_rubric(rubric_xml): + def __init__ (self, view_only = False): + self.has_score = False + self.view_only = view_only + + def render_rubric(self, rubric_xml): try: - rubric_categories = CombinedOpenEndedRubric.extract_rubric_categories(rubric_xml) - html = render_to_string('open_ended_rubric.html', {'rubric_categories' : rubric_categories}) + rubric_categories = self.extract_categories(rubric_xml) + html = render_to_string('open_ended_rubric.html', + {'categories' : rubric_categories, + 'has_score': self.has_score, + 'view_only': self.view_only}) except: log.exception("Could not parse the rubric.") - html = rubric_xml + html = etree.tostring(rubric_xml, pretty_print=True) return html - @staticmethod - def extract_rubric_categories(element): + def extract_categories(self, element): ''' Contstruct a list of categories such that the structure looks like: [ { category: "Category 1 Name", options: [{text: "Option 1 Name", points: 0}, {text:"Option 2 Name", points: 5}] }, { category: "Category 2 Name", - options: [{text: "Option 1 Name", points: 0}, - {text: "Option 2 Name", points: 1}, + options: [{text: "Option 1 Name", points: 0}, + {text: "Option 2 Name", points: 1}, {text: "Option 3 Name", points: 2]}] ''' - element = etree.fromstring(element) + if element.tag != 'rubric': + raise Exception("[extract_categories] Expected a tag: got {0} instead".format(element.tag)) + categorylist = list(element) categories = [] - for category in element: + for category in categorylist: if category.tag != 'category': - raise Exception("[capa.inputtypes.extract_categories] Expected a tag: got {0} instead".format(category.tag)) + raise Exception("[extract_categories] Expected a tag: got {0} instead".format(category.tag)) else: - categories.append(CombinedOpenEndedRubric.extract_category(category)) + categories.append(self.extract_category(category)) return categories - @staticmethod - def extract_category(category): - ''' + + def extract_category(self, category): + ''' construct an individual category {category: "Category 1 Name", options: [{text: "Option 1 text", points: 1}, @@ -48,41 +55,32 @@ class CombinedOpenEndedRubric: all sorting and auto-point generation occurs in this function ''' - - has_score=False descriptionxml = category[0] + optionsxml = category[1:] scorexml = category[1] - if scorexml.tag == "option": - optionsxml = category[1:] - else: + score = None + if scorexml.tag == 'score': + score_text = scorexml.text optionsxml = category[2:] - has_score=True + score = int(score_text) + self.has_score = True + # if we are missing the score tag and we are expecting one + elif self.has_score: + raise Exception("[extract_category] Category {0} is missing a score".format(descriptionxml.text)) + # parse description if descriptionxml.tag != 'description': raise Exception("[extract_category]: expected description tag, got {0} instead".format(descriptionxml.tag)) - if has_score: - if scorexml.tag != 'score': - raise Exception("[extract_category]: expected score tag, got {0} instead".format(scorexml.tag)) - - for option in optionsxml: - if option.tag != "option": - raise Exception("[extract_category]: expected option tag, got {0} instead".format(option.tag)) - description = descriptionxml.text - if has_score: - score = int(scorexml.text) - else: - score = 0 - cur_points = 0 options = [] autonumbering = True # parse options for option in optionsxml: - if option.tag != 'option': + if option.tag != 'option': raise Exception("[extract_category]: expected option tag, got {0} instead".format(option.tag)) else: pointstr = option.get("points") @@ -99,18 +97,17 @@ class CombinedOpenEndedRubric: cur_points = cur_points + 1 else: raise Exception("[extract_category]: missing points attribute. Cannot continue to auto-create points values after a points value is explicitly dfined.") + + selected = score == points optiontext = option.text - selected = False - if has_score: - if points == score: - selected = True - options.append({'text': option.text, 'points': points, 'selected' : selected}) + options.append({'text': option.text, 'points': points, 'selected': selected}) # sort and check for duplicates options = sorted(options, key=lambda option: option['points']) CombinedOpenEndedRubric.validate_options(options) - return {'description': description, 'options': options, 'score' : score, 'has_score' : has_score} + return {'description': description, 'options': options} + @staticmethod def validate_options(options): @@ -126,4 +123,4 @@ class CombinedOpenEndedRubric: if prev == option['points']: raise Exception("[extract_category]: found duplicate point values between two different options") else: - prev = option['points'] \ No newline at end of file + prev = option['points'] diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 9727336791..feb5add72e 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -19,7 +19,7 @@ from xmodule.course_module import CourseDescriptor from student.models import unique_id_for_user from xmodule.x_module import ModuleSystem from mitxmako.shortcuts import render_to_string -from capa import inputtypes +from xmodule.combined_open_ended_rubric import CombinedOpenEndedRubric from lxml import etree log = logging.getLogger(__name__) @@ -263,8 +263,9 @@ def _get_next(course_id, grader_id, location): response = staff_grading_service().get_next(course_id, location, grader_id) response_json = json.loads(response) rubric = response_json['rubric'] - rubric_input = inputtypes.RubricInput(module_system, etree.XML(rubric), {'id': location}) - rubric_html = etree.tostring(rubric_input.get_html()) + rubric_renderer = CombinedOpenEndedRubric(False) + rubric_xml = etree.XML(rubric) + rubric_html = rubric_renderer.render_rubric(rubric_xml) response_json['rubric'] = rubric_html return json.dumps(response_json) except GradingServiceError: diff --git a/lms/templates/open_ended_rubric.html b/lms/templates/open_ended_rubric.html index 9f8a2ece4e..3ad5f64958 100644 --- a/lms/templates/open_ended_rubric.html +++ b/lms/templates/open_ended_rubric.html @@ -1,30 +1,37 @@ - - % for i in range(len(rubric_categories)): - <% category = rubric_categories[i] %> - - - % for j in range(len(category['options'])): - <% option = category['options'][j] %> -
    - ${category['description']} - % if category['has_score'] == True: - (Your score: ${category['score']}) - % endif - -
    - ${option['text']} - % if option.has_key('selected'): - % if option['selected'] == True: -
    [${option['points']} points]
    - %else: -
    [${option['points']} points]
    +
    +

    Rubric

    + % if view_only and has_score: +

    This is the rubric that was used to grade your submission.The highlighted selection matches how the grader feels you performed in each category.

    + % elif view_only: +

    Use the below rubric to rate this submission.

    + % else: +

    Select the criteria you feel best represents this submission in each category.

    + % endif + + % for i in range(len(categories)): + <% category = categories[i] %> + + + % for j in range(len(category['options'])): + <% option = category['options'][j] %> + + + + % endif + + % endfor + % endfor - - % endfor -
    ${category['description']} + % if view_only: + ## if this is the selected rubric block, show it + % if option['selected']: +
    + % else: +
    % endif + ${option['text']} +
    [${option['points']} points]
    +
    % else: -
    [${option['points']} points]
    - %endif -
    -
    \ No newline at end of file +
    + From 79c8efcb689825e9d00b972c833d25dd36a66c67 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 14 Jan 2013 15:02:24 -0500 Subject: [PATCH 0013/1392] Update the rubric renderer --- .../xmodule/xmodule/combined_open_ended_rubric.py | 15 +++++++++++---- common/lib/xmodule/xmodule/open_ended_module.py | 3 ++- .../lib/xmodule/xmodule/self_assessment_module.py | 4 +++- .../open_ended_grading/staff_grading_service.py | 3 +-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py index a9fd027ddf..4861a15dbc 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py @@ -10,6 +10,15 @@ class CombinedOpenEndedRubric: self.has_score = False self.view_only = view_only + ''' + render_rubric: takes in an xml string and outputs the corresponding + html for that xml, given the type of rubric we're generating + Input: + rubric_xml: an string that has not been parsed into xml that + represents this particular rubric + Output: + html: the html that corresponds to the xml given + ''' def render_rubric(self, rubric_xml): try: rubric_categories = self.extract_categories(rubric_xml) @@ -34,11 +43,9 @@ class CombinedOpenEndedRubric: {text: "Option 3 Name", points: 2]}] ''' - if element.tag != 'rubric': - raise Exception("[extract_categories] Expected a tag: got {0} instead".format(element.tag)) - categorylist = list(element) + element = etree.fromstring(element) categories = [] - for category in categorylist: + for category in element: if category.tag != 'category': raise Exception("[extract_categories] Expected a tag: got {0} instead".format(category.tag)) else: diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index 11f96c9848..4033d140dd 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -382,7 +382,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild): rubric_feedback="" feedback = self._convert_longform_feedback_to_html(response_items) if response_items['rubric_scores_complete']==True: - rubric_feedback = CombinedOpenEndedRubric.render_rubric(response_items['rubric_xml']) + rubric_renderer = CombinedOpenEndedRubric(True) + rubric_feedback = rubric_renderer.render_rubric(response_items['rubric_xml']) if not response_items['success']: return system.render_template("open_ended_error.html", diff --git a/common/lib/xmodule/xmodule/self_assessment_module.py b/common/lib/xmodule/xmodule/self_assessment_module.py index 940b61c557..4a7e86e134 100644 --- a/common/lib/xmodule/xmodule/self_assessment_module.py +++ b/common/lib/xmodule/xmodule/self_assessment_module.py @@ -122,7 +122,9 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild): if self.state == self.INITIAL: return '' - rubric_html = CombinedOpenEndedRubric.render_rubric(self.rubric) + rubric_renderer = CombinedOpenEndedRubric(True) + + rubric_html = rubric_renderer.render_rubric(self.rubric) # we'll render it context = {'rubric': rubric_html, diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index feb5add72e..c684fa1d95 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -264,8 +264,7 @@ def _get_next(course_id, grader_id, location): response_json = json.loads(response) rubric = response_json['rubric'] rubric_renderer = CombinedOpenEndedRubric(False) - rubric_xml = etree.XML(rubric) - rubric_html = rubric_renderer.render_rubric(rubric_xml) + rubric_html = rubric_renderer.render_rubric(rubric) response_json['rubric'] = rubric_html return json.dumps(response_json) except GradingServiceError: From f5600c2b8abb36583c612c184cf69a9f2a15106c Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 15:42:38 -0500 Subject: [PATCH 0014/1392] Make things more robust, ensure that a rubric is specified properly before combined open ended module will render --- .../xmodule/xmodule/combined_open_ended_module.py | 7 +++++++ .../xmodule/xmodule/combined_open_ended_rubric.py | 14 ++++++++++++-- common/lib/xmodule/xmodule/open_ended_module.py | 2 +- .../lib/xmodule/xmodule/self_assessment_module.py | 2 +- .../open_ended_grading/staff_grading_service.py | 7 ++++++- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index a88acc6ffd..67c7d15910 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -21,6 +21,7 @@ from .xml_module import XmlDescriptor from xmodule.modulestore import Location import self_assessment_module import open_ended_module +from combined_open_ended_rubric import CombinedOpenEndedRubric from mitxmako.shortcuts import render_to_string @@ -140,6 +141,12 @@ class CombinedOpenEndedModule(XModule): # completion (doesn't matter if you self-assessed correct/incorrect). self._max_score = int(self.metadata.get('max_score', MAX_SCORE)) + rubric_renderer = CombinedOpenEndedRubric(True) + success, rubric_feedback = rubric_renderer.render_rubric(True, definition['rubric']) + if not success: + error_message="Could not parse rubric : {0}".format(definition['rubric']) + log.exception(error_message) + raise Exception(error_message) #Static data is passed to the child modules to render self.static_data = { 'max_score': self._max_score, diff --git a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py index 4861a15dbc..2146942296 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py @@ -20,16 +20,26 @@ class CombinedOpenEndedRubric: html: the html that corresponds to the xml given ''' def render_rubric(self, rubric_xml): + success = False try: + rubric_xml = rubric_xml.encode('ascii', 'ignore') rubric_categories = self.extract_categories(rubric_xml) html = render_to_string('open_ended_rubric.html', {'categories' : rubric_categories, 'has_score': self.has_score, 'view_only': self.view_only}) + success = True except: log.exception("Could not parse the rubric.") - html = etree.tostring(rubric_xml, pretty_print=True) - return html + try: + html = etree.tostring(rubric_xml, pretty_print=True) + except: + log.exception("Rubric XML is a string, not an XML object : {0}".format(rubric_xml)) + if isinstance(rubric_xml, basestring): + html = rubric_xml + else: + html = "Invalid rubric. Please contact course staff." + return success, html def extract_categories(self, element): ''' diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index 4033d140dd..824eac3639 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -383,7 +383,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): feedback = self._convert_longform_feedback_to_html(response_items) if response_items['rubric_scores_complete']==True: rubric_renderer = CombinedOpenEndedRubric(True) - rubric_feedback = rubric_renderer.render_rubric(response_items['rubric_xml']) + success, rubric_feedback = rubric_renderer.render_rubric(response_items['rubric_xml']) if not response_items['success']: return system.render_template("open_ended_error.html", diff --git a/common/lib/xmodule/xmodule/self_assessment_module.py b/common/lib/xmodule/xmodule/self_assessment_module.py index 4a7e86e134..de842091c9 100644 --- a/common/lib/xmodule/xmodule/self_assessment_module.py +++ b/common/lib/xmodule/xmodule/self_assessment_module.py @@ -124,7 +124,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild): rubric_renderer = CombinedOpenEndedRubric(True) - rubric_html = rubric_renderer.render_rubric(self.rubric) + success, rubric_html = rubric_renderer.render_rubric(self.rubric) # we'll render it context = {'rubric': rubric_html, diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index c684fa1d95..9f7daeb786 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -264,7 +264,12 @@ def _get_next(course_id, grader_id, location): response_json = json.loads(response) rubric = response_json['rubric'] rubric_renderer = CombinedOpenEndedRubric(False) - rubric_html = rubric_renderer.render_rubric(rubric) + success, rubric_html = rubric_renderer.render_rubric(rubric) + if not success: + error_message = "Could not render rubric: {0}".format(rubric) + log.exception(error_message) + return json.dumps({'success': False, + 'error': error_message}) response_json['rubric'] = rubric_html return json.dumps(response_json) except GradingServiceError: From 8e213f53d892aa3e28ea0e5edbef91cb2c5f5245 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 15:52:57 -0500 Subject: [PATCH 0015/1392] Fix rubric parsing errors --- common/lib/xmodule/xmodule/combined_open_ended_module.py | 5 +++-- common/lib/xmodule/xmodule/combined_open_ended_rubric.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 67c7d15910..a35573032a 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -22,6 +22,7 @@ from xmodule.modulestore import Location import self_assessment_module import open_ended_module from combined_open_ended_rubric import CombinedOpenEndedRubric +from .stringify import stringify_children from mitxmako.shortcuts import render_to_string @@ -142,11 +143,11 @@ class CombinedOpenEndedModule(XModule): self._max_score = int(self.metadata.get('max_score', MAX_SCORE)) rubric_renderer = CombinedOpenEndedRubric(True) - success, rubric_feedback = rubric_renderer.render_rubric(True, definition['rubric']) + success, rubric_feedback = rubric_renderer.render_rubric(stringify_children(definition['rubric'])) if not success: error_message="Could not parse rubric : {0}".format(definition['rubric']) log.exception(error_message) - raise Exception(error_message) + raise Exception #Static data is passed to the child modules to render self.static_data = { 'max_score': self._max_score, diff --git a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py index 2146942296..37ce18e4f1 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py @@ -22,7 +22,6 @@ class CombinedOpenEndedRubric: def render_rubric(self, rubric_xml): success = False try: - rubric_xml = rubric_xml.encode('ascii', 'ignore') rubric_categories = self.extract_categories(rubric_xml) html = render_to_string('open_ended_rubric.html', {'categories' : rubric_categories, @@ -53,7 +52,8 @@ class CombinedOpenEndedRubric: {text: "Option 3 Name", points: 2]}] ''' - element = etree.fromstring(element) + if isinstance(element, basestring): + element = etree.fromstring(element) categories = [] for category in element: if category.tag != 'category': From 6427a7dac548cf2e747b0285139c47a5b1372243 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 16:03:53 -0500 Subject: [PATCH 0016/1392] Rubric html change --- lms/djangoapps/open_ended_grading/staff_grading_service.py | 1 + lms/templates/instructor/staff_grading.html | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 9f7daeb786..67f2775ad4 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -271,6 +271,7 @@ def _get_next(course_id, grader_id, location): return json.dumps({'success': False, 'error': error_message}) response_json['rubric'] = rubric_html + log.debug(rubric_html) return json.dumps(response_json) except GradingServiceError: log.exception("Error from grading service. server url: {0}" diff --git a/lms/templates/instructor/staff_grading.html b/lms/templates/instructor/staff_grading.html index 3749a63e73..f518f1e924 100644 --- a/lms/templates/instructor/staff_grading.html +++ b/lms/templates/instructor/staff_grading.html @@ -57,6 +57,12 @@ +
    +
    + +
    +
    +
    From 50f951d9df049781751d8d92f6cf4565dd1c144b Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 17:14:55 -0500 Subject: [PATCH 0017/1392] Bug fixes --- .../staff_grading_service.py | 20 +++++++++---------- lms/templates/instructor/staff_grading.html | 6 ------ 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 67f2775ad4..f417ca026e 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -262,16 +262,16 @@ def _get_next(course_id, grader_id, location): try: response = staff_grading_service().get_next(course_id, location, grader_id) response_json = json.loads(response) - rubric = response_json['rubric'] - rubric_renderer = CombinedOpenEndedRubric(False) - success, rubric_html = rubric_renderer.render_rubric(rubric) - if not success: - error_message = "Could not render rubric: {0}".format(rubric) - log.exception(error_message) - return json.dumps({'success': False, - 'error': error_message}) - response_json['rubric'] = rubric_html - log.debug(rubric_html) + if response_json.has_key('rubric'): + rubric = response_json['rubric'] + rubric_renderer = CombinedOpenEndedRubric(False) + success, rubric_html = rubric_renderer.render_rubric(rubric) + if not success: + error_message = "Could not render rubric: {0}".format(rubric) + log.exception(error_message) + return json.dumps({'success': False, + 'error': error_message}) + response_json['rubric'] = rubric_html return json.dumps(response_json) except GradingServiceError: log.exception("Error from grading service. server url: {0}" diff --git a/lms/templates/instructor/staff_grading.html b/lms/templates/instructor/staff_grading.html index f518f1e924..3749a63e73 100644 --- a/lms/templates/instructor/staff_grading.html +++ b/lms/templates/instructor/staff_grading.html @@ -57,12 +57,6 @@ -
    -
    - -
    -
    -
    From e5c6414d39daef349bc16c136cb3c2b41e06a64b Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 17:35:41 -0500 Subject: [PATCH 0018/1392] Adding score selection back into staff grading view --- .../src/staff_grading/staff_grading.coffee | 27 +++++++++++++++---- lms/templates/instructor/staff_grading.html | 2 ++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index d8fcb087a6..8e1fe738bf 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -174,7 +174,8 @@ class StaffGrading @grading_wrapper = $('.grading-wrapper') @feedback_area = $('.feedback-area') - @score_selection_container = $('.score-selection-container') + @score_selection_container = $('.score-selection-container') + @grade_selection_container = $('.grade-selection-container') @submit_button = $('.submit-button') @action_button = $('.action-button') @@ -202,6 +203,7 @@ class StaffGrading @num_graded = 0 @num_pending = 0 @score_lst = [] + @score = null @problems = null @@ -216,10 +218,23 @@ class StaffGrading setup_score_selection: => + # first, get rid of all the old inputs, if any. + @grade_selection_container.html('Choose score: ') + # Now create new labels and inputs for each possible score. + for score in [0..@max_score] + id = 'score-' + score + label = """""" + input = """ + + """ # " fix broken parsing in emacs + @grade_selection_container.append(input + label) + @score_selection_container.html(@rubric) $('.score-selection').click => @graded_callback() graded_callback: () => + @grade = $("input[name='grade-selection']:selected").val() + # check to see whether or not any categories have not been scored num_categories = $('table.rubric tr').length for i in [0..(num_categories-1)] @@ -229,8 +244,6 @@ class StaffGrading # show button if we have scores for all categories @state = state_graded @submit_button.show() - - set_button_text: (text) => @action_button.attr('value', text) @@ -272,6 +285,7 @@ class StaffGrading skip_and_get_next: () => data = + score: @grade rubric_scores: @get_score_list() feedback: @feedback_area.val() submission_id: @submission_id @@ -285,8 +299,8 @@ class StaffGrading submit_and_get_next: () -> data = + score: @grade rubric_scores: @get_score_list() - score: 0 feedback: @feedback_area.val() submission_id: @submission_id location: @location @@ -303,6 +317,8 @@ class StaffGrading @rubric = response.rubric @submission_id = response.submission_id @feedback_area.val('') + @grade = null + @max_score = response.max_score @ml_error_info=response.ml_error_info @prompt_name = response.problem_name @num_graded = response.num_graded @@ -322,9 +338,10 @@ class StaffGrading @ml_error_info = null @submission_id = null @message = message + @grade = null + @max_score = 0 @state = state_no_data - render_view: () -> # clear the problem list and breadcrumbs @problem_list.html('') diff --git a/lms/templates/instructor/staff_grading.html b/lms/templates/instructor/staff_grading.html index 3749a63e73..7364e3beb8 100644 --- a/lms/templates/instructor/staff_grading.html +++ b/lms/templates/instructor/staff_grading.html @@ -71,6 +71,8 @@
    +

    +

    From 6f9c0a7d72f4d9c84b281d4e5baf946a863de23e Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 17:47:44 -0500 Subject: [PATCH 0020/1392] Minor fix for when grade is ready to submit --- lms/static/coffee/src/staff_grading/staff_grading.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index 65cf85fd8d..5bbf72529e 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -234,7 +234,8 @@ class StaffGrading graded_callback: () => @grade = $("input[name='grade-selection']:checked").val() - + if score == undefined + return # check to see whether or not any categories have not been scored num_categories = $('table.rubric tr').length for i in [0..(num_categories-1)] From 78a94a4e206c47d74efd6bd5897f7153c42fff3f Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 17:50:20 -0500 Subject: [PATCH 0021/1392] Fix naming bug --- lms/static/coffee/src/staff_grading/staff_grading.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index 5bbf72529e..aeb39993e8 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -234,7 +234,7 @@ class StaffGrading graded_callback: () => @grade = $("input[name='grade-selection']:checked").val() - if score == undefined + if @grade == undefined return # check to see whether or not any categories have not been scored num_categories = $('table.rubric tr').length From be3d8cbb861fd14cc6ba2edd123f100b34079ffe Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Mon, 14 Jan 2013 18:00:53 -0500 Subject: [PATCH 0022/1392] Fix small issue with graded callback --- lms/static/coffee/src/staff_grading/staff_grading.coffee | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index aeb39993e8..3274f2048c 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -219,19 +219,24 @@ class StaffGrading setup_score_selection: => # first, get rid of all the old inputs, if any. - @grade_selection_container.html('Choose score: ') + @grade_selection_container.html(""" +

    Overall Score

    +

    Choose an overall score for this submission.

    + """) # Now create new labels and inputs for each possible score. for score in [0..@max_score] id = 'score-' + score label = """""" input = """ - + """ # " fix broken parsing in emacs @grade_selection_container.append(input + label) + $('.grade-selection').click => @graded_callback() @score_selection_container.html(@rubric) $('.score-selection').click => @graded_callback() + graded_callback: () => @grade = $("input[name='grade-selection']:checked").val() if @grade == undefined From 3a2c57524fb1fd6c910cfb051273ac097dcf168f Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Tue, 15 Jan 2013 10:35:20 -0500 Subject: [PATCH 0023/1392] Basic dnd for units --- cms/static/js/base.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/cms/static/js/base.js b/cms/static/js/base.js index 4137690395..59b5a3812c 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -59,7 +59,9 @@ $(document).ready(function() { $('.sortable-unit-list').sortable({ axis: 'y', handle: '.drag-handle', - update: onUnitReordered + update: onUnitReordered, + connectWith: '.sortable-unit-list', + revert: true }); // expand/collapse methods for optional date setters @@ -242,7 +244,7 @@ function removePolicyMetadata(e) { // This method only changes the ordering of the child objects in a subsection -function onUnitReordered() { +function onUnitReordered(event, ui) { var subsection_id = $(this).data('subsection-id'); var _els = $(this).children('li:.leaf'); @@ -256,6 +258,23 @@ function onUnitReordered() { contentType: "application/json", data:JSON.stringify({ 'id' : subsection_id, 'children' : children}) }); + + // remove from old container + if (ui.sender && subsection_id !== ui.sender.data('subsection-id')) { + + var _els = ui.sender.children('li:.leaf'); + var children = _els.map(function(idx, el) { return $(el).data('id'); }).get(); + + // call into server to commit the new order + $.ajax({ + url: "/save_item", + type: "POST", + dataType: "json", + contentType: "application/json", + data:JSON.stringify({ 'id' : ui.sender.data('subsection-id'), 'children' : children}) + }); + + } } function onSubsectionReordered() { From 48be0b15a161d893c41980fc5f827ce46cb61bc0 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 15 Jan 2013 11:21:10 -0500 Subject: [PATCH 0024/1392] Clean up on staff grading code path and the beginnings of peer grading. --- .../peer_grading_service.py | 28 +++- .../staff_grading_service.py | 4 +- .../peer_grading/peer_grading_problem.coffee | 122 +++++++++++++++--- .../src/staff_grading/staff_grading.coffee | 10 -- lms/static/sass/course/_staff_grading.scss | 3 +- .../peer_grading/peer_grading_problem.html | 12 +- 6 files changed, 133 insertions(+), 46 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/peer_grading_service.py b/lms/djangoapps/open_ended_grading/peer_grading_service.py index 9ef0383fb5..ce89448374 100644 --- a/lms/djangoapps/open_ended_grading/peer_grading_service.py +++ b/lms/djangoapps/open_ended_grading/peer_grading_service.py @@ -190,7 +190,7 @@ def get_next_submission(request, course_id): mimetype="application/json") except GradingServiceError: log.exception("Error getting next submission. server url: {0} location: {1}, grader_id: {2}" - .format(staff_grading_service().url, location, grader_id)) + .format(peer_grading_service().url, location, grader_id)) return json.dumps({'success': False, 'error': 'Could not connect to grading service'}) @@ -228,7 +228,7 @@ def save_grade(request, course_id): except GradingServiceError: log.exception("""Error saving grade. server url: {0}, location: {1}, submission_id:{2}, submission_key: {3}, score: {4}""" - .format(staff_grading_service().url, + .format(peer_grading_service().url, location, submission_id, submission_key, score) ) return json.dumps({'success': False, @@ -267,7 +267,7 @@ def is_student_calibrated(request, course_id): return HttpResponse(response, mimetype="application/json") except GradingServiceError: log.exception("Error from grading service. server url: {0}, grader_id: {0}, location: {1}" - .format(staff_grading_service().url, grader_id, location)) + .format(peer_grading_service().url, grader_id, location)) return json.dumps({'success': False, 'error': 'Could not connect to grading service'}) @@ -308,12 +308,30 @@ def show_calibration_essay(request, course_id): location = p['location'] try: response = peer_grading_service().show_calibration_essay(location, grader_id) - return HttpResponse(response, mimetype="application/json") + response_json = json.loads(response) + # if we can't handle the rubric + if response_json.has_key('rubric'): + rubric = response_json['rubric'] + rubric_renderer = CombinedOpenEndedRubric(False) + success, rubric_html = rubric_renderer.render_rubric(rubric) + if not success: + error_message = "Could not render rubric: {0}".format(rubric) + log.exception(error_message) + return json.dumps({'success': False, + 'error': error_message}) + response_json['rubric'] = rubric_html + return json.dumps(response_json) except GradingServiceError: log.exception("Error from grading service. server url: {0}, location: {0}" - .format(staff_grading_service().url, location)) + .format(peer_grading_service().url, location)) return json.dumps({'success': False, 'error': 'Could not connect to grading service'}) + # if we can't parse the rubric into HTML, + except etree.XMLSyntaxError: + log.exception("Cannot parse rubric string. Raw string: {0}" + .format(rubric)) + return json.dumps({'success': False, + 'error': 'Error displaying submission'}) def save_calibration_essay(request, course_id): diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index f417ca026e..b988a3548c 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -50,9 +50,9 @@ class MockStaffGradingService(object): self.cnt += 1 return json.dumps({'success': True, 'problem_list': [ - json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo1', \ + json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo1', 'problem_name': "Problem 1", 'num_graded': 3, 'num_pending': 5, 'min_for_ml': 10}), - json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo2', \ + json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo2', 'problem_name': "Problem 2", 'num_graded': 1, 'num_pending': 5, 'min_for_ml': 10}) ]}) diff --git a/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee b/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee index e294c50f7c..548a3f3db3 100644 --- a/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee +++ b/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee @@ -56,13 +56,41 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t

    This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.

    ''' rubric: ''' -
      -
    • Metals tend to be good electronic conductors, meaning that they have a large number of electrons which are able to access empty (mobile) energy states within the material.
    • -
    • Sodium has a half-filled s-band, so there are a number of empty states immediately above the highest occupied energy levels within the band.
    • -
    • Magnesium has a full s-band, but the the s-band and p-band overlap in magnesium. Thus are still a large number of available energy states immediately above the s-band highest occupied energy level.
    • -
    - -

    Please score your response according to how many of the above components you identified:

    + + + + + + + + + + + + + + + + + + +
    Purpose + + + + + + + +
    Organization + + + + + + + +
    ''' max_score: 4 else if cmd == 'get_next_submission' @@ -82,13 +110,41 @@ Curabitur tristique purus ac arcu consequat cursus. Cras diam felis, dignissim q

    This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.

    ''' rubric: ''' -
      -
    • Metals tend to be good electronic conductors, meaning that they have a large number of electrons which are able to access empty (mobile) energy states within the material.
    • -
    • Sodium has a half-filled s-band, so there are a number of empty states immediately above the highest occupied energy levels within the band.
    • -
    • Magnesium has a full s-band, but the the s-band and p-band overlap in magnesium. Thus are still a large number of available energy states immediately above the s-band highest occupied energy level.
    • -
    - -

    Please score your response according to how many of the above components you identified:

    + + + + + + + + + + + + + + + + + + +
    Purpose + + + + + + + +
    Organization + + + + + + + +
    ''' max_score: 4 else if cmd == 'save_calibration_essay' @@ -137,6 +193,7 @@ class PeerGradingProblem @feedback_area = $('.feedback-area') @score_selection_container = $('.score-selection-container') + @rubric_selection_container = $('.rubric-selection-container') @score = null @calibration = null @@ -175,8 +232,22 @@ class PeerGradingProblem fetch_submission_essay: () => @backend.post('get_next_submission', {location: @location}, @render_submission) + # finds the scores for each rubric category + get_score_list: () => + # find the number of categories: + num_categories = $('table.rubric tr').length + + score_lst = [] + # get the score for each one + for i in [0..(num_categories-1)] + score = $("input[name='score-selection-#{i}']:checked").val() + score_lst.push(score) + + return score_lst + construct_data: () -> data = + rubric_scores: @get_score_list() score: @score location: @location submission_id: @essay_id_input.val() @@ -244,8 +315,16 @@ class PeerGradingProblem # called after a grade is selected on the interface graded_callback: (event) => - @grading_message.hide() - @score = event.target.value + @grade = $("input[name='grade-selection']:checked").val() + if @grade == undefined + return + # check to see whether or not any categories have not been scored + num_categories = $('table.rubric tr').length + for i in [0..(num_categories-1)] + score = $("input[name='score-selection-#{i}']:checked").val() + if score == undefined + return + # show button if we have scores for all categories @show_submit_button() @@ -322,7 +401,7 @@ class PeerGradingProblem @submission_container.append(@make_paragraphs(response.student_response)) @prompt_container.html(response.prompt) - @rubric_container.html(response.rubric) + @rubric_selection_container.html(response.rubric) @submission_key_input.val(response.submission_key) @essay_id_input.val(response.submission_id) @setup_score_selection(response.max_score) @@ -366,8 +445,12 @@ class PeerGradingProblem @submit_button.show() setup_score_selection: (max_score) => + # first, get rid of all the old inputs, if any. - @score_selection_container.html('Choose score: ') + @score_selection_container.html(""" +

    Overall Score

    +

    Choose an overall score for this submission.

    + """) # Now create new labels and inputs for each possible score. for score in [0..max_score] @@ -375,12 +458,13 @@ class PeerGradingProblem label = """""" input = """ - + """ # " fix broken parsing in emacs @score_selection_container.append(input + label) # And now hook up an event handler again $("input[name='score-selection']").change @graded_callback + $("input[name='grade-selection']").change @graded_callback diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index 3274f2048c..a9e70f7e75 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -45,43 +45,35 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t
    Purpose - - - -
    Organization - - - -
    ''' @@ -169,8 +161,6 @@ class StaffGrading @submission_container = $('.submission-container') @submission_wrapper = $('.submission-wrapper') - @rubric_container = $('.rubric-container') - @rubric_wrapper = $('.rubric-wrapper') @grading_wrapper = $('.grading-wrapper') @feedback_area = $('.feedback-area') diff --git a/lms/static/sass/course/_staff_grading.scss b/lms/static/sass/course/_staff_grading.scss index edcd16b350..6023c48dfa 100644 --- a/lms/static/sass/course/_staff_grading.scss +++ b/lms/static/sass/course/_staff_grading.scss @@ -24,7 +24,8 @@ div.peer-grading{ color: white; } - input[name='score-selection'] { + input[name='score-selection'], + input[name='grade-selection'] { display: none; } diff --git a/lms/templates/peer_grading/peer_grading_problem.html b/lms/templates/peer_grading/peer_grading_problem.html index d493e84ace..b96d878bee 100644 --- a/lms/templates/peer_grading/peer_grading_problem.html +++ b/lms/templates/peer_grading/peer_grading_problem.html @@ -44,20 +44,13 @@
    -
    -
    Question
    +
    +
    Question
    -
    -
    Rubric
    -
    -
    -
    -
    -
    @@ -74,6 +67,7 @@
    +

    + Add cohort members + +
      +
    +
    From 9e84ae14d4c32509d4c0de74b632a8c7b664def2 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Wed, 23 Jan 2013 17:49:01 -0500 Subject: [PATCH 0154/1392] Started integration work with Kevin's cohort changes - Create new cohorts.py file - moved code there from models.py - implemented necessary functions. Next: testing :) --- common/djangoapps/course_groups/cohorts.py | 166 ++++++++++++++++++ common/djangoapps/course_groups/models.py | 119 ------------- common/djangoapps/course_groups/views.py | 18 +- common/lib/xmodule/xmodule/course_module.py | 33 ++-- lms/djangoapps/courseware/courses.py | 20 --- .../django_comment_client/base/views.py | 2 +- .../django_comment_client/forum/views.py | 2 +- 7 files changed, 200 insertions(+), 160 deletions(-) create mode 100644 common/djangoapps/course_groups/cohorts.py diff --git a/common/djangoapps/course_groups/cohorts.py b/common/djangoapps/course_groups/cohorts.py new file mode 100644 index 0000000000..6c18491775 --- /dev/null +++ b/common/djangoapps/course_groups/cohorts.py @@ -0,0 +1,166 @@ +""" +This file contains the logic for cohort groups, as exposed internally to the +forums, and to the cohort admin views. +""" + +from django.contrib.auth.models import User +import logging + +from courseware import courses +from .models import CourseUserGroup + +log = logging.getLogger(__name__) + +def is_course_cohorted(course_id): + """ + Given a course id, return a boolean for whether or not the course is + cohorted. + + Raises: + Http404 if the course doesn't exist. + """ + return courses.get_course_by_id(course_id).is_cohorted + + +def get_cohort_id(user, course_id): + """ + Given a course id and a user, return the id of the cohort that user is + assigned to in that course. If they don't have a cohort, return None. + """ + cohort = get_cohort(user, course_id) + return None if cohort is None else cohort.id + + +def is_commentable_cohorted(course_id, commentable_id): + """ + Given a course and a commentable id, return whether or not this commentable + is cohorted. + + Raises: + Http404 if the course doesn't exist. + """ + course = courses.get_course_by_id(course_id) + return commentable_id in course.cohorted_discussions() + + +def get_cohort(user, course_id): + """ + Given a django User and a course_id, return the user's cohort. In classes with + auto-cohorting, put the user in a cohort if they aren't in one already. + + Arguments: + user: a Django User object. + course_id: string in the format 'org/course/run' + + Returns: + A CourseUserGroup object if the User has a cohort, or None. + """ + try: + group = CourseUserGroup.objects.get(course_id=course_id, + group_type=CourseUserGroup.COHORT, + users__id=user.id) + except CourseUserGroup.DoesNotExist: + group = None + + if group: + return group + + # TODO: add auto-cohorting logic here once we know what that will be. + return None + + +def get_course_cohorts(course_id): + """ + Get a list of all the cohorts in the given course. + + Arguments: + course_id: string in the format 'org/course/run' + + Returns: + A list of CourseUserGroup objects. Empty if there are no cohorts. + """ + return list(CourseUserGroup.objects.filter(course_id=course_id, + group_type=CourseUserGroup.COHORT)) + +### Helpers for cohort management views + +def get_cohort_by_name(course_id, name): + """ + Return the CourseUserGroup object for the given cohort. Raises DoesNotExist + it isn't present. + """ + return CourseUserGroup.objects.get(course_id=course_id, + group_type=CourseUserGroup.COHORT, + name=name) + +def get_cohort_by_id(course_id, cohort_id): + """ + Return the CourseUserGroup object for the given cohort. Raises DoesNotExist + it isn't present. Uses the course_id for extra validation... + """ + return CourseUserGroup.objects.get(course_id=course_id, + group_type=CourseUserGroup.COHORT, + id=cohort_id) + +def add_cohort(course_id, name): + """ + Add a cohort to a course. Raises ValueError if a cohort of the same name already + exists. + """ + log.debug("Adding cohort %s to %s", name, course_id) + if CourseUserGroup.objects.filter(course_id=course_id, + group_type=CourseUserGroup.COHORT, + name=name).exists(): + raise ValueError("Can't create two cohorts with the same name") + + return CourseUserGroup.objects.create(course_id=course_id, + group_type=CourseUserGroup.COHORT, + name=name) + +def add_user_to_cohort(cohort, username_or_email): + """ + Look up the given user, and if successful, add them to the specified cohort. + + Arguments: + cohort: CourseUserGroup + username_or_email: string. Treated as email if has '@' + + Returns: + User object. + + Raises: + User.DoesNotExist if can't find user. + + ValueError if user already present. + """ + if '@' in username_or_email: + user = User.objects.get(email=username_or_email) + else: + user = User.objects.get(username=username_or_email) + + if cohort.users.filter(id=user.id).exists(): + raise ValueError("User {0} already present".format(user.username)) + + cohort.users.add(user) + return user + + +def get_course_cohort_names(course_id): + """ + Return a list of the cohort names in a course. + """ + return [c.name for c in get_course_cohorts(course_id)] + + +def delete_empty_cohort(course_id, name): + """ + Remove an empty cohort. Raise ValueError if cohort is not empty. + """ + cohort = get_cohort_by_name(course_id, name) + if cohort.users.exists(): + raise ValueError( + "Can't delete non-empty cohort {0} in course {1}".format( + name, course_id)) + + cohort.delete() + diff --git a/common/djangoapps/course_groups/models.py b/common/djangoapps/course_groups/models.py index dd46e5a055..957d230d92 100644 --- a/common/djangoapps/course_groups/models.py +++ b/common/djangoapps/course_groups/models.py @@ -31,123 +31,4 @@ class CourseUserGroup(models.Model): GROUP_TYPE_CHOICES = ((COHORT, 'Cohort'),) group_type = models.CharField(max_length=20, choices=GROUP_TYPE_CHOICES) -def get_cohort(user, course_id): - """ - Given a django User and a course_id, return the user's cohort. In classes with - auto-cohorting, put the user in a cohort if they aren't in one already. - - Arguments: - user: a Django User object. - course_id: string in the format 'org/course/run' - - Returns: - A CourseUserGroup object if the User has a cohort, or None. - """ - try: - group = CourseUserGroup.objects.get(course_id=course_id, - group_type=CourseUserGroup.COHORT, - users__id=user.id) - except CourseUserGroup.DoesNotExist: - group = None - - if group: - return group - - # TODO: add auto-cohorting logic here - return None - -def get_course_cohorts(course_id): - """ - Get a list of all the cohorts in the given course. - - Arguments: - course_id: string in the format 'org/course/run' - - Returns: - A list of CourseUserGroup objects. Empty if there are no cohorts. - """ - return list(CourseUserGroup.objects.filter(course_id=course_id, - group_type=CourseUserGroup.COHORT)) - -### Helpers for cohor management views - -def get_cohort_by_name(course_id, name): - """ - Return the CourseUserGroup object for the given cohort. Raises DoesNotExist - it isn't present. - """ - return CourseUserGroup.objects.get(course_id=course_id, - group_type=CourseUserGroup.COHORT, - name=name) - -def get_cohort_by_id(course_id, cohort_id): - """ - Return the CourseUserGroup object for the given cohort. Raises DoesNotExist - it isn't present. Uses the course_id for extra validation... - """ - return CourseUserGroup.objects.get(course_id=course_id, - group_type=CourseUserGroup.COHORT, - id=cohort_id) - -def add_cohort(course_id, name): - """ - Add a cohort to a course. Raises ValueError if a cohort of the same name already - exists. - """ - log.debug("Adding cohort %s to %s", name, course_id) - if CourseUserGroup.objects.filter(course_id=course_id, - group_type=CourseUserGroup.COHORT, - name=name).exists(): - raise ValueError("Can't create two cohorts with the same name") - - return CourseUserGroup.objects.create(course_id=course_id, - group_type=CourseUserGroup.COHORT, - name=name) - -def add_user_to_cohort(cohort, username_or_email): - """ - Look up the given user, and if successful, add them to the specified cohort. - - Arguments: - cohort: CourseUserGroup - username_or_email: string. Treated as email if has '@' - - Returns: - User object. - - Raises: - User.DoesNotExist if can't find user. - - ValueError if user already present. - """ - if '@' in username_or_email: - user = User.objects.get(email=username_or_email) - else: - user = User.objects.get(username=username_or_email) - - if cohort.users.filter(id=user.id).exists(): - raise ValueError("User {0} already present".format(user.username)) - - cohort.users.add(user) - return user - - -def get_course_cohort_names(course_id): - """ - Return a list of the cohort names in a course. - """ - return [c.name for c in get_course_cohorts(course_id)] - - -def delete_empty_cohort(course_id, name): - """ - Remove an empty cohort. Raise ValueError if cohort is not empty. - """ - cohort = get_cohort_by_name(course_id, name) - if cohort.users.exists(): - raise ValueError( - "Can't delete non-empty cohort {0} in course {1}".format( - name, course_id)) - - cohort.delete() diff --git a/common/djangoapps/course_groups/views.py b/common/djangoapps/course_groups/views.py index f02bff2d00..c79839208e 100644 --- a/common/djangoapps/course_groups/views.py +++ b/common/djangoapps/course_groups/views.py @@ -1,4 +1,3 @@ -import json from django_future.csrf import ensure_csrf_cookie from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User @@ -7,6 +6,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.urlresolvers import reverse from django.http import HttpResponse, HttpResponseForbidden, Http404 from django.shortcuts import redirect +import json import logging from courseware.courses import get_course_with_access @@ -14,7 +14,7 @@ from mitxmako.shortcuts import render_to_response, render_to_string from string_util import split_by_comma_and_whitespace from .models import CourseUserGroup -from . import models +from . import cohorts import track.views @@ -38,11 +38,11 @@ def list_cohorts(request, course_id): """ get_course_with_access(request.user, course_id, 'staff') - cohorts = [{'name': c.name, 'id': c.id} - for c in models.get_course_cohorts(course_id)] + all_cohorts = [{'name': c.name, 'id': c.id} + for c in cohorts.get_course_cohorts(course_id)] return JsonHttpReponse({'success': True, - 'cohorts': cohorts}) + 'cohorts': all_cohorts}) @ensure_csrf_cookie @@ -70,7 +70,7 @@ def add_cohort(request, course_id): 'msg': "No name specified"}) try: - cohort = models.add_cohort(course_id, name) + cohort = cohorts.add_cohort(course_id, name) except ValueError as err: return JsonHttpReponse({'success': False, 'msg': str(err)}) @@ -98,7 +98,7 @@ def users_in_cohort(request, course_id, cohort_id): """ get_course_with_access(request.user, course_id, 'staff') - cohort = models.get_cohort_by_id(course_id, int(cohort_id)) + cohort = cohorts.get_cohort_by_id(course_id, int(cohort_id)) paginator = Paginator(cohort.users.all(), 100) page = request.GET.get('page') @@ -141,7 +141,7 @@ def add_users_to_cohort(request, course_id, cohort_id): if request.method != "POST": raise Http404("Must POST to add users to cohorts") - cohort = models.get_cohort_by_id(course_id, cohort_id) + cohort = cohorts.get_cohort_by_id(course_id, cohort_id) users = request.POST.get('users', '') added = [] @@ -149,7 +149,7 @@ def add_users_to_cohort(request, course_id, cohort_id): unknown = [] for username_or_email in split_by_comma_and_whitespace(users): try: - user = models.add_user_to_cohort(cohort, username_or_email) + user = cohorts.add_user_to_cohort(cohort, username_or_email) added.append({'username': user.username, 'name': "{0} {1}".format(user.first_name, user.last_name), 'email': user.email, diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index c0b3000258..5b6de04f3e 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -223,7 +223,7 @@ class CourseDescriptor(SequenceDescriptor): return policy_str - + @classmethod def from_xml(cls, xml_data, system, org=None, course=None): instance = super(CourseDescriptor, cls).from_xml(xml_data, system, org, course) @@ -248,7 +248,7 @@ class CourseDescriptor(SequenceDescriptor): except ValueError: system.error_tracker("Unable to decode grading policy as json") policy = None - + # cdodge: import the grading policy information that is on disk and put into the # descriptor 'definition' bucket as a dictionary so that it is persisted in the DB instance.definition['data']['grading_policy'] = policy @@ -303,28 +303,28 @@ class CourseDescriptor(SequenceDescriptor): @property def enrollment_start(self): return self._try_parse_time("enrollment_start") - + @enrollment_start.setter def enrollment_start(self, value): if isinstance(value, time.struct_time): self.metadata['enrollment_start'] = stringify_time(value) @property - def enrollment_end(self): + def enrollment_end(self): return self._try_parse_time("enrollment_end") - + @enrollment_end.setter def enrollment_end(self, value): if isinstance(value, time.struct_time): self.metadata['enrollment_end'] = stringify_time(value) - + @property def grader(self): return self._grading_policy['GRADER'] - + @property def raw_grader(self): return self._grading_policy['RAW_GRADER'] - + @raw_grader.setter def raw_grader(self, value): # NOTE WELL: this change will not update the processed graders. If we need that, this needs to call grader_from_conf @@ -334,12 +334,12 @@ class CourseDescriptor(SequenceDescriptor): @property def grade_cutoffs(self): return self._grading_policy['GRADE_CUTOFFS'] - + @grade_cutoffs.setter def grade_cutoffs(self, value): self._grading_policy['GRADE_CUTOFFS'] = value self.definition['data'].setdefault('grading_policy',{})['GRADE_CUTOFFS'] = value - + @property def lowest_passing_grade(self): @@ -371,6 +371,19 @@ class CourseDescriptor(SequenceDescriptor): return bool(config.get("cohorted")) + def cohorted_discussions(self): + """ + Return the set of discussions that is cohorted. It may be the empty + set. + """ + config = self.metadata.get("cohort-config") + if config is None: + return set() + + return set(config.get("cohorted-discussions", [])) + + + @property def is_new(self): """ diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 74f5e4c54f..89a1496eca 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -83,26 +83,6 @@ def get_opt_course_with_access(user, course_id, action): return None return get_course_with_access(user, course_id, action) - -def get_cohort_id(user, course_id): - """ - given a course id and a user, return the id of the cohort that user is assigned to - and if the course is not cohorted or the user is an instructor, return None - - """ - return 127 - -def is_commentable_cohorted(course_id,commentable_id): - """ - given a course and a commentable id, return whether or not this commentable is cohorted - - """ - - -def get_cohort_ids(course_id): - """ - given a course id, return an array of all cohort ids for that course (needed for UI - """ def course_image_url(course): """Try to look up the image url for the course. If it's not found, diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index c1e188ff1a..eee6c6d09d 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -21,7 +21,7 @@ from django.contrib.auth.models import User from mitxmako.shortcuts import render_to_response, render_to_string from courseware.courses import get_course_with_access -from courseware.courses import get_cohort_id,is_commentable_cohorted +from course_groups.cohorts import get_cohort_id, is_commentable_cohorted from django_comment_client.utils import JsonResponse, JsonError, extract, get_courseware_context diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index 443329ec1f..93752f6c33 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -11,7 +11,7 @@ from django.contrib.auth.models import User from mitxmako.shortcuts import render_to_response, render_to_string from courseware.courses import get_course_with_access -from courseware.courses import get_cohort_id +from course_groups.cohorts import get_cohort_id from courseware.access import has_access from urllib import urlencode From de027211586a0e4704abe6e34887059a75e44427 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Thu, 24 Jan 2013 11:00:53 -0500 Subject: [PATCH 0155/1392] Add removing students from cohorts. --- common/djangoapps/course_groups/views.py | 31 +++++++++++++++++ common/static/js/course_groups/cohorts.js | 34 ++++++++++++++++--- .../course_groups/cohort_management.html | 2 +- lms/urls.py | 3 ++ 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/common/djangoapps/course_groups/views.py b/common/djangoapps/course_groups/views.py index c79839208e..e82532ae50 100644 --- a/common/djangoapps/course_groups/views.py +++ b/common/djangoapps/course_groups/views.py @@ -164,6 +164,37 @@ def add_users_to_cohort(request, course_id, cohort_id): 'present': present, 'unknown': unknown}) +@ensure_csrf_cookie +def remove_user_from_cohort(request, course_id, cohort_id): + """ + Expects 'username': username in POST data. + + Return json dict of: + + {'success': True} or + {'success': False, + 'msg': error_msg} + """ + get_course_with_access(request.user, course_id, 'staff') + + if request.method != "POST": + raise Http404("Must POST to add users to cohorts") + + username = request.POST.get('username') + if username is None: + return JsonHttpReponse({'success': False, + 'msg': 'No username specified'}) + + cohort = cohorts.get_cohort_by_id(course_id, cohort_id) + try: + user = User.objects.get(username=username) + cohort.users.remove(user) + return JsonHttpReponse({'success': True}) + except User.DoesNotExist: + log.debug('no user') + return JsonHttpReponse({'success': False, + 'msg': "No user '{0}'".format(username)}) + def debug_cohort_mgmt(request, course_id): """ diff --git a/common/static/js/course_groups/cohorts.js b/common/static/js/course_groups/cohorts.js index 531ce51923..ada0b16bd5 100644 --- a/common/static/js/course_groups/cohorts.js +++ b/common/static/js/course_groups/cohorts.js @@ -67,7 +67,8 @@ var CohortManager = (function ($) { var detail_page_num = $$(".page_num"); var users_area = $$(".users_area"); var add_members_button = $$(".add_members"); - var op_results = $$("op_results"); + var op_results = $$(".op_results"); + var cohort_id = null; var cohort_title = null; var detail_url = null; var page = null; @@ -79,6 +80,7 @@ var CohortManager = (function ($) { var el = $(this); cohort_title = el.text(); detail_url = el.data('href'); + cohort_id = el.data('id'); state = state_detail; render(); } @@ -118,12 +120,31 @@ var CohortManager = (function ($) { // *********** Detail view methods + function remove_user_from_cohort(username, cohort_id, row) { + var delete_url = detail_url + '/delete'; + var data = {'username': username} + $.post(delete_url, data).done(function() {row.remove()}) + .fail(function(jqXHR, status, error) { + log_error('Error removing user ' + username + + ' from cohort. ' + status + ' ' + error); + }); + } + function add_to_users_list(item) { var tr = $('
    '+"";var R=z?'":"";for(var S=0;S<7;S++){var T=(S+y)%7;R+="=5?' class="ui-datepicker-week-end"':"")+">"+''+C[T]+""}Q+=R+"";var U=this._getDaysInMonth(o,n);o==a.selectedYear&&n==a.selectedMonth&&(a.selectedDay=Math.min(a.selectedDay,U));var V=(this._getFirstDayOfMonth(o,n)-y+7)%7,W=Math.ceil((V+U)/7),X=j?this.maxRows>W?this.maxRows:W:W;this.maxRows=X;var Y=this._daylightSavingAdjust(new Date(o,n,1-V));for(var Z=0;Z";var _=z?'":"";for(var S=0;S<7;S++){var ba=F?F.apply(a.input?a.input[0]:null,[Y]):[!0,""],bb=Y.getMonth()!=n,bc=bb&&!H||!ba[0]||l&&Ym;_+='",Y.setDate(Y.getDate()+1),Y=this._daylightSavingAdjust(Y)}Q+=_+""}n++,n>11&&(n=0,o++),Q+="
    '+this._get(a,"weekHeader")+"
    '+this._get(a,"calculateWeek")(Y)+""+(bb&&!G?" ":bc?''+Y.getDate()+"":''+Y.getDate()+"")+"
    "+(j?""+(g[0]>0&&N==g[1]-1?'
    ':""):""),M+=Q}K+=M}return K+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!a.inline?'':""),a._keyEvent=!1,K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='
    ',m="";if(f||!i)m+=''+g[b]+"";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='"}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+=''+c+"";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='",l+=a.yearshtml,a.yearshtml=null}}return l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="
    ",l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&bd?d:e,e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));return b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth())),this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");return b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10),{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);return typeof a!="string"||a!="isDisabled"&&a!="getDate"&&a!="widget"?a=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b)):this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)}):$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.22",window["DP_jQuery_"+dpuuid]=$})(jQuery);;/*! jQuery UI - v1.8.22 - 2012-07-24 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.progressbar.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("
    ").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){return a===b?this._value():(this._setOption("value",a),this)},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;return typeof a!="number"&&(a=0),Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.22"})})(jQuery);;/*! jQuery UI - v1.8.22 - 2012-07-24 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.core.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -jQuery.effects||function(a,b){function c(b){var c;return b&&b.constructor==Array&&b.length==3?b:(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))?[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)]:(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))?[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))?[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)]:(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))?[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)]:(c=/rgba\(0, 0, 0, 0\)/.exec(b))?e.transparent:e[a.trim(b).toLowerCase()]}function d(b,d){var e;do{e=(a.curCSS||a.css)(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};return a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete,[b,c,d,e]}function l(b){return!b||typeof b=="number"||a.fx.speeds[b]?!0:typeof b=="string"&&!a.effects[b]?!0:!1}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){return a.isFunction(d)&&(e=d,d=null),this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class")||"";a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.22",save:function(a,b){for(var c=0;c").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;try{e.id}catch(f){e=document.body}return b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;return b.parent().is(".ui-effects-wrapper")?(c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus(),c):b},setTransition:function(b,c,d,e){return e=e||{},a.each(c,function(a,c){var f=b.cssUnit(c);f[0]>0&&(e[c]=f[0]*d+f[1])}),e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];return a.fx.off||!i?h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)}):i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="show",this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="hide",this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);return c[1].mode="toggle",this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];return a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])}),d}}),a.easing.jswing=a.easing.swing,a.extend(a.easing,{def:"easeOutQuad",swing:function(b,c,d,e,f){return a.easing[a.easing.def](b,c,d,e,f)},easeInQuad:function(a,b,c,d,e){return d*(b/=e)*b+c},easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c},easeInOutQuad:function(a,b,c,d,e){return(b/=e/2)<1?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},easeInCubic:function(a,b,c,d,e){return d*(b/=e)*b*b+c},easeOutCubic:function(a,b,c,d,e){return d*((b=b/e-1)*b*b+1)+c},easeInOutCubic:function(a,b,c,d,e){return(b/=e/2)<1?d/2*b*b*b+c:d/2*((b-=2)*b*b+2)+c},easeInQuart:function(a,b,c,d,e){return d*(b/=e)*b*b*b+c},easeOutQuart:function(a,b,c,d,e){return-d*((b=b/e-1)*b*b*b-1)+c},easeInOutQuart:function(a,b,c,d,e){return(b/=e/2)<1?d/2*b*b*b*b+c:-d/2*((b-=2)*b*b*b-2)+c},easeInQuint:function(a,b,c,d,e){return d*(b/=e)*b*b*b*b+c},easeOutQuint:function(a,b,c,d,e){return d*((b=b/e-1)*b*b*b*b+1)+c},easeInOutQuint:function(a,b,c,d,e){return(b/=e/2)<1?d/2*b*b*b*b*b+c:d/2*((b-=2)*b*b*b*b+2)+c},easeInSine:function(a,b,c,d,e){return-d*Math.cos(b/e*(Math.PI/2))+d+c},easeOutSine:function(a,b,c,d,e){return d*Math.sin(b/e*(Math.PI/2))+c},easeInOutSine:function(a,b,c,d,e){return-d/2*(Math.cos(Math.PI*b/e)-1)+c},easeInExpo:function(a,b,c,d,e){return b==0?c:d*Math.pow(2,10*(b/e-1))+c},easeOutExpo:function(a,b,c,d,e){return b==e?c+d:d*(-Math.pow(2,-10*b/e)+1)+c},easeInOutExpo:function(a,b,c,d,e){return b==0?c:b==e?c+d:(b/=e/2)<1?d/2*Math.pow(2,10*(b-1))+c:d/2*(-Math.pow(2,-10*--b)+2)+c},easeInCirc:function(a,b,c,d,e){return-d*(Math.sqrt(1-(b/=e)*b)-1)+c},easeOutCirc:function(a,b,c,d,e){return d*Math.sqrt(1-(b=b/e-1)*b)+c},easeInOutCirc:function(a,b,c,d,e){return(b/=e/2)<1?-d/2*(Math.sqrt(1-b*b)-1)+c:d/2*(Math.sqrt(1-(b-=2)*b)+1)+c},easeInElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/*! jQuery UI - v1.8.22 - 2012-07-24 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.fade.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.22 - 2012-07-24 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.fold.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.22 - 2012-07-24 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.highlight.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.22 - 2012-07-24 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.pulsate.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show"),e=(b.options.times||5)*2-1,f=b.duration?b.duration/2:a.fx.speeds._default/2,g=c.is(":visible"),h=0;g||(c.css("opacity",0).show(),h=1),(d=="hide"&&g||d=="show"&&!g)&&e--;for(var i=0;i').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);; \ No newline at end of file +/*! jQuery UI - v1.10.0 - 2013-01-23 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js +* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.10.0",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a={},f=t.split(".")[0];t=t.split(".")[1],i=f+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[f]=e[f]||{},s=e[f][t],o=e[f][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,r){if(!e.isFunction(r)){a[t]=r;return}a[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},i=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=i,s=r.apply(this,arguments),this._super=t,this._superApply=n,s}}()}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},a,{constructor:o,namespace:f,widgetName:t,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}function d(t){var n=t[0];return n.nodeType===9?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(n)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:n.preventDefault?{width:0,height:0,offset:{top:n.pageY,left:n.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("
    "),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};lr(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)a&&(v<0||v0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)10&&i<11,t.innerHTML="",n.removeChild(t)}()})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.0",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){this.options.helper==="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var n=this.options;return this.helper||n.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e("
    ").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!=="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!=="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n,r=this,i=!1,s=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),n=this.element[0];while(n&&(n=n.parentNode))n===document&&(i=!0);return!i&&this.options.helper==="original"?!1:(this.options.revert==="invalid"&&!s||this.options.revert==="valid"&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){r._trigger("stop",t)!==!1&&r._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1)},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").addBack().each(function(){this===t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper==="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo==="parent"?this.element[0].parentNode:n.appendTo),r[0]!==this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition==="absolute"&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()==="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,n,r,i=this.options;i.containment==="parent"&&(i.containment=this.helper[0].parentNode);if(i.containment==="document"||i.containment==="window")this.containment=[i.containment==="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,i.containment==="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(i.containment==="document"?0:e(window).scrollLeft())+e(i.containment==="document"?document:window).width()-this.helperProportions.width-this.margins.left,(i.containment==="document"?0:e(window).scrollTop())+(e(i.containment==="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(i.containment)&&i.containment.constructor!==Array){n=e(i.containment),r=n[0];if(!r)return;t=e(r).css("overflow")!=="hidden",this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(t?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else i.containment.constructor===Array&&(this.containment=i.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t==="absolute"?1:-1,i=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,s=/(html|body)/i.test(i[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():s?0:i.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():s?0:i.scrollLeft())*r}},_generatePosition:function(t){var n,r,i,s,o=this.options,u=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(u[0].tagName),f=t.pageX,l=t.pageY;return this.originalPosition&&(this.containment&&(this.relative_container?(r=this.relative_container.offset(),n=[this.containment[0]+r.left,this.containment[1]+r.top,this.containment[2]+r.left,this.containment[3]+r.top]):n=this.containment,t.pageX-this.offset.click.leftn[2]&&(f=n[2]+this.offset.click.left),t.pageY-this.offset.click.top>n[3]&&(l=n[3]+this.offset.click.top)),o.grid&&(i=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=n?i-this.offset.click.top>=n[1]||i-this.offset.click.top>n[3]?i:i-this.offset.click.top>=n[1]?i-o.grid[1]:i+o.grid[1]:i,s=o.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,f=n?s-this.offset.click.left>=n[0]||s-this.offset.click.left>n[2]?s:s-this.offset.click.left>=n[0]?s-o.grid[0]:s+o.grid[0]:s)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():a?0:u.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():a?0:u.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!==this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t==="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("ui-draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"ui-sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("ui-draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper==="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("ui-draggable"),i=this;e.each(r.sortables,function(){var s=!1,o=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(s=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.ui.contains(o.instance.element[0],this.instance.element[0])&&(s=!1),s})),s?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),n=e(this).data("ui-draggable").options;t.css("cursor")&&(n._cursor=t.css("cursor")),t.css("cursor",n.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("ui-draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("ui-draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&t.scrollParent[0].tagName!=="HTML"&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var n=e(this).data("ui-draggable"),r=n.options,i=!1;if(n.scrollParent[0]!==document&&n.scrollParent[0].tagName!=="HTML"){if(!r.axis||r.axis!=="x")n.overflowOffset.top+n.scrollParent[0].offsetHeight-t.pageY=0;c--){u=p.snapElements[c].left,a=u+p.snapElements[c].width,f=p.snapElements[c].top,l=f+p.snapElements[c].height;if(!(u-vt&&e=h&&a<=p||f>=h&&f<=p||ap)&&(o>=l&&o<=c||u>=l&&u<=c||oc);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r,i,s=e.ui.ddmanager.droppables[t.options.scope]||[],o=n?n.type:null,u=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(r=0;r").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=u.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor===String){this.handles==="all"&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={};for(n=0;n"),i.css({zIndex:u.zIndex}),"se"===r&&i.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[r]=".ui-resizable-"+r,this.element.append(i)}this._renderAxis=function(t){var n,r,i,s;t=t||this.element;for(n in this.handles){this.handles[n].constructor===String&&(this.handles[n]=e(this.handles[n],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(r=e(this.handles[n],this.element),s=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth(),i=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize());if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=i&&i[1]?i[1]:"se")}),u.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(u.disabled)return;e(this).removeClass("ui-resizable-autohide"),o._handles.show()}).mouseleave(function(){if(u.disabled)return;o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,n=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(n(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),n(this.originalElement),this},_mouseCapture:function(t){var n,r,i=!1;for(n in this.handles){r=e(this.handles[n])[0];if(r===t.target||e.contains(r,t.target))i=!0}return!this.options.disabled&&i},_mouseStart:function(t){var r,i,s,o=this.options,u=this.element.position(),a=this.element;return this.resizing=!0,/absolute/.test(a.css("position"))?a.css({position:"absolute",top:a.css("top"),left:a.css("left")}):a.is(".ui-draggable")&&a.css({position:"absolute",top:u.top,left:u.left}),this._renderProxy(),r=n(this.helper.css("left")),i=n(this.helper.css("top")),o.containment&&(r+=e(o.containment).scrollLeft()||0,i+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:r,top:i},this.size=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.originalPosition={left:r,top:i},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof o.aspectRatio=="number"?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor",s==="auto"?this.axis+"-resize":s),a.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var n,r=this.helper,i={},s=this.originalMousePosition,o=this.axis,u=this.position.top,a=this.position.left,f=this.size.width,l=this.size.height,c=t.pageX-s.left||0,h=t.pageY-s.top||0,p=this._change[o];if(!p)return!1;n=p.apply(this,[t,c,h]),this._updateVirtualBoundaries(t.shiftKey);if(this._aspectRatio||t.shiftKey)n=this._updateRatio(n,t);return n=this._respectSize(n,t),this._updateCache(n),this._propagate("resize",t),this.position.top!==u&&(i.top=this.position.top+"px"),this.position.left!==a&&(i.left=this.position.left+"px"),this.size.width!==f&&(i.width=this.size.width+"px"),this.size.height!==l&&(i.height=this.size.height+"px"),r.css(i),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(i)||this._trigger("resize",t,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n,r,i,s,o,u,a,f=this.options,l=this;return this._helper&&(n=this._proportionallyResizeElements,r=n.length&&/textarea/i.test(n[0].nodeName),i=r&&e.ui.hasScroll(n[0],"left")?0:l.sizeDiff.height,s=r?0:l.sizeDiff.width,o={width:l.helper.width()-s,height:l.helper.height()-i},u=parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left)||null,a=parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top)||null,f.animate||this.element.css(e.extend(o,{top:a,left:u})),l.helper.height(l.size.height),l.helper.width(l.size.width),this._helper&&!f.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,n,i,s,o,u=this.options;o={minWidth:r(u.minWidth)?u.minWidth:0,maxWidth:r(u.maxWidth)?u.maxWidth:Infinity,minHeight:r(u.minHeight)?u.minHeight:0,maxHeight:r(u.maxHeight)?u.maxHeight:Infinity};if(this._aspectRatio||e)t=o.minHeight*this.aspectRatio,i=o.minWidth/this.aspectRatio,n=o.maxHeight*this.aspectRatio,s=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),i>o.minHeight&&(o.minHeight=i),ne.width,u=r(e.height)&&t.minHeight&&t.minHeight>e.height,a=this.originalPosition.left+this.originalSize.width,f=this.position.top+this.size.height,l=/sw|nw|w/.test(n),c=/nw|ne|n/.test(n);return o&&(e.width=t.minWidth),u&&(e.height=t.minHeight),i&&(e.width=t.maxWidth),s&&(e.height=t.maxHeight),o&&l&&(e.left=a-t.minWidth),i&&l&&(e.left=a-t.maxWidth),u&&c&&(e.top=f-t.minHeight),s&&c&&(e.top=f-t.maxHeight),!e.width&&!e.height&&!e.left&&e.top?e.top=null:!e.width&&!e.height&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){if(!this._proportionallyResizeElements.length)return;var e,t,n,r,i,s=this.helper||this.element;for(e=0;e"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var n=this.originalSize,r=this.originalPosition;return{left:r.left+t,width:n.width-t}},n:function(e,t,n){var r=this.originalSize,i=this.originalPosition;return{top:i.top+n,height:r.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!=="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var n=e(this).data("ui-resizable"),r=n.options,i=n._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:n.sizeDiff.height,u=s?0:n.sizeDiff.width,a={width:n.size.width-u,height:n.size.height-o},f=parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left)||null,l=parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top)||null;n.element.animate(e.extend(a,l&&f?{top:l,left:f}:{}),{duration:r.animateDuration,easing:r.animateEasing,step:function(){var r={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};i&&i.length&&e(i[0]).css({width:r.width,height:r.height}),n._updateCache(r),n._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,r,i,s,o,u,a,f=e(this).data("ui-resizable"),l=f.options,c=f.element,h=l.containment,p=h instanceof e?h.get(0):/parent/.test(h)?c.parent().get(0):h;if(!p)return;f.containerElement=e(p),/document/.test(h)||h===document?(f.containerOffset={left:0,top:0},f.containerPosition={left:0,top:0},f.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(p),r=[],e(["Top","Right","Left","Bottom"]).each(function(e,i){r[e]=n(t.css("padding"+i))}),f.containerOffset=t.offset(),f.containerPosition=t.position(),f.containerSize={height:t.innerHeight()-r[3],width:t.innerWidth()-r[1]},i=f.containerOffset,s=f.containerSize.height,o=f.containerSize.width,u=e.ui.hasScroll(p,"left")?p.scrollWidth:o,a=e.ui.hasScroll(p)?p.scrollHeight:s,f.parentData={element:p,left:i.left,top:i.top,width:u,height:a})},resize:function(t){var n,r,i,s,o=e(this).data("ui-resizable"),u=o.options,a=o.containerOffset,f=o.position,l=o._aspectRatio||t.shiftKey,c={top:0,left:0},h=o.containerElement;h[0]!==document&&/static/.test(h.css("position"))&&(c=a),f.left<(o._helper?a.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-a.left:o.position.left-c.left),l&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=u.helper?a.left:0),f.top<(o._helper?a.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-a.top:o.position.top),l&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?a.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,n=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),r=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-a.top)+o.sizeDiff.height),i=o.containerElement.get(0)===o.element.parent().get(0),s=/relative|absolute/.test(o.containerElement.css("position")),i&&s&&(n-=o.parentData.left),n+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-n,l&&(o.size.height=o.size.width/o.aspectRatio)),r+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-r,l&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.containerOffset,i=t.containerPosition,s=t.containerElement,o=e(t.helper),u=o.offset(),a=o.outerWidth()-t.sizeDiff.width,f=o.outerHeight()-t.sizeDiff.height;t._helper&&!n.animate&&/relative/.test(s.css("position"))&&e(this).css({left:u.left-i.left-r.left,width:a,height:f}),t._helper&&!n.animate&&/static/.test(s.css("position"))&&e(this).css({left:u.left-i.left-r.left,width:a,height:f})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),n=t.options,r=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof n.alsoResize=="object"&&!n.alsoResize.parentNode?n.alsoResize.length?(n.alsoResize=n.alsoResize[0],r(n.alsoResize)):e.each(n.alsoResize,function(e){r(e)}):r(n.alsoResize)},resize:function(t,n){var r=e(this).data("ui-resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("ui-resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:r.height,width:r.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof n.ghost=="string"?n.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.size,i=t.originalSize,s=t.originalPosition,o=t.axis,u=typeof n.grid=="number"?[n.grid,n.grid]:n.grid,a=u[0]||1,f=u[1]||1,l=Math.round((r.width-i.width)/a)*a,c=Math.round((r.height-i.height)/f)*f,h=i.width+l,p=i.height+c,d=n.maxWidth&&n.maxWidthh,g=n.minHeight&&n.minHeight>p;n.grid=u,m&&(h+=a),g&&(p+=f),d&&(h-=a),v&&(p-=f),/^(se|s|e)$/.test(o)?(t.size.width=h,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=h,t.size.height=p,t.position.top=s.top-c):/^(sw)$/.test(o)?(t.size.width=h,t.size.height=p,t.position.left=s.left-l):(t.size.width=h,t.size.height=p,t.position.top=s.top-c,t.position.left=s.left-l)}})})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.10.0",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,n=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(n.options.filter,n.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
    ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this,r=this.options;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().addBack().each(function(){var r,i=e.data(this,"selectable-item");if(i)return r=!t.metaKey&&!t.ctrlKey||!i.$element.hasClass("ui-selected"),i.$element.removeClass(r?"ui-unselecting":"ui-selected").addClass(r?"ui-selecting":"ui-unselecting"),i.unselecting=!r,i.selecting=r,i.selected=r,r?n._trigger("selecting",t,{selecting:i.element}):n._trigger("unselecting",t,{unselecting:i.element}),!1})},_mouseDrag:function(t){this.dragged=!0;if(this.options.disabled)return;var n,r=this,i=this.options,s=this.opos[0],o=this.opos[1],u=t.pageX,a=t.pageY;return s>u&&(n=u,u=s,s=n),o>a&&(n=a,a=o,o=n),this.helper.css({left:s,top:o,width:u-s,height:a-o}),this.selectees.each(function(){var n=e.data(this,"selectable-item"),f=!1;if(!n||n.element===r.element[0])return;i.tolerance==="touch"?f=!(n.left>u||n.righta||n.bottoms&&n.righto&&n.bottomt&&e *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=null,i=!1,s=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type==="static")return!1;this._refreshItems(t),e(t.target).parents().each(function(){if(e.data(this,s.widgetName+"-item")===s)return r=e(this),!1}),e.data(t.target,s.widgetName+"-item")===s&&(r=e(t.target));if(!r)return!1;if(this.options.handle&&!n){e(this.options.handle,r).find("*").addBack().each(function(){this===t.target&&(i=!0)});if(!i)return!1}return this.currentItem=r,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i,s=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,s.cursorAt&&this._adjustOffsetFromHelper(s.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),s.containment&&this._setContainment(),s.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",s.cursor)),s.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",s.opacity)),s.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",s.zIndex)),this.scrollParent[0]!==document&&this.scrollParent[0].tagName!=="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(i=this.containers.length-1;i>=0;i--)this.containers[i]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!s.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var n,r,i,s,o=this.options,u=!1;this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&this.scrollParent[0].tagName!=="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;n--){r=this.items[n],i=r.item[0],s=this._intersectsWithPointer(r);if(!s)continue;if(r.instance!==this.currentContainer)continue;if(i!==this.currentItem[0]&&this.placeholder[s===1?"next":"prev"]()[0]!==i&&!e.contains(this.placeholder[0],i)&&(this.options.type==="semi-dynamic"?!e.contains(this.element[0],i):!0)){this.direction=s===1?"down":"up";if(this.options.tolerance!=="pointer"&&!this._intersectsWithSides(r))break;this._rearrange(t,r),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper==="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!=="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+fs&&t+le[this.floating?"width":"height"]?c:s0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!==0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n,r,i,s,o=[],u=[],a=this._connectWith();if(a&&t)for(n=a.length-1;n>=0;n--){i=e(a[n]);for(r=i.length-1;r>=0;r--)s=e.data(i[r],this.widgetFullName),s&&s!==this&&!s.options.disabled&&u.push([e.isFunction(s.options.items)?s.options.items.call(s.element):e(s.options.items,s.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),s])}u.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(n=u.length-1;n>=0;n--)u[n][0].each(function(){o.push(this)});return e(o)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n=0;n--){i=e(h[n]);for(r=i.length-1;r>=0;r--)s=e.data(i[r],this.widgetFullName),s&&s!==this&&!s.options.disabled&&(c.push([e.isFunction(s.options.items)?s.options.items.call(s.element[0],t,{item:this.currentItem}):e(s.options.items,s.element),s]),this.containers.push(s))}for(n=c.length-1;n>=0;n--){o=c[n][1],u=c[n][0];for(r=0,f=u.length;r=0;n--){r=this.items[n];if(r.instance!==this.currentContainer&&this.currentContainer&&r.item[0]!==this.currentItem[0])continue;i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item,t||(r.width=i.outerWidth(),r.height=i.outerHeight()),s=i.offset(),r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(n=this.containers.length-1;n>=0;n--)s=this.containers[n].element.offset(),this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var n,r=t.options;if(!r.placeholder||r.placeholder.constructor===String)n=r.placeholder,r.placeholder={element:function(){var r=e(document.createElement(t.currentItem[0].nodeName)).addClass(n||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return n||(r.style.visibility="hidden"),r},update:function(e,i){if(n&&!r.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}};t.placeholder=e(r.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),r.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n,r,i,s,o,u,a,f,l,c=null,h=null;for(n=this.containers.length-1;n>=0;n--){if(e.contains(this.currentItem[0],this.containers[n].element[0]))continue;if(this._intersectsWith(this.containers[n].containerCache)){if(c&&e.contains(this.containers[n].element[0],c.element[0]))continue;c=this.containers[n],h=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",t,this._uiHash(this)),this.containers[n].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[h]._trigger("over",t,this._uiHash(this)),this.containers[h].containerCache.over=1;else{i=1e4,s=null,o=this.containers[h].floating?"left":"top",u=this.containers[h].floating?"width":"height",a=this.positionAbs[o]+this.offset.click[o];for(r=this.items.length-1;r>=0;r--){if(!e.contains(this.containers[h].element[0],this.items[r].item[0]))continue;if(this.items[r].item[0]===this.currentItem[0])continue;f=this.items[r].item.offset()[o],l=!1,Math.abs(f-a)>Math.abs(f+this.items[r][u]-a)&&(l=!0,f+=this.items[r][u]),Math.abs(f-a)this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),i.grid&&(n=this.originalPageY+Math.round((o-this.originalPageY)/i.grid[1])*i.grid[1],o=this.containment?n-this.offset.click.top>=this.containment[1]&&n-this.offset.click.top<=this.containment[3]?n:n-this.offset.click.top>=this.containment[1]?n-i.grid[1]:n+i.grid[1]:n,r=this.originalPageX+Math.round((s-this.originalPageX)/i.grid[0])*i.grid[0],s=this.containment?r-this.offset.click.left>=this.containment[0]&&r-this.offset.click.left<=this.containment[2]?r:r-this.offset.click.left>=this.containment[0]?r-i.grid[0]:r+i.grid[0]:r)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():a?0:u.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():a?0:u.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction==="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i===this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r,i=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]===this.currentItem[0]){for(r in this._storedCSS)if(this._storedCSS[r]==="auto"||this._storedCSS[r]==="static")this._storedCSS[r]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&i.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!==this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!==this.currentItem.parent()[0])&&!n&&i.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(i.push(function(e){this._trigger("remove",e,this._uiHash())}),i.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),i.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(r=this.containers.length-1;r>=0;r--)n||i.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[r])),this.containers[r].containerCache.over&&(i.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[r])),this.containers[r].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex==="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(r=0;r li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),!t.collapsible&&(t.active===!1||t.active==null)&&(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels();if(t.active===!1&&t.collapsible===!0||!this.headers.length)t.active=!1,this.active=e();t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var t,r=this.options,i=r.heightStyle,s=this.element.parent(),o=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n);this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(t){var n=e(this),r=n.attr("id"),i=n.next(),s=i.attr("id");r||(r=o+"-header-"+t,n.attr("id",r)),s||(s=o+"-panel-"+t,i.attr("id",s)),n.attr("aria-controls",s),i.attr("aria-labelledby",r)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(r.event),i==="fill"?(t=s.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):i==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,n),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("
    +

    If you are interested in this position, please send an email to jobs@edx.org.

    + + + +

    INSTRUCTIONAL DESIGNER — CONTRACT OPPORTUNITY

    From 37a9dccbe7b74d31083942bf8b130d96481da905 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Sun, 27 Jan 2013 17:50:53 -0500 Subject: [PATCH 0207/1392] Update media kit download (LH #168) --- lms/static/files/edx-identity.zip | Bin 633710 -> 620417 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lms/static/files/edx-identity.zip b/lms/static/files/edx-identity.zip index a37d2b4e203b96c8a11efb87b2508e812fa12878..22b95f70f57cfa990c89cf7c99aee8af38d552aa 100644 GIT binary patch delta 175894 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%0A!yz8$*7cylQL)Rr+x^MAT3@E^Ntgw&)Mz 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 F@82!7HX#52 delta 189331 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�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 From 1f6331161c14da910762ed8002492303778ced77 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Sun, 27 Jan 2013 18:10:14 -0500 Subject: [PATCH 0208/1392] Update FAQ (LH #125) --- lms/templates/static_templates/help.html | 62 ++++++++++++++---------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/lms/templates/static_templates/help.html b/lms/templates/static_templates/help.html index 04c9164289..74b4c2afc9 100644 --- a/lms/templates/static_templates/help.html +++ b/lms/templates/static_templates/help.html @@ -53,12 +53,6 @@

    We are continually reviewing and creating courses to add to the edX platform. Please check the website for future course announcements. You can also "friend" edX on Facebook – you’ll receive updates and announcements.

    -
    -

    How can I help edX?

    -
    -

    You may not realize it, but just by taking a course you are helping edX. That’s because the edX platform has been specifically designed to not only teach, but also gather data about learning. EdX will utilize this data to find out how to improve education online and on-campus.

    -
    -

    When does my course start and/or finish?

    @@ -78,7 +72,7 @@
    -

    What happens if I have to quit a course, are there any penalties, will I be able to take another course in the future?

    +

    What happens if I have to quit a course? Are there any penalties? Will I be able to take another course in the future?

    You may unregister from an edX course at anytime, there are absolutely no penalties associated with incomplete edX studies, and you may register for the same course (provided we are still offering it) at a later time.

    @@ -147,85 +141,94 @@

    The Discussion Forums are the best place to reach out to the edX teaching team for your class, and you don’t have to wait in line or rearrange your schedule to fit your professor’s – just post your questions. The response isn’t always immediate, but it’s usually pretty darned quick.

    - -
    -

    Getting Help

    +
    +

    Getting help.

    +
    +

    You have a vibrant, global community of fellow online learners available 24-7 to help with the course within the framework of the Honor Code, as well as support from the TAs who monitor the course. Take a look at the course’s Discussion Forum where you can review questions, answers and comments from fellow online learners, as well as post a question.

    +
    +

    Can I re-take a course?

    -
    +

    Good news: there are unlimited "mulligans" in edX. You may re-take edX courses as often as you wish. Your performance in any particular offering of a course will not effect your standing in future offerings of any edX course, including future offerings of the same course.

    Enrollment for a course that I am interested in is open, but the course has already started. Can I still enroll?

    -
    +

    Yes, but you will not be able to turn in any assignments or exams that have already been due. If it is early in the course, you might still be able to earn enough points for a certificate, but you will have to check with the course in question in order to find out more.

    Is there an exam at the end?

    -
    +

    Different courses have slightly different structures. Please check the course material description to see if there is a final exam or final project.

    Will the same courses be offered again in the future?

    -
    +

    Existing edX courses will be re-offered, and more courses added.

    +
    + + +
    +

    Certificates & Credits

    +

    Will I get a certificate for taking an edX course?

    -
    +

    Online learners who receive a passing grade for a course will receive a certificate of mastery from edX and the underlying X University that offered the course. For example, a certificate of mastery for MITx’s 6.002x Circuits & Electronics will come from edX and MITx.

    How are edX certificates delivered?

    -
    +

    EdX certificates are delivered online through edx.org. So be sure to check your email in the weeks following the final grading – you will be able to download and print your certificate.

    What is the difference between a proctored certificate and an honor code certificate?

    -
    +

    A proctored certificate is given to students who take and pass an exam under proctored conditions. An honor-code certificate is given to students who have completed all of the necessary online coursework associated with a course and have signed the edX honor code .

    -

    Yes. The requirements for both certificates can be independently satisfied.

    -
    -

    It is certainly possible to pass an edX course if you miss a week; however, coursework is progressive, so you should review and study what you may have missed. You can check your progress dashboard in the course to see your course average along the way if you have any concerns.

    +

    Can I get both a proctored certificate and an honor code certificate?

    +
    +

    Yes. The requirements for both certificates can be independently satisfied.

    Will my grade be shown on my certificate?

    -
    +

    No. Grades are not displayed on either honor code or proctored certificates.

    How can I talk to professors, fellows and teaching assistants?

    -
    +

    The Discussion Forums are the best place to reach out to the edX teaching team for your class, and you don’t have to wait in line or rearrange your schedule to fit your professor’s – just post your questions. The response isn’t always immediate, but it’s usually pretty darned quick.

    The only certificates distributed with grades by edX were for the initial prototype course.

    -
    +

    You may unregister from an edX course at anytime, there are absolutely no penalties associated with incomplete edX studies, and you may register for the same course (provided we are still offering it) at a later time.

    Will my university accept my edX coursework for credit?

    -
    +

    Each educational institution makes its own decision regarding whether to accept edX coursework for credit. Check with your university for its policy.

    I lost my edX certificate – can you resend it to me?

    -
    +

    Please log back in to your account to find certificates from the same profile page where they were originally posted. You will be able to re-print your certificate from there.

    @@ -292,6 +295,13 @@

    Please check your browser and settings. We recommend downloading the current version of Firefox or Chrome. Alternatively, you may re-register with a different email account. There is no need to delete the old account, as it will disappear if unused.

    +
    +

    How can I help edX?

    +
    +

    You may not realize it, but just by taking a course you are helping edX. That’s because the edX platform has been specifically designed to not only teach, but also gather data about learning. EdX will utilize this data to find out how to improve education online and on-campus.

    +
    +
    +
    @@ -299,7 +309,7 @@
    From 8d64bfdbdb910535fa41e130b7a2af9a7eb7aa66 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 28 Jan 2013 08:41:39 -0500 Subject: [PATCH 0209/1392] Update tests to handle rubric scores --- lms/djangoapps/open_ended_grading/peer_grading_service.py | 4 ++-- lms/djangoapps/open_ended_grading/tests.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/peer_grading_service.py b/lms/djangoapps/open_ended_grading/peer_grading_service.py index b850293255..b4f918397f 100644 --- a/lms/djangoapps/open_ended_grading/peer_grading_service.py +++ b/lms/djangoapps/open_ended_grading/peer_grading_service.py @@ -50,7 +50,7 @@ class MockPeerGradingService(object): 'max_score': 4}) def save_grade(self, location, grader_id, submission_id, - score, feedback, submission_key): + score, feedback, submission_key, rubric_scores): return json.dumps({'success': True}) def is_student_calibrated(self, problem_location, grader_id): @@ -66,7 +66,7 @@ class MockPeerGradingService(object): 'max_score': 4}) def save_calibration_essay(self, problem_location, grader_id, - calibration_essay_id, submission_key, score, feedback): + calibration_essay_id, submission_key, score, feedback, rubric_scores): return json.dumps({'success': True, 'actual_score': 2}) def get_problem_list(self, course_id, grader_id): diff --git a/lms/djangoapps/open_ended_grading/tests.py b/lms/djangoapps/open_ended_grading/tests.py index c1d192b6cc..57ea4f319c 100644 --- a/lms/djangoapps/open_ended_grading/tests.py +++ b/lms/djangoapps/open_ended_grading/tests.py @@ -171,7 +171,8 @@ class TestPeerGradingService(ct.PageLoader): 'submission_id': '1', 'submission_key': 'fake key', 'score': '2', - 'feedback': 'This is feedback'} + 'feedback': 'This is feedback', + 'rubric_scores[]': [1, 2]} r = self.check_for_post_code(200, url, data) d = json.loads(r.content) self.assertTrue(d['success']) @@ -236,7 +237,8 @@ class TestPeerGradingService(ct.PageLoader): 'submission_id': '1', 'submission_key': 'fake key', 'score': '2', - 'feedback': 'This is feedback'} + 'feedback': 'This is feedback', + 'rubric_scores[]': [1, 2]} r = self.check_for_post_code(200, url, data) d = json.loads(r.content) self.assertTrue(d['success']) From fe4dc7622ea1afb325d49cb04358e1357fc81957 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 28 Jan 2013 10:18:01 -0500 Subject: [PATCH 0210/1392] Updates to combined open ended tests --- .../xmodule/tests/test_combined_open_ended.py | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py index ba3dc10b4b..b327d10340 100644 --- a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py +++ b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py @@ -290,7 +290,7 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): ''') - task_xml = ''' + task_xml1 = ''' What hint about this problem would you give to someone? @@ -300,7 +300,15 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): ''' - definition = {'prompt': etree.XML(prompt), 'rubric': etree.XML(rubric), 'task_xml': [task_xml]} + task_xml2 = ''' + + + Enter essay here. + This is the answer. + {"grader_settings" : "ml_grading.conf", "problem_id" : "6.002x/Welcome/OETest"} + + ''' + definition = {'prompt': etree.XML(prompt), 'rubric': etree.XML(rubric), 'task_xml': [task_xml1, task_xml2]} descriptor = Mock() def setUp(self): @@ -320,7 +328,12 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): changed = self.combinedoe.update_task_states() self.assertFalse(changed) - # do something to change the state + #prev_context = self.combinedoe.get_context() + #new_state = {'state': CombinedOpenEndedModule.INITIAL, 'history': []} + ## force a task change + #task_state = self.combinedoe.overwrite_state(json.dumps(new_state)) - # check again + ## check again + #new_context = self.combinedoe.get_context() + #self.assertNotEqual(prev_context['state'], new_context['state']) From 1d4b674c79da72c6047003481c9f35c7c696bc5f Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 28 Jan 2013 10:57:06 -0500 Subject: [PATCH 0211/1392] Address code review feedback --- .../xmodule/combined_open_ended_module.py | 2 +- .../open_ended_grading/grading_service.py | 17 ++++++++++------- .../open_ended_grading/peer_grading_service.py | 4 ++-- .../open_ended_grading/staff_grading_service.py | 3 +-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index ee22962c4e..aa4b1f18ad 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -145,7 +145,7 @@ class CombinedOpenEndedModule(XModule): rubric_feedback = rubric_renderer.render_rubric(stringify_children(definition['rubric'])) except RubricParsingError: log.error("Failed to parse rubric in location: {1}".format(location)) - raise Exception("CombinedOpenEnded: could not render given rubric") + raise #Static data is passed to the child modules to render self.static_data = { 'max_score': self._max_score, diff --git a/lms/djangoapps/open_ended_grading/grading_service.py b/lms/djangoapps/open_ended_grading/grading_service.py index 9d4849d3ed..f65554a9d6 100644 --- a/lms/djangoapps/open_ended_grading/grading_service.py +++ b/lms/djangoapps/open_ended_grading/grading_service.py @@ -106,26 +106,29 @@ class GradingService(object): def _render_rubric(self, response, view_only=False): """ Given an HTTP Response with the key 'rubric', render out the html - required to display the rubric + required to display the rubric and put it back into the response + + returns the updated response as a dictionary that can be serialized later + """ try: response_json = json.loads(response) - if response_json.has_key('rubric'): + if 'rubric' in response_json: rubric = response_json['rubric'] rubric_renderer = CombinedOpenEndedRubric(self.system, False) rubric_html = rubric_renderer.render_rubric(rubric) response_json['rubric'] = rubric_html - return json.dumps(response_json) + return response_json # if we can't parse the rubric into HTML, except etree.XMLSyntaxError, RubricParsingError: log.exception("Cannot parse rubric string. Raw string: {0}" .format(rubric)) - return json.dumps({'success': False, - 'error': 'Error displaying submission'}) + return {'success': False, + 'error': 'Error displaying submission'} except ValueError: log.exception("Error parsing response: {0}".format(response)) - return json.dumps({'success': False, - 'error': "Error displaying submission"}) + return {'success': False, + 'error': "Error displaying submission"} diff --git a/lms/djangoapps/open_ended_grading/peer_grading_service.py b/lms/djangoapps/open_ended_grading/peer_grading_service.py index f1dd531277..caa349125d 100644 --- a/lms/djangoapps/open_ended_grading/peer_grading_service.py +++ b/lms/djangoapps/open_ended_grading/peer_grading_service.py @@ -86,7 +86,7 @@ class PeerGradingService(GradingService): def get_next_submission(self, problem_location, grader_id): response = self.get(self.get_next_submission_url, {'location': problem_location, 'grader_id': grader_id}) - return self._render_rubric(response) + return json.dumps(self._render_rubric(response)) def save_grade(self, location, grader_id, submission_id, score, feedback, submission_key, rubric_scores): data = {'grader_id' : grader_id, @@ -106,7 +106,7 @@ class PeerGradingService(GradingService): def show_calibration_essay(self, problem_location, grader_id): params = {'problem_id' : problem_location, 'student_id': grader_id} response = self.get(self.show_calibration_essay_url, params) - return self._render_rubric(response) + return json.dumps(self._render_rubric(response)) def save_calibration_essay(self, problem_location, grader_id, calibration_essay_id, submission_key, score, feedback, rubric_scores): diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 226bdbc389..4e776b688b 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -112,7 +112,7 @@ class StaffGradingService(GradingService): response = self.get(self.get_next_url, params={'location': location, 'grader_id': grader_id}) - return self._render_rubric(response) + return json.dumps(self._render_rubric(response)) def save_grade(self, course_id, grader_id, submission_id, score, feedback, skipped, rubric_scores): @@ -148,7 +148,6 @@ class StaffGradingService(GradingService): # importing this file doesn't create objects that may not have the right config _service = None -module_system = ModuleSystem("", None, None, render_to_string, None) def staff_grading_service(): """ From ef3a124281e11a3c4d3cc5abe0a24b79521e34fd Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Mon, 28 Jan 2013 11:13:21 -0500 Subject: [PATCH 0212/1392] LMS - added in additional JQUI accordion parameter needed to display full height of active element in courseware sidebar --- lms/static/coffee/src/navigation.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/lms/static/coffee/src/navigation.coffee b/lms/static/coffee/src/navigation.coffee index 94d53c17c4..3f89a6ce1d 100644 --- a/lms/static/coffee/src/navigation.coffee +++ b/lms/static/coffee/src/navigation.coffee @@ -13,6 +13,7 @@ class @Navigation active: active header: 'h3' autoHeight: false + heightStyle: 'content' $('#accordion .ui-state-active').closest('.chapter').addClass('is-open') $('#open_close_accordion a').click @toggle $('#accordion').show() From ffbda8a0be72c8add8b6210a6437d9f178148bdf Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 28 Jan 2013 11:52:15 -0500 Subject: [PATCH 0213/1392] Update test --- .../xmodule/tests/test_combined_open_ended.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py index b327d10340..9485ed2a47 100644 --- a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py +++ b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py @@ -328,12 +328,10 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): changed = self.combinedoe.update_task_states() self.assertFalse(changed) - #prev_context = self.combinedoe.get_context() - #new_state = {'state': CombinedOpenEndedModule.INITIAL, 'history': []} - ## force a task change - #task_state = self.combinedoe.overwrite_state(json.dumps(new_state)) + current_task = self.combinedoe.current_task + current_task.change_state(CombinedOpenEndedModule.DONE) + changed = self.combinedoe.update_task_states() + + self.assertTrue(changed) - ## check again - #new_context = self.combinedoe.get_context() - #self.assertNotEqual(prev_context['state'], new_context['state']) From d1e5632880d2ef020f791e8a789c9d4b367e3205 Mon Sep 17 00:00:00 2001 From: Ashley Penney Date: Mon, 28 Jan 2013 12:51:05 -0500 Subject: [PATCH 0214/1392] Remove the specific version of ruby here because it's breaking the dev scripts amongst other things. --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index b95f3b5d1a..43a9f6e2b1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,4 @@ source :rubygems -ruby "1.8.7" gem 'rake', '~> 10.0.3' gem 'sass', '3.1.15' gem 'bourbon', '~> 1.3.6' From 9cf0f0900b3e34f1c9abce3056c64885b3540e17 Mon Sep 17 00:00:00 2001 From: Brian Wilson Date: Mon, 28 Jan 2013 12:56:26 -0500 Subject: [PATCH 0215/1392] Fix Pearson unit tests. --- .../student/management/commands/tests/test_pearson.py | 5 +++-- lms/envs/test.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/djangoapps/student/management/commands/tests/test_pearson.py b/common/djangoapps/student/management/commands/tests/test_pearson.py index 199557bf87..2f4878a09d 100644 --- a/common/djangoapps/student/management/commands/tests/test_pearson.py +++ b/common/djangoapps/student/management/commands/tests/test_pearson.py @@ -40,6 +40,7 @@ def create_tc_registration(username, course_id = 'org1/course1/term1', exam_code 'eligibility_appointment_date_first' : '2013-01-01T00:00', 'eligibility_appointment_date_last' : '2013-12-31T23:59', 'accommodation_code' : accommodation_code, + 'create_dummy_exam' : True, } call_command('pearson_make_tc_registration', username, course_id, **options) @@ -179,11 +180,11 @@ class PearsonCommandTestCase(PearsonTestCase): self.assertErrorContains(error_string, 'Field Form Error: address_1') def test_create_good_testcenter_user(self): - testcenter_user = create_tc_user("test1") + testcenter_user = create_tc_user("test_good_user") self.assertIsNotNone(testcenter_user) def test_create_good_testcenter_registration(self): - username = 'test1' + username = 'test_good_registration' create_tc_user(username) registration = create_tc_registration(username) self.assertIsNotNone(registration) diff --git a/lms/envs/test.py b/lms/envs/test.py index a045baa669..8b546549eb 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -17,7 +17,7 @@ from path import path MITX_FEATURES['DISABLE_START_DATES'] = True # Until we have discussion actually working in test mode, just turn it off -#MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = True +MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = False # Need wiki for courseware views to work. TODO (vshnayder): shouldn't need it. WIKI_ENABLED = True From 5d5642673ce77c0bec0324fbd09e660b1797a550 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 12:58:02 -0500 Subject: [PATCH 0216/1392] Add new field to disable certificate download --- common/djangoapps/student/models.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 44b947c045..ba1977da5b 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -90,6 +90,7 @@ class UserProfile(models.Model): ) mailing_address = models.TextField(blank=True, null=True) goals = models.TextField(blank=True, null=True) + allow_certificate = models.BooleanField(default=1) def get_meta(self): js_str = self.meta @@ -402,11 +403,11 @@ class TestCenterRegistration(models.Model): def exam_authorization_count(self): # TODO: figure out if this should really go in the database (with a default value). return 1 - + @property def needs_uploading(self): return self.uploaded_at is None or self.uploaded_at < self.user_updated_at - + @classmethod def create(cls, testcenter_user, exam, accommodation_request): registration = cls(testcenter_user = testcenter_user) @@ -532,7 +533,7 @@ def get_testcenter_registration(user, course_id, exam_series_code): # nosetests thinks that anything with _test_ in the name is a test. # Correct this (https://nose.readthedocs.org/en/latest/finding_tests.html) get_testcenter_registration.__test__ = False - + def unique_id_for_user(user): """ Return a unique id for a user, suitable for inserting into From 734a8bd6e5e9d62512df0e41597d9a72c9271e2a Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Mon, 28 Jan 2013 15:07:44 -0500 Subject: [PATCH 0217/1392] make tests pass with cms config as well as lms --- .../djangoapps/course_groups/tests/tests.py | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/common/djangoapps/course_groups/tests/tests.py b/common/djangoapps/course_groups/tests/tests.py index 21fad8bbeb..86f0be0791 100644 --- a/common/djangoapps/course_groups/tests/tests.py +++ b/common/djangoapps/course_groups/tests/tests.py @@ -10,6 +10,25 @@ from course_groups.cohorts import (get_cohort, get_course_cohorts, from xmodule.modulestore.django import modulestore, _MODULESTORES +# NOTE: running this with the lms.envs.test config works without +# manually overriding the modulestore. However, running with +# cms.envs.test doesn't. + +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestCohorts(django.test.TestCase): @@ -77,7 +96,7 @@ class TestCohorts(django.test.TestCase): course = modulestore().get_course("edX/toy/2012_Fall") self.assertEqual(course.id, "edX/toy/2012_Fall") self.assertFalse(course.is_cohorted) - + user = User.objects.create(username="test", email="a@b.com") other_user = User.objects.create(username="test2", email="a2@b.com") From fba88db5fadf6ddc6729b419494efe8623eaf53b Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 15:10:35 -0500 Subject: [PATCH 0218/1392] Adding django-admin command for certificate_restriction --- .../management/commands/cert_restriction.py | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 common/djangoapps/student/management/commands/cert_restriction.py diff --git a/common/djangoapps/student/management/commands/cert_restriction.py b/common/djangoapps/student/management/commands/cert_restriction.py new file mode 100644 index 0000000000..a5de880980 --- /dev/null +++ b/common/djangoapps/student/management/commands/cert_restriction.py @@ -0,0 +1,102 @@ +from django.core.management.base import BaseCommand, CommandError +import os +from optparse import make_option +from student.models import UserProfile +import csv + + +class Command(BaseCommand): + + help = """ + Sets or gets certificate restrictions for users + from embargoed countries. + + Import a list of students to restrict certificate download + by setting "allow_certificate" to True in userprofile: + + $ ... cert_restriction --import path/to/userlist.csv + + CSV should be comma delimited with double quoted entries. + + Export a list of students who have "allow_certificate" in + userprofile set to True + + $ ... cert_restriction --export path/to/export.csv + + """ + + option_list = BaseCommand.option_list + ( + make_option('-i', '--import', + metavar='IMPORT_FILE', + dest='import', + default=False, + help='csv file to import, comma delimitted file with ' + 'double-quoted entries'), + make_option('-o', '--output', + metavar='EXPORT_FILE', + dest='output', + default=False, + help='csv file to export'), + make_option('-e', '--enable', + metavar='STUDENT', + dest='enable', + default=False, + help="enable a single student's certificate"), + make_option('-d', '--disable', + metavar='STUDENT', + dest='disable', + default=False, + help="disable a single student's certificate") + ) + + def handle(self, *args, **options): + + if options['output']: + + if os.path.exists(options['output']): + raise CommandError("File {0} already exists".format( + options['output'])) + disabled_users = UserProfile.objects.filter( + allow_certificate=False) + + with open(options['output'], 'w') as csvfile: + csvwriter = csv.writer(csvfile, delimiter=',', quotechar='"', + quoting=csv.QUOTE_MINIMAL) + for user in disabled_users: + csvwriter.writerow([user.username]) + + elif options['input']: + + if not os.path.exists(options['input']): + raise CommandError("File {0} does not exist".format( + options['input'])) + + print "Importing students from {0}".format(options['input']) + + students = None + with open(options['input']) as csvfile: + student_list = csv.reader(csvfile, delimiter=',', + quotechar='"') + students = [student[0] for student in student_list] + if not students: + raise CommandError( + "Unable to read student data from {0}".format( + options['input'])) + UserProfile.objects.filter(username__in=students).update( + allow_certificate=False) + + elif options['enable']: + + print "Enabling {0} for certificate download".format( + options['enable']) + cert_allow = UserProfile.objects.get(user=options['enable']) + cert_allow.allow_certificate = True + cert_allow.save() + + elif options['disable']: + + print "Disabling {0} for certificate download".format( + options['disable']) + cert_allow = UserProfile.objects.get(user=options['disable']) + cert_allow.allow_certificate = False + cert_allow.save() From 7918c35414ca2f6d9cfe7205b684902deaf43ae9 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Mon, 28 Jan 2013 15:29:55 -0500 Subject: [PATCH 0219/1392] fixing up tests --- .../courseware/tests/test_courses.py | 30 ++-- .../courseware/tests/test_module_render.py | 130 ++++++++++++------ lms/djangoapps/courseware/tests/test_views.py | 44 +++--- 3 files changed, 126 insertions(+), 78 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py index 2f4868b27b..91b6af4dfc 100644 --- a/lms/djangoapps/courseware/tests/test_courses.py +++ b/lms/djangoapps/courseware/tests/test_courses.py @@ -10,6 +10,7 @@ from student.models import CourseEnrollment import courseware.courses as courses from xmodule.modulestore.xml import XMLModuleStore from xmodule.modulestore.django import modulestore +from xmodule.modulestore import Location def xml_store_config(data_dir): return { @@ -28,34 +29,35 @@ TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class CoursesTestCase(TestCase): def setUp(self): - self.user = User.objects.create(username='dummy', password='123456', - email='test@mit.edu') - self.date = datetime.datetime(2013,1,22) - self.course_id = 'edx/toy/2012_Fall' - self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, - course_id = self.course_id, - created = self.date)[0] +## self.user = User.objects.create(username='dummy', password='123456', +## email='test@mit.edu') +## self.date = datetime.datetime(2013,1,22) +## self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, +## course_id = self.course_id, +## created = self.date)[0] self._MODULESTORES = {} + #self.course_id = 'edx/toy/2012_Fall' self.toy_course = modulestore().get_course('edX/toy/2012_Fall') def test_get_course_by_id(self): - courses.get_course_by_id("edx/toy/2012_Fall") + courses.get_course_by_id("edX/toy/2012_Fall") + @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class CoursesTests(TestCase): + # runs def setUp(self): self._MODULESTORES = {} - self.course_name = 'edX/toy/2012_Fall' + #self.course_id = 'edX/toy/2012_Fall' self.toy_course = modulestore().get_course('edX/toy/2012_Fall') - self.fake_user = User.objects.create(is_superuser=True) +## self.fake_user = User.objects.create(is_superuser=True) ''' no test written for get_request_for_thread ''' def test_get_course_by_id(self): - self.test_course_id = "edX/toy/2012_Fall" + #self.test_course_id = "edX/toy/2012_Fall" + courses.get_course_by_id("edX/toy/2012_Fall") # print modulestore().get_instance(test_course_id, Location('i4x', 'edx', 'toy', 'course', '2012_Fall')) - self.assertEqual(courses.get_course_by_id(self.test_course_id),modulestore().get_instance(self.test_course_id, Location('i4x', 'edX', 'toy', 'course', '2012_Fall'), None)) - - + #self.assertEqual(courses.get_course_by_id(self.test_course_id),modulestore().get_instance(self.test_course_id, Location('i4x', 'edX', 'toy', 'course', '2012_Fall'), None)) diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 925601ba37..3150450648 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -2,7 +2,9 @@ import logging from mock import MagicMock, patch import json import factory -import unittest +import unittest +from nose.tools import set_trace +from nose.plugins.skip import SkipTest from django.http import Http404, HttpResponse, HttpRequest from django.conf import settings @@ -11,22 +13,50 @@ from django.test.client import Client from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory +from django.core.urlresolvers import reverse -from courseware.models import StudentModule +from courseware.models import StudentModule, StudentModuleCache from xmodule.modulestore.exceptions import ItemNotFoundError +from xmodule.exceptions import NotFoundError from xmodule.modulestore import Location import courseware.module_render as render from override_settings import override_settings from xmodule.modulestore.django import modulestore, _MODULESTORES - +from xmodule.seq_module import SequenceModule +from courseware.tests.tests import PageLoader +from student.models import Registration class Stub: def __init__(self): pass -class ModuleRenderTestCase(TestCase): +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +class UserFactory(factory.Factory): + first_name = 'Test' + last_name = 'Robot' + is_staff = True + is_active = True + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +class ModuleRenderTestCase(PageLoader): def setUp(self): - self.location = ['tag', 'org', 'course', 'category', 'name'] + self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + self._MODULESTORES = {} + self.course_id = 'edX/toy/2012_Fall' + self.toy_course = modulestore().get_course(self.course_id) def test_toc_for_course(self): mock_course = MagicMock() @@ -37,19 +67,26 @@ class ModuleRenderTestCase(TestCase): mock_user.is_authenticated.return_value = False self.assertIsNone(render.toc_for_course(mock_user,'dummy', mock_course, 'dummy', 'dummy')) + # rest of tests are in class TestTOC def test_get_module(self): self.assertIsNone(render.get_module('dummyuser',None,\ 'invalid location',None,None)) - + #done def test__get_module(self): mock_user = MagicMock() - mock_user.is_authenticated.return_value = True - location = ['tag', 'org', 'course', 'category', 'name'] - #render._get_module(mock_user, + mock_user.is_authenticated.return_value = False + location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') + mock_request = MagicMock() + s = render._get_module(mock_user, mock_request, location, + 'dummy', 'edX/toy/2012_Fall') + self.assertIsInstance(s, SequenceModule) + # Don't know how to generate error in line 260 to test + # Can't tell if sequence module is an error? def test_get_instance_module(self): + # done mock_user = MagicMock() mock_user.is_authenticated.return_value = False self.assertIsNone(render.get_instance_module('dummy', mock_user, 'dummy', @@ -62,16 +99,28 @@ class ModuleRenderTestCase(TestCase): mock_module,'dummy')) def test_get_shared_instance_module(self): + raise SkipTest mock_user = MagicMock(User) mock_user.is_authenticated.return_value = False self.assertIsNone(render.get_shared_instance_module('dummy', mock_user, 'dummy', 'dummy')) mock_user_2 = MagicMock(User) mock_user_2.is_authenticated.return_value = True + mock_module = MagicMock() mock_module.shared_state_key = 'key' - self.assertIsInstance(render.get_shared_instance_module('dummy', mock_user, - mock_module, 'dummy'), StudentModule) + mock_module.location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') + mock_module.get_shared_state.return_value = '{}' + mock_cache = MagicMock() + mock_cache.lookup.return_value = False + #mock_cache._state = 'dummy' + #set_trace() + print mock_module.get_shared_state() + s = render.get_shared_instance_module(self.course_id, mock_user_2, + mock_module, mock_cache) + self.assertIsInstance(s, StudentModule) + # Problem: can't get code to take branch that creates StudentModule? + # Can't finish testing modx_dispatch def test_xqueue_callback(self): mock_request = MagicMock() @@ -90,9 +139,21 @@ class ModuleRenderTestCase(TestCase): xpackage_2 = {'xqueue_header': json.dumps({'lms_key':'secretkey'}), 'xqueue_body' : 'Message from grader'} mock_request_3.POST.copy.return_value = xpackage_2 -## self.assertRaises(Http404, render.xqueue_callback, mock_request_3, -## 'dummy', 0, 'dummy', 'dummy') - # continue later + # Roadblock: how to get user registered in class? + raise SkipTest + # + # trying alternate way of creating account in hopes of getting valid id + # Problem: Can't activate user + + self.student_name = '12' + self.password = 'foo' + self.email = 'test@mit.edu' + self.create_account(self.student_name, self.email, self.password) + self.activate_user(self.email) + request = RequestFactory().get('stuff') + # This doesn't work to install user + render.xqueue_callback(mock_request_3, self.course_id, + self.student_name, self.password, 'dummy') def test_modx_dispatch(self): self.assertRaises(Http404, render.modx_dispatch, 'dummy', 'dummy', @@ -117,12 +178,23 @@ class ModuleRenderTestCase(TestCase): (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE/(1000**2))})) mock_request_3 = MagicMock() mock_request_3.POST.copy.return_value = {} + mock_request_3.FILES = False + mock_request_3.user = UserFactory() inputfile_2 = Stub() inputfile_2.size = 1 inputfile_2.name = 'name' self.assertRaises(ItemNotFoundError, render.modx_dispatch, mock_request_3, 'dummy', self.location, 'toy') - # Deadend + self.assertRaises(Http404,render.modx_dispatch, mock_request_3, 'dummy', + self.location, self.course_id) +## student_module_cache = StudentModuleCache.cache_for_descriptor_descendents(self.course_id, +## mock_request_3.user, modulestore().get_instance(self.course_id, self.location)) +## get_shared_instance_module(course_id, request.user, instance, student_module_cache) + # 'goto_position' is the only dispatch that will work + mock_request_3.POST.copy.return_value = {'position':1} + self.assertIsInstance(render.modx_dispatch(mock_request_3, 'goto_position', + self.location, self.course_id), HttpResponse) + # keep going def test_preview_chemcalc(self): mock_request = MagicMock() @@ -159,33 +231,6 @@ class ModuleRenderTestCase(TestCase): self.assertEquals(render.get_score_bucket(11, 10), 'incorrect') self.assertEquals(render.get_score_bucket(-1, 10), 'incorrect') - -class MagicMockFactory(factory.Factory): - FACTORY_FOR = MagicMock - v = factory.LazyAttribute(i for i in [True, False, False]) - - - -def xml_store_config(data_dir): - return { - 'default': { - 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', - 'OPTIONS': { - 'data_dir': data_dir, - 'default_class': 'xmodule.hidden_module.HiddenDescriptor', - } - } -} - -TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT -TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) - -class UserFactory(factory.Factory): - first_name = 'Test' - last_name = 'Robot' - is_staff = True - is_active = True - @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestTOC(TestCase): """Check the Table of Contents for a course""" @@ -245,3 +290,4 @@ class TestTOC(TestCase): actual = render.toc_for_course(self.portal_user, request, self.toy_course, chapter, section) self.assertEqual(expected, actual) + diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 52496bcb6b..c901f87720 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -32,14 +32,6 @@ def skipped(func): class Stub(): pass -##def render_to_response(template_name, dictionary, context_instance=None, -## namespace='main', **kwargs): -## # The original returns HttpResponse -## print dir() -## print template_name -## print dictionary -## return HttpResponse('foo') - class UserFactory(factory.Factory): first_name = 'Test' last_name = 'Robot' @@ -100,7 +92,7 @@ class ViewsTestCase(TestCase): self.user = User.objects.create(username='dummy', password='123456', email='test@mit.edu') self.date = datetime.datetime(2013,1,22) - self.course_id = 'edx/toy/2012_Fall' + self.course_id = 'edX/toy/2012_Fall' self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, course_id = self.course_id, created = self.date)[0] @@ -109,6 +101,9 @@ class ViewsTestCase(TestCase): # This is a CourseDescriptor object self.toy_course = modulestore().get_course('edX/toy/2012_Fall') self.request_factory = RequestFactory() + chapter = 'Overview' + self.chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) + def test_user_groups(self): # depreciated function @@ -145,9 +140,19 @@ class ViewsTestCase(TestCase): mock_module, True) def test_index(self): - pass - #print modulestore() - #assert False + assert SkipTest + request = self.request_factory.get(self.chapter_url) + request.user = UserFactory() + response = views.index(request, self.course_id) + self.assertIsInstance(response, HttpResponse) + self.assertEqual(response.status_code, 302) + # views.index does not throw 404 if chapter, section, or position are + # not valid, which doesn't match index's comments + views.index(request, self.course_id, chapter='foo', section='bar', + position='baz') + request_2 = self.request_factory.get(self.chapter_url) + request_2.user = self.user + response = views.index(request_2, self.course_id) def test_registered_for_course(self): self.assertFalse(views.registered_for_course('Basketweaving', None)) @@ -159,9 +164,7 @@ class ViewsTestCase(TestCase): self.assertTrue(views.registered_for_course(mock_course, self.user)) def test_jump_to(self): - chapter = 'Overview' - chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) - request = self.request_factory.get(chapter_url) + request = self.request_factory.get(self.chapter_url) self.assertRaisesRegexp(Http404, 'Invalid location', views.jump_to, request, 'bar', ()) self.assertRaisesRegexp(Http404, 'No data*', views.jump_to, request, @@ -186,16 +189,14 @@ class ViewsTestCase(TestCase): def test_static_university_profile(self): # TODO - # Can't test unless have a valid template file + # Can't test unless havehttp://toastdriven.com/blog/2011/apr/10/guide-to-testing-in-django/ a valid template file raise SkipTest request = self.client.get('university_profile/edX') self.assertIsInstance(views.static_university_profile(request, 'edX'), HttpResponse) def test_university_profile(self): raise SkipTest - chapter = 'Overview' - chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) - request = self.request_factory.get(chapter_url) + request = self.request_factory.get(self.chapter_url) request.user = UserFactory() self.assertRaisesRegexp(Http404, 'University Profile*', views.university_profile, request, 'Harvard') @@ -207,15 +208,14 @@ class ViewsTestCase(TestCase): def test_syllabus(self): raise SkipTest - chapter = 'Overview' - chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) - request = self.request_factory.get(chapter_url) + request = self.request_factory.get(self.chapter_url) request.user = UserFactory() # Can't find valid template # TODO views.syllabus(request, 'edX/toy/2012_Fall') def test_render_notifications(self): + raise SkipTest request = self.request_factory.get('foo') #views.render_notifications(request, self.course_id, 'dummy') # TODO From 28a2dd9a18e1aafe14d26995ad0cfcacb83f6d6e Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 28 Jan 2013 16:33:28 -0500 Subject: [PATCH 0220/1392] support reordering of static tabs in studio --- cms/djangoapps/contentstore/views.py | 41 +++++++++++++++++++++++-- cms/static/coffee/src/views/tabs.coffee | 16 +++++++++- cms/urls.py | 1 + 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index 816ccab091..326b47ee64 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -903,6 +903,36 @@ def static_pages(request, org, course, coursename): def edit_static(request, org, course, coursename): return render_to_response('edit-static-page.html', {}) + +@login_required +@expect_json +def reorder_tabs(request): + tabs = request.POST['tabs'] + logging.debug('tabs = {0} {1}'.format(tabs.__class__, tabs)) + + if len(tabs) > 0: + course = get_course_for_item(tabs[0]) + + if not has_access(request.user, course.location): + raise PermissionDenied() + + # first filter out all non-static tabs from the tabs list + course_tabs = [t for t in course.tabs if t['type'] != 'static_tab'] + + # OK, re-assemble the static tabs in the new order + for tab in tabs: + item = modulestore('direct').get_item(Location(tab)) + + course_tabs.append({ 'type':'static_tab', + 'name' : item.metadata.get('display_name'), + 'url_slug' : item.location.name} + ) + + course.tabs = course_tabs + modulestore('direct').update_metadata(course.location, course.metadata) + + return HttpResponse() + @login_required @ensure_csrf_cookie def edit_tabs(request, org, course, coursename): @@ -914,12 +944,19 @@ def edit_tabs(request, org, course, coursename): if not has_access(request.user, location): raise PermissionDenied() - static_tabs = modulestore('direct').get_items(static_tabs_loc) - # see tabs have been uninitialized (e.g. supporing courses created before tab support in studio) if course_item.tabs is None or len(course_item.tabs) == 0: initialize_course_tabs(course_item) + # first get all static tabs from the tabs list + # we do this because this is also the order in which items are displayed in the LMS + static_tabs_refs = [t for t in course_item.tabs if t['type'] == 'static_tab'] + + static_tabs = [] + for static_tab_ref in static_tabs_refs: + static_tab_loc = Location(location)._replace(category='static_tab', name=static_tab_ref['url_slug']) + static_tabs.append(modulestore('direct').get_item(static_tab_loc)) + components = [ static_tab.location.url() for static_tab diff --git a/cms/static/coffee/src/views/tabs.coffee b/cms/static/coffee/src/views/tabs.coffee index 1fbc6ffa7f..3799eb25ee 100644 --- a/cms/static/coffee/src/views/tabs.coffee +++ b/cms/static/coffee/src/views/tabs.coffee @@ -15,7 +15,7 @@ class CMS.Views.TabsEdit extends Backbone.View @$('.components').sortable( handle: '.drag-handle' - update: (event, ui) => alert 'not yet implemented!' + update: @tabMoved helper: 'clone' opacity: '0.5' placeholder: 'component-placeholder' @@ -24,6 +24,20 @@ class CMS.Views.TabsEdit extends Backbone.View items: '> .component' ) + tabMoved: (event, ui) => + tabs = [] + @$('.component').each((idx, element) => + tabs.push($(element).data('id')) + ) + $.ajax({ + type:'POST', + url: '/reorder_tabs', + data: JSON.stringify({ + tabs : tabs + }), + contentType: 'application/json' + }) + addNewTab: (event) => event.preventDefault() diff --git a/cms/urls.py b/cms/urls.py index 6f8736551b..2b329dc16b 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -17,6 +17,7 @@ urlpatterns = ('', url(r'^publish_draft$', 'contentstore.views.publish_draft', name='publish_draft'), url(r'^unpublish_unit$', 'contentstore.views.unpublish_unit', name='unpublish_unit'), url(r'^create_new_course', 'contentstore.views.create_new_course', name='create_new_course'), + url(r'^reorder_tabs', 'contentstore.views.reorder_tabs', name='reorder_tabs'), url(r'^(?P[^/]+)/(?P[^/]+)/course/(?P[^/]+)$', 'contentstore.views.course_index', name='course_index'), From bae2162fa065a242ce91bbb8828a13621f26331b Mon Sep 17 00:00:00 2001 From: Brian Wilson Date: Mon, 28 Jan 2013 18:29:34 -0500 Subject: [PATCH 0221/1392] add pearson_dump command. Modify rule for determining authorization transaction type. --- .../management/commands/pearson_dump.py | 76 +++++++++++++++++++ common/djangoapps/student/models.py | 36 ++++++++- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 common/djangoapps/student/management/commands/pearson_dump.py diff --git a/common/djangoapps/student/management/commands/pearson_dump.py b/common/djangoapps/student/management/commands/pearson_dump.py new file mode 100644 index 0000000000..28931dc468 --- /dev/null +++ b/common/djangoapps/student/management/commands/pearson_dump.py @@ -0,0 +1,76 @@ +from optparse import make_option +from json import dump + +from django.core.management.base import BaseCommand, CommandError + +from student.models import TestCenterRegistration + + +class Command(BaseCommand): + + args = '' + help = """ + Dump information as JSON from TestCenterRegistration tables, including username and status. + """ + + option_list = BaseCommand.option_list + ( + make_option('--course_id', + action='store', + dest='course_id', + help='Specify a particular course.'), + make_option('--exam_series_code', + action='store', + dest='exam_series_code', + default=None, + help='Specify a particular exam, using the Pearson code'), + make_option('--accommodation_pending', + action='store_true', + dest='accommodation_pending', + default=False, + ), + ) + + def handle(self, *args, **options): + if len(args) < 1: + raise CommandError("Missing single argument: output JSON file") + + # get output location: + outputfile = args[0] + + # construct the query object to dump: + registrations = TestCenterRegistration.objects.all() + if 'course_id' in options and options['course_id']: + registrations = registrations.filter(course_id=options['course_id']) + if 'exam_series_code' in options and options['exam_series_code']: + registrations = registrations.filter(exam_series_code=options['exam_series_code']) + + # collect output: + output = [] + for registration in registrations: + if 'accommodation_pending' in options and options['accommodation_pending'] and not registration.accommodation_is_pending: + continue + record = {'username' : registration.testcenter_user.user.username, + 'email' : registration.testcenter_user.email, + 'first_name' : registration.testcenter_user.first_name, + 'last_name' : registration.testcenter_user.last_name, + 'client_candidate_id' : registration.client_candidate_id, + 'client_authorization_id' : registration.client_authorization_id, + 'course_id' : registration.course_id, + 'exam_series_code' : registration.exam_series_code, + 'accommodation_request' : registration.accommodation_request, + 'accommodation_code' : registration.accommodation_code, + 'registration_status' : registration.registration_status(), + 'demographics_status' : registration.demographics_status(), + 'accommodation_status' : registration.accommodation_status(), + } + if len(registration.upload_error_message) > 0: + record['registration_error'] = registration.upload_error_message + if registration.needs_uploading: + record['needs_uploading'] = True + + output.append(record) + + # dump output: + with open(outputfile, 'w') as outfile: + dump(output, outfile) + diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 44b947c045..d35045ed39 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -387,6 +387,12 @@ class TestCenterRegistration(models.Model): return 'Update' elif self.uploaded_at is None: return 'Add' + elif self.registration_is_rejected: + # Assume that if the registration was rejected before, + # it is more likely this is the (first) correction + # than a second correction in flight before the first was + # processed. + return 'Add' else: # TODO: decide what to send when we have uploaded an initial version, # but have not received confirmation back from that upload. If the @@ -400,7 +406,8 @@ class TestCenterRegistration(models.Model): @property def exam_authorization_count(self): - # TODO: figure out if this should really go in the database (with a default value). + # Someday this could go in the database (with a default value). But at present, + # we do not expect anyone to be authorized to take an exam more than once. return 1 @property @@ -499,6 +506,33 @@ class TestCenterRegistration(models.Model): def registration_signup_url(self): return settings.PEARSONVUE_SIGNINPAGE_URL + def demographics_status(self): + if self.demographics_is_accepted: + return "Accepted" + elif self.demographics_is_rejected: + return "Rejected" + else: + return "Pending" + + def accommodation_status(self): + if self.accommodation_is_skipped: + return "Skipped" + elif self.accommodation_is_accepted: + return "Accepted" + elif self.accommodation_is_rejected: + return "Rejected" + else: + return "Pending" + + def registration_status(self): + if self.registration_is_accepted: + return "Accepted" + elif self.registration_is_rejected: + return "Rejected" + else: + return "Pending" + + class TestCenterRegistrationForm(ModelForm): class Meta: model = TestCenterRegistration From 7e033d0265851633080e52a961da2116575847f8 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 19:28:24 -0500 Subject: [PATCH 0222/1392] django command for certificate restriction --- .../migrations/0024_add_allow_certificate.py | 172 ++++++++++++++++++ .../management/commands/cert_whitelist.py | 73 ++++++++ .../migrations/0014_adding_whitelist.py | 89 +++++++++ lms/djangoapps/certificates/models.py | 9 + lms/djangoapps/certificates/queue.py | 106 +++-------- 5 files changed, 372 insertions(+), 77 deletions(-) create mode 100644 common/djangoapps/student/migrations/0024_add_allow_certificate.py create mode 100644 lms/djangoapps/certificates/management/commands/cert_whitelist.py create mode 100644 lms/djangoapps/certificates/migrations/0014_adding_whitelist.py diff --git a/common/djangoapps/student/migrations/0024_add_allow_certificate.py b/common/djangoapps/student/migrations/0024_add_allow_certificate.py new file mode 100644 index 0000000000..fb3a97cd4b --- /dev/null +++ b/common/djangoapps/student/migrations/0024_add_allow_certificate.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'UserProfile.allow_certificate' + db.add_column('auth_userprofile', 'allow_certificate', + self.gf('django.db.models.fields.BooleanField')(default=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'UserProfile.allow_certificate' + db.delete_column('auth_userprofile', 'allow_certificate') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'student.courseenrollment': { + 'Meta': {'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'}, + 'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'student.courseenrollmentallowed': { + 'Meta': {'unique_together': "(('email', 'course_id'),)", 'object_name': 'CourseEnrollmentAllowed'}, + 'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'student.pendingemailchange': { + 'Meta': {'object_name': 'PendingEmailChange'}, + 'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'new_email': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}) + }, + 'student.pendingnamechange': { + 'Meta': {'object_name': 'PendingNameChange'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'new_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'rationale': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}) + }, + 'student.registration': { + 'Meta': {'object_name': 'Registration', 'db_table': "'auth_registration'"}, + 'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + }, + 'student.testcenterregistration': { + 'Meta': {'object_name': 'TestCenterRegistration'}, + 'accommodation_code': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'accommodation_request': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '1024', 'blank': 'True'}), + 'authorization_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'db_index': 'True'}), + 'client_authorization_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}), + 'confirmed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), + 'course_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), + 'eligibility_appointment_date_first': ('django.db.models.fields.DateField', [], {'db_index': 'True'}), + 'eligibility_appointment_date_last': ('django.db.models.fields.DateField', [], {'db_index': 'True'}), + 'exam_series_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'processed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), + 'testcenter_user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['student.TestCenterUser']"}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'upload_error_message': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), + 'upload_status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '20', 'blank': 'True'}), + 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), + 'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}) + }, + 'student.testcenteruser': { + 'Meta': {'object_name': 'TestCenterUser'}, + 'address_1': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'address_2': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}), + 'address_3': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}), + 'candidate_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'db_index': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), + 'client_candidate_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), + 'company_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'confirmed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), + 'country': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), + 'extension': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '8', 'blank': 'True'}), + 'fax': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'fax_country_code': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}), + 'middle_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'phone': ('django.db.models.fields.CharField', [], {'max_length': '35'}), + 'phone_country_code': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'}), + 'postal_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '16', 'blank': 'True'}), + 'processed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), + 'salutation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '20', 'blank': 'True'}), + 'suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'upload_error_message': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), + 'upload_status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '20', 'blank': 'True'}), + 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'unique': 'True'}), + 'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}) + }, + 'student.userprofile': { + 'Meta': {'object_name': 'UserProfile', 'db_table': "'auth_userprofile'"}, + 'allow_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'courseware': ('django.db.models.fields.CharField', [], {'default': "'course.xml'", 'max_length': '255', 'blank': 'True'}), + 'gender': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}), + 'goals': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}), + 'level_of_education': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}), + 'location': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}), + 'mailing_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'meta': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}), + 'year_of_birth': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}) + }, + 'student.usertestgroup': { + 'Meta': {'object_name': 'UserTestGroup'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}) + } + } + + complete_apps = ['student'] \ No newline at end of file diff --git a/lms/djangoapps/certificates/management/commands/cert_whitelist.py b/lms/djangoapps/certificates/management/commands/cert_whitelist.py new file mode 100644 index 0000000000..73f6338577 --- /dev/null +++ b/lms/djangoapps/certificates/management/commands/cert_whitelist.py @@ -0,0 +1,73 @@ +from django.core.management.base import BaseCommand, CommandError +import os +from optparse import make_option +from student.models import UserProfile +from certificates.models import CertificateWhitelist +from django.contrib.auth.models import User + +class Command(BaseCommand): + + help = """ + Sets or gets the certificate whitelist for a given + user/course + + Add a user to the whitelist for a course + + $ ... cert_whitelist --add joe -c "MITx/6.002x/2012_Fall" + + Remove a user from the whitelist for a course + + $ ... cert_whitelist --del joe -c "MITx/6.002x/2012_Fall" + + Print out who is whitelisted for a course + + $ ... cert_whitelist -c "MITx/6.002x/2012_Fall" + + """ + + option_list = BaseCommand.option_list + ( + make_option('-a', '--add', + metavar='USER', + dest='add', + default=False, + help='user to add to the certificate whitelist'), + + make_option('-d', '--del', + metavar='USER', + dest='del', + default=False, + help='user to remove from the certificate whitelist'), + + make_option('-c', '--course-id', + metavar='COURSE_ID', + dest='course_id', + default=False, + help="course id to query"), + ) + + def handle(self, *args, **options): + course_id = options['course_id'] + if not course_id: + raise CommandError("You must specify a course-id") + if options['add'] and options['del']: + raise CommandError("Either remove or add a user, not both") + + if options['add'] or options['del']: + user_str = options['add'] or options['del'] + if '@' in user_str: + user = User.objects.get(email=user_str) + else: + user = User.objects.get(username=user_str) + + cert_whitelist, created = CertificateWhitelist.objects.get_or_create( + user=user, course_id=course_id) + if options['add']: + cert_whitelist.whitelist = True + elif options['del']: + cert_whitelist.whitelist = False + cert_whitelist.save() + + whitelist = CertificateWhitelist.objects.all() + print "User whitelist for course {0}:\n{1}".format(course_id, + '\n'.join([ "{0} {1} {2}".format(u.user.username, u.user.email, u.whitelist) for u in whitelist])) + diff --git a/lms/djangoapps/certificates/migrations/0014_adding_whitelist.py b/lms/djangoapps/certificates/migrations/0014_adding_whitelist.py new file mode 100644 index 0000000000..1bd4d994cf --- /dev/null +++ b/lms/djangoapps/certificates/migrations/0014_adding_whitelist.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'CertificateWhitelist' + db.create_table('certificates_certificatewhitelist', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('course_id', self.gf('django.db.models.fields.CharField')(default='', max_length=255, blank=True)), + ('whitelist', self.gf('django.db.models.fields.BooleanField')(default=False)), + )) + db.send_create_signal('certificates', ['CertificateWhitelist']) + + + def backwards(self, orm): + # Deleting model 'CertificateWhitelist' + db.delete_table('certificates_certificatewhitelist') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'certificates.certificatewhitelist': { + 'Meta': {'object_name': 'CertificateWhitelist'}, + 'course_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'whitelist': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'certificates.generatedcertificate': { + 'Meta': {'unique_together': "(('user', 'course_id'),)", 'object_name': 'GeneratedCertificate'}, + 'course_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}), + 'created_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now_add': 'True', 'blank': 'True'}), + 'distinction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), + 'download_uuid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'error_reason': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}), + 'grade': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '5', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'modified_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'unavailable'", 'max_length': '32'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'verify_uuid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['certificates'] \ No newline at end of file diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index b9bd55b9af..c8e1dd047f 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -46,8 +46,13 @@ class CertificateStatuses(object): deleted = 'deleted' downloadable = 'downloadable' notpassing = 'notpassing' + restricted = 'restricted' error = 'error' +class CertificateWhitelist(models.Model): + user = models.ForeignKey(User) + course_id = models.CharField(max_length=255, blank=True, default='') + whitelist = models.BooleanField(default=0) class GeneratedCertificate(models.Model): user = models.ForeignKey(User) @@ -87,6 +92,10 @@ def certificate_status_for_student(student, course_id): deleted - The certificate has been deleted. downloadable - The certificate is available for download. notpassing - The student was graded but is not passing + restricted - The student is on the restricted embargo list and + should not be issued a certificate. This will + be set if allow_certificate is set to False in + the userprofile table If the status is "downloadable", the dictionary also contains "download_url". diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index b9316220fa..cdf84bba2f 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -1,6 +1,7 @@ from certificates.models import GeneratedCertificate from certificates.models import certificate_status_for_student from certificates.models import CertificateStatuses as status +from certificates.models import CertificateWhitelist from courseware import grades, courses from django.test.client import RequestFactory @@ -71,6 +72,8 @@ class XQueueCertInterface(object): settings.XQUEUE_INTERFACE['django_auth'], requests_auth, ) + self.whitelist = CertificateWhitelist.objects.all() + self.restricted = UserProfile.objects.filter(allow_certificate=False) def regen_cert(self, student, course_id): """ @@ -93,49 +96,7 @@ class XQueueCertInterface(object): """ - VALID_STATUSES = [status.error, status.downloadable] - - cert_status = certificate_status_for_student( - student, course_id)['status'] - - if cert_status in VALID_STATUSES: - # grade the student - course = courses.get_course_by_id(course_id) - grade = grades.grade(student, self.request, course) - - profile = UserProfile.objects.get(user=student) - try: - cert = GeneratedCertificate.objects.get( - user=student, course_id=course_id) - except GeneratedCertificate.DoesNotExist: - logger.critical("Attempting to regenerate a certificate" - "for a user that doesn't have one") - raise - - if grade['grade'] is not None: - - cert.status = status.regenerating - cert.name = profile.name - - contents = { - 'action': 'regen', - 'delete_verify_uuid': cert.verify_uuid, - 'delete_download_uuid': cert.download_uuid, - 'username': cert.user.username, - 'course_id': cert.course_id, - 'name': profile.name, - } - - key = cert.key - self._send_to_xqueue(contents, key) - cert.save() - - else: - cert.status = status.notpassing - cert.name = profile.name - cert.save() - - return cert_status + raise NotImplementedError def del_cert(self, student, course_id): @@ -152,34 +113,7 @@ class XQueueCertInterface(object): """ - VALID_STATUSES = [status.error, status.downloadable] - - cert_status = certificate_status_for_student( - student, course_id)['status'] - - if cert_status in VALID_STATUSES: - - try: - cert = GeneratedCertificate.objects.get( - user=student, course_id=course_id) - except GeneratedCertificate.DoesNotExist: - logger.warning("Attempting to delete a certificate" - "for a user that doesn't have one") - raise - - cert.status = status.deleting - - contents = { - 'action': 'delete', - 'delete_verify_uuid': cert.verify_uuid, - 'delete_download_uuid': cert.download_uuid, - 'username': cert.user.username, - } - - key = cert.key - self._send_to_xqueue(contents, key) - cert.save() - return cert_status + raise NotImplementedError def add_cert(self, student, course_id): """ @@ -189,14 +123,18 @@ class XQueueCertInterface(object): course_id - courseenrollment.course_id (string) Request a new certificate for a student. - Will change the certificate status to 'deleting'. + Will change the certificate status to 'generating'. Certificate must be in the 'unavailable', 'error', 'deleted' or 'generating' state. - If a student has a passing grade a request will made - for a new cert + If a student has a passing grade or is in the whitelist + table for the course a request will made for a new cert. + If a student has allow_certificate set to False in the + userprofile table the status will change to 'restricted' + + If a student does not have a passing grade the status will change to status.notpassing @@ -210,16 +148,30 @@ class XQueueCertInterface(object): cert_status = certificate_status_for_student( student, course_id)['status'] - + if cert_status in VALID_STATUSES: # grade the student course = courses.get_course_by_id(course_id) - grade = grades.grade(student, self.request, course) profile = UserProfile.objects.get(user=student) + + cert, created = GeneratedCertificate.objects.get_or_create( user=student, course_id=course_id) - if grade['grade'] is not None: + grade = grades.grade(student, self.request, course) + whitelist = self.whitelist.filter( + user=student, course_id=course_id, whitelist=True).exists() + + if whitelist or grade['grade'] is not None: + + # check to see whether the student is on the + # the embargoed country restricted list + if self.restricted.filter(user=student).exists(): + cert_status = status.restricted + cert.status = cert_status + cert.save() + return cert.status + cert_status = status.generating key = make_hashkey(random.random()) From 666828f71aaf571546e332bab70a2067315d5859 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 19:28:47 -0500 Subject: [PATCH 0223/1392] Command for certificate whitelist --- .../management/commands/cert_whitelist.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lms/djangoapps/certificates/management/commands/cert_whitelist.py b/lms/djangoapps/certificates/management/commands/cert_whitelist.py index 73f6338577..94dfda74a6 100644 --- a/lms/djangoapps/certificates/management/commands/cert_whitelist.py +++ b/lms/djangoapps/certificates/management/commands/cert_whitelist.py @@ -1,10 +1,9 @@ from django.core.management.base import BaseCommand, CommandError -import os from optparse import make_option -from student.models import UserProfile from certificates.models import CertificateWhitelist from django.contrib.auth.models import User + class Command(BaseCommand): help = """ @@ -16,12 +15,12 @@ class Command(BaseCommand): $ ... cert_whitelist --add joe -c "MITx/6.002x/2012_Fall" Remove a user from the whitelist for a course - + $ ... cert_whitelist --del joe -c "MITx/6.002x/2012_Fall" Print out who is whitelisted for a course - $ ... cert_whitelist -c "MITx/6.002x/2012_Fall" + $ ... cert_whitelist -c "MITx/6.002x/2012_Fall" """ @@ -37,7 +36,7 @@ class Command(BaseCommand): dest='del', default=False, help='user to remove from the certificate whitelist'), - + make_option('-c', '--course-id', metavar='COURSE_ID', dest='course_id', @@ -50,7 +49,7 @@ class Command(BaseCommand): if not course_id: raise CommandError("You must specify a course-id") if options['add'] and options['del']: - raise CommandError("Either remove or add a user, not both") + raise CommandError("Either remove or add a user, not both") if options['add'] or options['del']: user_str = options['add'] or options['del'] @@ -59,8 +58,9 @@ class Command(BaseCommand): else: user = User.objects.get(username=user_str) - cert_whitelist, created = CertificateWhitelist.objects.get_or_create( - user=user, course_id=course_id) + cert_whitelist, created = \ + CertificateWhitelist.objects.get_or_create( + user=user, course_id=course_id) if options['add']: cert_whitelist.whitelist = True elif options['del']: @@ -68,6 +68,7 @@ class Command(BaseCommand): cert_whitelist.save() whitelist = CertificateWhitelist.objects.all() - print "User whitelist for course {0}:\n{1}".format(course_id, - '\n'.join([ "{0} {1} {2}".format(u.user.username, u.user.email, u.whitelist) for u in whitelist])) - + print "User whitelist for course {0}:\n{1}".format(course_id, + '\n'.join(["{0} {1} {2}".format( + u.user.username, u.user.email, u.whitelist) + for u in whitelist])) From e81394c2b0baee2e0b0a4c09d3ff7503c6010c4a Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 19:29:13 -0500 Subject: [PATCH 0224/1392] Adding new model for certificate whitelist --- lms/djangoapps/certificates/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index c8e1dd047f..02e8ab0c5f 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -92,7 +92,7 @@ def certificate_status_for_student(student, course_id): deleted - The certificate has been deleted. downloadable - The certificate is available for download. notpassing - The student was graded but is not passing - restricted - The student is on the restricted embargo list and + restricted - The student is on the restricted embargo list and should not be issued a certificate. This will be set if allow_certificate is set to False in the userprofile table From e9722b259b117ab8fb4e79e9ad611a7469044b16 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 19:29:53 -0500 Subject: [PATCH 0225/1392] Removing whitespace --- lms/djangoapps/certificates/queue.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index cdf84bba2f..f6b5943564 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -134,7 +134,7 @@ class XQueueCertInterface(object): If a student has allow_certificate set to False in the userprofile table the status will change to 'restricted' - + If a student does not have a passing grade the status will change to status.notpassing @@ -148,7 +148,7 @@ class XQueueCertInterface(object): cert_status = certificate_status_for_student( student, course_id)['status'] - + if cert_status in VALID_STATUSES: # grade the student course = courses.get_course_by_id(course_id) From 0c43e69c00cee0a7d6a71dc39222056fe41baaa0 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 19:30:40 -0500 Subject: [PATCH 0226/1392] command for certificate restriction (embargoed countries) --- .../management/commands/cert_restriction.py | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/common/djangoapps/student/management/commands/cert_restriction.py b/common/djangoapps/student/management/commands/cert_restriction.py index a5de880980..81405de156 100644 --- a/common/djangoapps/student/management/commands/cert_restriction.py +++ b/common/djangoapps/student/management/commands/cert_restriction.py @@ -9,15 +9,13 @@ class Command(BaseCommand): help = """ Sets or gets certificate restrictions for users - from embargoed countries. - - Import a list of students to restrict certificate download - by setting "allow_certificate" to True in userprofile: - - $ ... cert_restriction --import path/to/userlist.csv + from embargoed countries. (allow_certificate in + userprofile) CSV should be comma delimited with double quoted entries. + $ ... cert_restriction --import path/to/userlist.csv + Export a list of students who have "allow_certificate" in userprofile set to True @@ -50,7 +48,6 @@ class Command(BaseCommand): ) def handle(self, *args, **options): - if options['output']: if os.path.exists(options['output']): @@ -63,33 +60,34 @@ class Command(BaseCommand): csvwriter = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) for user in disabled_users: - csvwriter.writerow([user.username]) + csvwriter.writerow([user.user.username]) - elif options['input']: + elif options['import']: - if not os.path.exists(options['input']): + if not os.path.exists(options['import']): raise CommandError("File {0} does not exist".format( - options['input'])) + options['import'])) - print "Importing students from {0}".format(options['input']) + print "Importing students from {0}".format(options['import']) students = None - with open(options['input']) as csvfile: + with open(options['import']) as csvfile: student_list = csv.reader(csvfile, delimiter=',', quotechar='"') students = [student[0] for student in student_list] if not students: raise CommandError( "Unable to read student data from {0}".format( - options['input'])) - UserProfile.objects.filter(username__in=students).update( + options['import'])) + UserProfile.objects.filter(user__username__in=students).update( allow_certificate=False) elif options['enable']: print "Enabling {0} for certificate download".format( options['enable']) - cert_allow = UserProfile.objects.get(user=options['enable']) + cert_allow = UserProfile.objects.get( + user__username=options['enable']) cert_allow.allow_certificate = True cert_allow.save() @@ -97,6 +95,7 @@ class Command(BaseCommand): print "Disabling {0} for certificate download".format( options['disable']) - cert_allow = UserProfile.objects.get(user=options['disable']) + cert_allow = UserProfile.objects.get( + user__username=options['disable']) cert_allow.allow_certificate = False cert_allow.save() From 289301e0ea29962b6e25377c9302a491ff20acdb Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Mon, 28 Jan 2013 19:38:51 -0500 Subject: [PATCH 0227/1392] adding more to help string --- .../student/management/commands/cert_restriction.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/common/djangoapps/student/management/commands/cert_restriction.py b/common/djangoapps/student/management/commands/cert_restriction.py index 81405de156..c43ff05f3e 100644 --- a/common/djangoapps/student/management/commands/cert_restriction.py +++ b/common/djangoapps/student/management/commands/cert_restriction.py @@ -19,7 +19,15 @@ class Command(BaseCommand): Export a list of students who have "allow_certificate" in userprofile set to True - $ ... cert_restriction --export path/to/export.csv + $ ... cert_restriction --output path/to/export.csv + + Enable a single user so she is not on the restricted list + + $ ... cert_restriction -e user + + Disable a single user so she is on the restricted list + + $ ... cert_restriction -d user """ From 5a4c0fb9078a5f1d146197cacf1fd3b5e01eb4fb Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Tue, 29 Jan 2013 09:38:59 -0500 Subject: [PATCH 0228/1392] imports should have a marketing video. Treat it as a warning as every course might not have one. --- .../xmodule/xmodule/modulestore/xml_importer.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py index fa45f92dfc..7658d699d4 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py @@ -247,7 +247,7 @@ def remap_namespace(module, target_location_namespace): return module -def validate_category_hierarcy(module_store, course_id, parent_category, expected_child_category): +def validate_category_hierarchy(module_store, course_id, parent_category, expected_child_category): err_cnt = 0 parents = [] @@ -324,11 +324,18 @@ def perform_xlint(data_dir, course_dirs, for course_id in module_store.modules.keys(): # constrain that courses only have 'chapter' children - err_cnt += validate_category_hierarcy(module_store, course_id, "course", "chapter") + err_cnt += validate_category_hierarchy(module_store, course_id, "course", "chapter") # constrain that chapters only have 'sequentials' - err_cnt += validate_category_hierarcy(module_store, course_id, "chapter", "sequential") + err_cnt += validate_category_hierarchy(module_store, course_id, "chapter", "sequential") # constrain that sequentials only have 'verticals' - err_cnt += validate_category_hierarcy(module_store, course_id, "sequential", "vertical") + err_cnt += validate_category_hierarchy(module_store, course_id, "sequential", "vertical") + + # check for a presence of a course marketing video + location_elements = course_id.split('/') + if Location(['i4x', location_elements[0], location_elements[1], 'about', 'video', None]) not in module_store.modules[course_id]: + print "WARN: Missing course marketing video. It is recommended that every course have a marketing video." + warn_cnt += 1 + print "\n\n------------------------------------------\nVALIDATION SUMMARY: {0} Errors {1} Warnings\n".format(err_cnt, warn_cnt) From 74839663ff163576bef15ac951c6eba1a6d6dddf Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 10:12:39 -0500 Subject: [PATCH 0229/1392] added cms/djangoapps/contentstore/test/tests.py --- .../contentstore/tests/test_views.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 cms/djangoapps/contentstore/tests/test_views.py diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py new file mode 100644 index 0000000000..f513eef7f9 --- /dev/null +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -0,0 +1,50 @@ +import logging +from mock import MagicMock, patch +import json +import factory +import unittest +from nose.tools import set_trace +from nose.plugins.skip import SkipTest + +from django.http import Http404, HttpResponse, HttpRequest +from django.conf import settings +from django.contrib.auth.models import User +from django.test.client import Client +from django.conf import settings +from django.test import TestCase +from django.test.client import RequestFactory + +import cms.djangoapps.contentstore.views as views + +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +class UserFactory(factory.Factory): + first_name = 'Test' + last_name = 'Robot' + is_staff = True + is_active = True + is_authenticated = True + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +class ViewsTestCase(TestCase): + def setUp(self): + self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + self._MODULESTORES = {} + self.course_id = 'edX/toy/2012_Fall' + self.toy_course = modulestore().get_course(self.course_id) + + def test_has_access(self): + user = UserFactory() + views.has_access(user, self.location) From 09ab52bc946915d43cdf7dc29ae6947b91871307 Mon Sep 17 00:00:00 2001 From: Brian Wilson Date: Tue, 29 Jan 2013 10:21:41 -0500 Subject: [PATCH 0230/1392] fix log message in pearson import --- .../student/management/commands/pearson_import_conf_zip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/djangoapps/student/management/commands/pearson_import_conf_zip.py b/common/djangoapps/student/management/commands/pearson_import_conf_zip.py index 9c3a34a90c..d94c3ba863 100644 --- a/common/djangoapps/student/management/commands/pearson_import_conf_zip.py +++ b/common/djangoapps/student/management/commands/pearson_import_conf_zip.py @@ -65,7 +65,7 @@ class Command(BaseCommand): else: try: registration = TestCenterRegistration.objects.get(client_authorization_id=client_authorization_id) - Command.datadog_error("Found authorization record for user {}".format(registration.testcenter_user.user.username), eacfile) + Command.datadog_error("Found authorization record for user {}".format(registration.testcenter_user.user.username), eacfile.name) # now update the record: registration.upload_status = row['Status'] registration.upload_error_message = row['Message'] From dbc0f353c55e81a92eb8d6751f6b20b0818356ce Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Tue, 29 Jan 2013 10:22:58 -0500 Subject: [PATCH 0231/1392] cert_status temporary assignment removed --- lms/djangoapps/certificates/queue.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index f6b5943564..2150f1066c 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -167,8 +167,7 @@ class XQueueCertInterface(object): # check to see whether the student is on the # the embargoed country restricted list if self.restricted.filter(user=student).exists(): - cert_status = status.restricted - cert.status = cert_status + cert.status = status.restricted cert.save() return cert.status From 415ebec8797b2da6044254d8523851fca905982d Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Tue, 29 Jan 2013 10:24:29 -0500 Subject: [PATCH 0232/1392] renaming whitelist to is_whitelisted --- lms/djangoapps/certificates/queue.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index 2150f1066c..d4e96f85be 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -159,10 +159,10 @@ class XQueueCertInterface(object): user=student, course_id=course_id) grade = grades.grade(student, self.request, course) - whitelist = self.whitelist.filter( + is_whitelisted = self.whitelist.filter( user=student, course_id=course_id, whitelist=True).exists() - if whitelist or grade['grade'] is not None: + if is_whitelisted or grade['grade'] is not None: # check to see whether the student is on the # the embargoed country restricted list From 4b0999939b5226fbc74660f6444be5be6c10f643 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Tue, 29 Jan 2013 10:26:21 -0500 Subject: [PATCH 0233/1392] Adding docstring to CertificateWhitelist model --- lms/djangoapps/certificates/models.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 02e8ab0c5f..334200d348 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -50,6 +50,13 @@ class CertificateStatuses(object): error = 'error' class CertificateWhitelist(models.Model): + """ + Tracks students who are whitelisted, all users + in this table will always qualify for a certificate + regardless of their grade unless they are on the + embargoed country restriction list + (allow_certificate set to False in userprofile). + """ user = models.ForeignKey(User) course_id = models.CharField(max_length=255, blank=True, default='') whitelist = models.BooleanField(default=0) From 0f39e04697295c950a5a6d92ac2fa5562ae99da8 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Tue, 29 Jan 2013 10:27:53 -0500 Subject: [PATCH 0234/1392] Adding certificate restriction lookup If certificate status is 'restricted' the grade and survey link will be shown, the download link will not --- common/djangoapps/student/views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 61b49e6022..b583599e97 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -135,7 +135,7 @@ def cert_info(user, course): Get the certificate info needed to render the dashboard section for the given student and course. Returns a dictionary with keys: - 'status': one of 'generating', 'ready', 'notpassing', 'processing' + 'status': one of 'generating', 'ready', 'notpassing', 'processing', 'restricted' 'show_download_url': bool 'download_url': url, only present if show_download_url is True 'show_disabled_download_button': bool -- true if state is 'generating' @@ -168,6 +168,7 @@ def _cert_info(user, course, cert_status): CertificateStatuses.regenerating: 'generating', CertificateStatuses.downloadable: 'ready', CertificateStatuses.notpassing: 'notpassing', + CertificateStatuses.restricted: 'restricted', } status = template_state.get(cert_status['status'], default_status) @@ -176,7 +177,7 @@ def _cert_info(user, course, cert_status): 'show_download_url': status == 'ready', 'show_disabled_download_button': status == 'generating',} - if (status in ('generating', 'ready', 'notpassing') and + if (status in ('generating', 'ready', 'notpassing', 'restricted') and course.end_of_course_survey_url is not None): d.update({ 'show_survey_button': True, @@ -192,7 +193,7 @@ def _cert_info(user, course, cert_status): else: d['download_url'] = cert_status['download_url'] - if status in ('generating', 'ready', 'notpassing'): + if status in ('generating', 'ready', 'notpassing', 'restricted'): if 'grade' not in cert_status: # Note: as of 11/20/2012, we know there are students in this state-- cs169.1x, # who need to be regraded (we weren't tracking 'notpassing' at first). From 69ff879e9546ee05f34a377f522534fc59637877 Mon Sep 17 00:00:00 2001 From: Brian Wilson Date: Tue, 29 Jan 2013 10:41:41 -0500 Subject: [PATCH 0235/1392] add more validation for countries --- common/djangoapps/student/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index d35045ed39..f39cc2e119 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -255,9 +255,9 @@ class TestCenterUserForm(ModelForm): def clean_country(self): code = self.cleaned_data['country'] - if code and len(code) != 3: + if code and (len(code) != 3 or not code.isalpha()): raise forms.ValidationError(u'Must be three characters (ISO 3166-1): e.g. USA, CAN, MNG') - return code + return code.upper() def clean(self): def _can_encode_as_latin(fieldvalue): From 85c412fc2eafefd0240a3c0081532d633b045a37 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 11:06:32 -0500 Subject: [PATCH 0236/1392] changed cms/env/tests, added test_views.py --- cms/djangoapps/contentstore/tests/test_views.py | 10 +++++++--- cms/envs/test.py | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index f513eef7f9..ae6548bd9d 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -13,8 +13,11 @@ from django.test.client import Client from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory +from override_settings import override_settings + +from xmodule.modulestore.django import modulestore, _MODULESTORES +import contentstore.views as views -import cms.djangoapps.contentstore.views as views def xml_store_config(data_dir): return { @@ -32,7 +35,6 @@ class UserFactory(factory.Factory): last_name = 'Robot' is_staff = True is_active = True - is_authenticated = True TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) @@ -47,4 +49,6 @@ class ViewsTestCase(TestCase): def test_has_access(self): user = UserFactory() - views.has_access(user, self.location) + user.is_authenticated = True + set_trace() + self.assertTrue(views.has_access(user, self.location)) diff --git a/cms/envs/test.py b/cms/envs/test.py index d55c309827..e31037b04f 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -25,6 +25,9 @@ STATIC_ROOT = TEST_ROOT / "staticfiles" GITHUB_REPO_ROOT = TEST_ROOT / "data" COMMON_TEST_DATA_ROOT = COMMON_ROOT / "test" / "data" +# Makes the tests run much faster... +SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead + # TODO (cpennington): We need to figure out how envs/test.py can inject things into common.py so that we don't have to repeat this sort of thing STATICFILES_DIRS = [ COMMON_ROOT / "static", From 3a6d45e716eb5d17ab625f7d73f9caa6fcb08f49 Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Tue, 29 Jan 2013 11:13:30 -0500 Subject: [PATCH 0237/1392] Grade a student even if they are on the restricted list --- lms/djangoapps/certificates/queue.py | 32 +++++++++++++--------------- lms/templates/dashboard.html | 2 +- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index d4e96f85be..d926035efd 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -164,31 +164,29 @@ class XQueueCertInterface(object): if is_whitelisted or grade['grade'] is not None: - # check to see whether the student is on the - # the embargoed country restricted list - if self.restricted.filter(user=student).exists(): - cert.status = status.restricted - cert.save() - return cert.status - - cert_status = status.generating key = make_hashkey(random.random()) - cert.status = cert_status cert.grade = grade['percent'] cert.user = student cert.course_id = course_id cert.key = key cert.name = profile.name - contents = { - 'action': 'create', - 'username': student.username, - 'course_id': course_id, - 'name': profile.name, - } - - self._send_to_xqueue(contents, key) + # check to see whether the student is on the + # the embargoed country restricted list + # otherwise, put a new certificate request + # on the queue + if self.restricted.filter(user=student).exists(): + cert.status = status.restricted + else: + contents = { + 'action': 'create', + 'username': student.username, + 'course_id': course_id, + 'name': profile.name, + } + cert.status = status.generating + self._send_to_xqueue(contents, key) cert.save() else: cert_status = status.notpassing diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 8ec58a6a28..845880c69f 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -273,7 +273,7 @@ % if cert_status['status'] == 'processing':

    Final course details are being wrapped up at this time. Your final standing will be available shortly.

    - % elif cert_status['status'] in ('generating', 'ready', 'notpassing'): + % elif cert_status['status'] in ('generating', 'ready', 'notpassing', 'restricted'):

    Your final grade: ${"{0:.0f}%".format(float(cert_status['grade'])*100)}. % if cert_status['status'] == 'notpassing': From 15a11e9cb7b643f07e653e0923e2064f3fb810c5 Mon Sep 17 00:00:00 2001 From: Brian Wilson Date: Tue, 29 Jan 2013 11:16:23 -0500 Subject: [PATCH 0238/1392] add validation of accommodation codes --- .../commands/pearson_make_tc_registration.py | 3 ++- common/djangoapps/student/models.py | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/common/djangoapps/student/management/commands/pearson_make_tc_registration.py b/common/djangoapps/student/management/commands/pearson_make_tc_registration.py index 2fcfa9ae48..b59241240d 100644 --- a/common/djangoapps/student/management/commands/pearson_make_tc_registration.py +++ b/common/djangoapps/student/management/commands/pearson_make_tc_registration.py @@ -179,7 +179,8 @@ class Command(BaseCommand): if (len(form.errors) > 0): print "Field Form errors encountered:" for fielderror in form.errors: - print "Field Form Error: %s" % fielderror + for msg in form.errors[fielderror]: + print "Field Form Error: {} -- {}".format(fielderror, msg) if (len(form.non_field_errors()) > 0): print "Non-field Form errors encountered:" for nonfielderror in form.non_field_errors: diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index f39cc2e119..838680c844 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -552,7 +552,15 @@ class TestCenterRegistrationForm(ModelForm): registration.save() log.info("Updated registration information for user's test center exam registration: username \"{}\" course \"{}\", examcode \"{}\"".format(registration.testcenter_user.user.username, registration.course_id, registration.exam_series_code)) - # TODO: add validation code for values added to accommodation_code field. + def clean_accommodation_code(self): + code = self.cleaned_data['accommodation_code'] + if code: + code = code.upper() + codes = code.split('*') + for codeval in codes: + if codeval not in ACCOMMODATION_CODE_DICT: + raise forms.ValidationError(u'Invalid accommodation code specified: "{}"'.format(codeval)) + return code From a9ee71fffc96296903c6b7eb6d0d3896b56d833a Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Tue, 29 Jan 2013 11:26:55 -0500 Subject: [PATCH 0239/1392] Adding section on eligibility --- lms/djangoapps/certificates/models.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 334200d348..0e68e3cfe7 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -35,6 +35,19 @@ State diagram: v v v [downloadable] [downloadable] [deleted] + +Eligibility: + + Students are eligible for a certificate if they pass the course + with the following exceptions: + + If the student has allow_certificate set to False in the student profile + he will never be issued a certificate. + + If the user and course is present in the certificate whitelist table + then the student will be issued a certificate regardless of his grade, + unless he has allow_certificate set to False. + """ From 39a9c475120e789b72dd168caa0906854aed94ac Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Tue, 29 Jan 2013 11:33:26 -0500 Subject: [PATCH 0240/1392] make links look like links --- common/static/js/course_groups/cohorts.js | 3 ++- lms/djangoapps/django_comment_client/forum/views.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common/static/js/course_groups/cohorts.js b/common/static/js/course_groups/cohorts.js index aa3ce34b5b..97837c6bac 100644 --- a/common/static/js/course_groups/cohorts.js +++ b/common/static/js/course_groups/cohorts.js @@ -83,10 +83,11 @@ var CohortManager = (function ($) { cohort_id = el.data('id'); state = state_detail; render(); + return false; } function add_to_cohorts_list(item) { - var li = $('

  • '); + var li = $('
  • '); $("a", li).text(item.name) .data('href', url + '/' + item.id) .addClass('link') diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index 6a182665a8..2c1d3c68d5 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -61,7 +61,7 @@ def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAG #if the course-user is cohorted, then add the group id - group_id = get_cohort_id(user,course_id) + group_id = get_cohort_id(user, course_id) if group_id: default_query_params["group_id"] = group_id From 3f4c45468fcb68301aad66fbc74ef5970b99f5cf Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 29 Jan 2013 11:36:10 -0500 Subject: [PATCH 0241/1392] Fix courseware jasmine tests --- lms/static/coffee/spec/courseware_spec.coffee | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/lms/static/coffee/spec/courseware_spec.coffee b/lms/static/coffee/spec/courseware_spec.coffee index 3b40930b41..a51e64ec21 100644 --- a/lms/static/coffee/spec/courseware_spec.coffee +++ b/lms/static/coffee/spec/courseware_spec.coffee @@ -10,19 +10,6 @@ describe 'Courseware', -> Courseware.start() expect(Logger.bind).toHaveBeenCalled() - describe 'bind', -> - beforeEach -> - @courseware = new Courseware - setFixtures """ -
    -
    -
    - """ - - it 'binds the content change event', -> - @courseware.bind() - expect($('.course-content .sequence')).toHandleWith 'contentChanged', @courseware.render - describe 'render', -> beforeEach -> jasmine.stubRequests() @@ -30,6 +17,7 @@ describe 'Courseware', -> spyOn(window, 'Histogram') spyOn(window, 'Problem') spyOn(window, 'Video') + spyOn(XModule, 'loadModules') setFixtures """
    @@ -41,12 +29,8 @@ describe 'Courseware', -> """ @courseware.render() - it 'detect the video elements and convert them', -> - expect(window.Video).toHaveBeenCalledWith('1', '1.0:abc1234') - expect(window.Video).toHaveBeenCalledWith('2', '1.0:def5678') - - it 'detect the problem element and convert it', -> - expect(window.Problem).toHaveBeenCalledWith(3, 'problem_3', '/example/url/') + it 'ensure that the XModules have been loaded', -> + expect(XModule.loadModules).toHaveBeenCalled() it 'detect the histrogram element and convert it', -> expect(window.Histogram).toHaveBeenCalledWith('3', [[0, 1]]) From ba95cf238576bb99a610ef996da6d4057cccd9fc Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Tue, 29 Jan 2013 13:10:23 -0500 Subject: [PATCH 0242/1392] Auto expand on hover of drag&drop unit --- cms/static/js/base.js | 67 +++++++++++++++++-- cms/static/js/hesitate.js | 31 +++++---- .../static/js/vendor/jquery.ui.draggable.js | 8 +++ 3 files changed, 86 insertions(+), 20 deletions(-) diff --git a/cms/static/js/base.js b/cms/static/js/base.js index ee8df97b28..a39056bde3 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -88,6 +88,9 @@ $(document).ready(function() { axis: 'y', handle: '.drag-handle', stack: '.unit', + start: initiateHesitate, + drag: checkHoverState, + stop: removeHesitate, revert: "invalid" }); @@ -179,10 +182,12 @@ function toggleSections(e) { if($button.hasClass('is-activated')) { $section.addClass('collapsed'); - $section.find('.expand-collapse-icon').removeClass('collapsed').addClass('expand'); + // first child in order to avoid the icons on the subsection lists which are not in the first child + $section.find('header .expand-collapse-icon').removeClass('collapse').addClass('expand'); } else { $section.removeClass('collapsed'); - $section.find('.expand-collapse-icon').removeClass('expand').addClass('collapse'); + // first child in order to avoid the icons on the subsection lists which are not in the first child + $section.find('header .expand-collapse-icon').removeClass('expand').addClass('collapse'); } } @@ -271,9 +276,63 @@ function removePolicyMetadata(e) { saveSubsection() } +CMS.HesitateEvent.toggleXpandHesitation = null; +function initiateHesitate(event, ui) { + CMS.HesitateEvent.toggleXpandHesitation = new CMS.HesitateEvent(expandSection, 'dragLeave', true); + $('.collapsed').on('dragEnter', CMS.HesitateEvent.toggleXpandHesitation, CMS.HesitateEvent.toggleXpandHesitation.trigger); + $('.collapsed').each(function() { + this.proportions = {width : this.offsetWidth, height : this.offsetHeight }; + // reset b/c these were holding values from aborts + this.isover = false; + }); +} +function checkHoverState(event, ui) { + // copied from jquery.ui.droppable.js $.ui.ddmanager.drag & other ui.intersect + var draggable = $(this).data("ui-draggable"), + x1 = (draggable.positionAbs || draggable.position.absolute).left + (draggable.helperProportions.width / 2), + y1 = (draggable.positionAbs || draggable.position.absolute).top + (draggable.helperProportions.height / 2); +var debugEle = $('article:first-of-type > section > div > ol:first-of-type > li:nth-of-type(2)').first(); + $('.collapsed').each(function() { + $.extend(this, {offset : $(this).offset()}); + + var droppable = this, + l = droppable.offset.left, + r = l + droppable.proportions.width, + t = droppable.offset.top, + b = t + droppable.proportions.height; + + if (l === r) { + // probably wrong values b/c invisible at the time of caching + droppable.proportions = { width : droppable.offsetWidth, height : droppable.offsetHeight }; + r = l + droppable.proportions.width; + b = t + droppable.proportions.height; + } + // equivalent to the intersects test + var intersects = (l < x1 && // Right Half + x1 < r && // Left Half + t < y1 && // Bottom Half + y1 < b ), // Top Half + + c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); + + if(!c) { + return; + } + + this[c] = true; + this[c === "isout" ? "isover" : "isout"] = false; + $(this).trigger(c === "isover" ? "dragEnter" : "dragLeave"); + }); +} +function removeHesitate(event, ui) { + $('.collapsed').off('dragEnter', CMS.HesitateEvent.toggleXpandHesitation.trigger); + CMS.HesitateEvent.toggleXpandHesitation = null; +} + function expandSection(event) { - $(event.delegateTarget).removeClass('collapsed'); - $(event.delegateTarget).find('.expand-collapse-icon').removeClass('expand').addClass('collapse'); + $(event.delegateTarget).removeClass('collapsed', 400); + // don't descend to icon's on children (which aren't under first child) only to this element's icon + $(event.delegateTarget).children().first().find('.expand-collapse-icon').removeClass('expand', 400).addClass('collapse', 400); } function onUnitReordered(event, ui) { diff --git a/cms/static/js/hesitate.js b/cms/static/js/hesitate.js index 63806ba0ec..a261f036e6 100644 --- a/cms/static/js/hesitate.js +++ b/cms/static/js/hesitate.js @@ -20,31 +20,30 @@ CMS.HesitateEvent = function(executeOnTimeOut, cancelSelector, onlyOnce) { this.onlyOnce = (onlyOnce === true); } -CMS.HesitateEvent.DURATION = 400; +CMS.HesitateEvent.DURATION = 800; CMS.HesitateEvent.prototype.trigger = function(event) { -console.log('trigger'); - if (this.timeoutEventId === null) { - this.timeoutEventId = window.setTimeout(this.fireEvent, CMS.HesitateEvent.DURATION); - this.originalEvent = event; + if (event.data.timeoutEventId == null) { + event.data.timeoutEventId = window.setTimeout( + function() { event.data.fireEvent(event); }, + CMS.HesitateEvent.DURATION); + event.data.originalEvent = event; // is it wrong to bind to the below v $(event.currentTarget)? - $(this.originalEvent.delegateTarget).on(this.cancelSelector, this.untrigger); + $(event.data.originalEvent.delegateTarget).on(event.data.cancelSelector, event.data, event.data.untrigger); } } CMS.HesitateEvent.prototype.fireEvent = function(event) { -console.log('fire'); - this.timeoutEventId = null; - $(this.originalEvent.delegateTarget).off(this.cancelSelector, this.untrigger); - if (this.onlyOnce) $(this.originalEvent.delegateTarget).off(this.originalEvent.type, this.trigger); - this.executeOnTimeOut(this.originalEvent); + event.data.timeoutEventId = null; + $(event.data.originalEvent.delegateTarget).off(event.data.cancelSelector, event.data.untrigger); + if (event.data.onlyOnce) $(event.data.originalEvent.delegateTarget).off(event.data.originalEvent.type, event.data.trigger); + event.data.executeOnTimeOut(event.data.originalEvent); } CMS.HesitateEvent.prototype.untrigger = function(event) { -console.log('untrigger'); - if (this.timeoutEventId) { - window.clearTimeout(this.timeoutEventId); - $(this.originalEvent.delegateTarget).off(this.cancelSelector, this.untrigger); + if (event.data.timeoutEventId) { + window.clearTimeout(event.data.timeoutEventId); + $(event.data.originalEvent.delegateTarget).off(event.data.cancelSelector, event.data.untrigger); } - this.timeoutEventId = null; + event.data.timeoutEventId = null; } \ No newline at end of file diff --git a/common/static/js/vendor/jquery.ui.draggable.js b/common/static/js/vendor/jquery.ui.draggable.js index b04686507c..4fa5066bb4 100644 --- a/common/static/js/vendor/jquery.ui.draggable.js +++ b/common/static/js/vendor/jquery.ui.draggable.js @@ -209,6 +209,14 @@ $.widget("ui.draggable", $.ui.mouse, { // computation of pageY or scrollTop() or caching of scrollTop at same state as pageY // btw: known bug in jqueryui http://bugs.jqueryui.com/ticket/5718 if (this.scrollParent.is(document) && this.cssPosition === 'relative') { + // need to catch the original parent having been shoved down during drag (perhaps by + // events) + // update cached originals if it shifted + if (this.offset && this.offset.parent && this.offset.parent.top !== this._getParentOffset().top) { + var deltaY = this.offset.parent.top - this._getParentOffset().top; + this.offset.parent.top = this._getParentOffset().top; + this.originalPageY -= deltaY; + } this.helper[0].style.top = (event.pageY - this.originalPageY) +"px"; } else this.helper[0].style.top = this.position.top+"px"; From 5fcb6bfcd42d88a6198ba87d5c5ffbe89f814102 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Tue, 29 Jan 2013 13:16:21 -0500 Subject: [PATCH 0243/1392] Remove debug code --- cms/static/js/base.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cms/static/js/base.js b/cms/static/js/base.js index a39056bde3..9f5e493aad 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -291,7 +291,6 @@ function checkHoverState(event, ui) { var draggable = $(this).data("ui-draggable"), x1 = (draggable.positionAbs || draggable.position.absolute).left + (draggable.helperProportions.width / 2), y1 = (draggable.positionAbs || draggable.position.absolute).top + (draggable.helperProportions.height / 2); -var debugEle = $('article:first-of-type > section > div > ol:first-of-type > li:nth-of-type(2)').first(); $('.collapsed').each(function() { $.extend(this, {offset : $(this).offset()}); From 3f740976bc12eb325cd3c3d05a70f3e9cb9d3a3d Mon Sep 17 00:00:00 2001 From: John Jarvis Date: Tue, 29 Jan 2013 13:24:17 -0500 Subject: [PATCH 0244/1392] Adding dashboard text for certificate restriction --- lms/templates/dashboard.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 845880c69f..43b69ea44b 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -279,6 +279,10 @@ % if cert_status['status'] == 'notpassing': Grade required for a certificate: ${"{0:.0f}%".format(float(course.lowest_passing_grade)*100)}. + % elif cert_status['status'] == 'restricted': +

    + Your certificate is being held while we seek confirmation that the issuance of your certificate is in compliance with strict U.S. embargoes on Iran, Cuba, Syria and Sudan. If you think our system has mistakenly identified you as being connected with one of those countries, please let us know by contacting info@edx.org. +

    % endif

    % endif From 87d8598abe097328ddf766cb262a2bc78c695e90 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Tue, 29 Jan 2013 13:43:58 -0500 Subject: [PATCH 0245/1392] subsection drag --- cms/static/js/base.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cms/static/js/base.js b/cms/static/js/base.js index 9f5e493aad..14a467c066 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -99,6 +99,9 @@ $(document).ready(function() { axis: 'y', handle: '.section-item .drag-handle', stack: '.id-holder', + start: initiateHesitate, + drag: checkHoverState, + stop: removeHesitate, revert: "invalid" }); @@ -292,6 +295,9 @@ function checkHoverState(event, ui) { x1 = (draggable.positionAbs || draggable.position.absolute).left + (draggable.helperProportions.width / 2), y1 = (draggable.positionAbs || draggable.position.absolute).top + (draggable.helperProportions.height / 2); $('.collapsed').each(function() { + // don't expand the thing being carried + if ($(draggable).is(this)) return; + $.extend(this, {offset : $(this).offset()}); var droppable = this, From 855c8bb7e7c7f9a6f1258d3e13e0f7a1cc6d8037 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Tue, 29 Jan 2013 13:44:42 -0500 Subject: [PATCH 0246/1392] add unit test for tab reordering --- cms/djangoapps/contentstore/tests/tests.py | 28 +++++++++++++++++++ cms/djangoapps/contentstore/views.py | 1 - .../data/full/policies/6.002_Spring_2012.json | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 3025ee78a4..bfdcfe1438 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -350,6 +350,34 @@ class ContentStoreTest(TestCase): def test_edit_unit_full(self): self.check_edit_unit('full') + def test_static_tab_reordering(self): + import_from_xml(modulestore(), 'common/test/data/', ['full']) + + # reverse the ordering + tabs = { 'tabs' : ['i4x://edX/full/static_tab/resources', 'i4x://edX/full/static_tab/syllabus'] } + resp = self.client.post(reverse('reorder_tabs'), json.dumps(tabs), "application/json") + + ms = modulestore('direct') + course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None])) + # compare to make sure that the tabs information is in the expected order after the server call + + resource_idx = 0 + syllabus_idx = 0 + idx = 0 + for tab in course.tabs: + if tab['type'] == 'static_tab': + if tab['url_slug'] == 'resources': + resource_idx = idx + elif tab['url_slug'] == 'syllabus': + syllabus_idx = idx + idx+=1 + + self.assertLess(resource_idx, syllabus_idx) + + + + + def test_about_overrides(self): ''' This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index 326b47ee64..205bf787fd 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -908,7 +908,6 @@ def edit_static(request, org, course, coursename): @expect_json def reorder_tabs(request): tabs = request.POST['tabs'] - logging.debug('tabs = {0} {1}'.format(tabs.__class__, tabs)) if len(tabs) > 0: course = get_course_for_item(tabs[0]) diff --git a/common/test/data/full/policies/6.002_Spring_2012.json b/common/test/data/full/policies/6.002_Spring_2012.json index 345309ff5c..2f55528b7b 100644 --- a/common/test/data/full/policies/6.002_Spring_2012.json +++ b/common/test/data/full/policies/6.002_Spring_2012.json @@ -8,6 +8,7 @@ {"type": "courseware"}, {"type": "course_info", "name": "Course Info"}, {"type": "static_tab", "url_slug": "syllabus", "name": "Syllabus"}, + {"type": "static_tab", "url_slug": "resources", "name": "Resources"}, {"type": "discussion", "name": "Discussion"}, {"type": "wiki", "name": "Wiki"}, {"type": "progress", "name": "Progress"} From d9fdccb567924f04ec420e95bfe5c37e5bee751a Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 14:23:55 -0500 Subject: [PATCH 0247/1392] testing testing tests --- .../contentstore/tests/test_views.py | 45 ++++++++++++++++--- .../courseware/tests/test_module_render.py | 9 ++-- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index ae6548bd9d..c1fa19624c 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -6,7 +6,7 @@ import unittest from nose.tools import set_trace from nose.plugins.skip import SkipTest -from django.http import Http404, HttpResponse, HttpRequest +from django.http import Http404, HttpResponse, HttpRequest, HttpResponseRedirect from django.conf import settings from django.contrib.auth.models import User from django.test.client import Client @@ -14,9 +14,12 @@ from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory from override_settings import override_settings +from django.core.exceptions import PermissionDenied from xmodule.modulestore.django import modulestore, _MODULESTORES import contentstore.views as views +import auth.authz as a +from contentstore.tests.factories import XModuleCourseFactory, CourseFactory def xml_store_config(data_dir): @@ -39,16 +42,46 @@ class UserFactory(factory.Factory): TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class ViewsTestCase(TestCase): def setUp(self): self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] + # empty Modulestore self._MODULESTORES = {} self.course_id = 'edX/toy/2012_Fall' + self.course_id_2 = 'edx/full/6.002_Spring_2012' self.toy_course = modulestore().get_course(self.course_id) def test_has_access(self): - user = UserFactory() - user.is_authenticated = True - set_trace() - self.assertTrue(views.has_access(user, self.location)) + user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) + m = MagicMock() + m.count.return_value = 1 + user.groups.filter.return_value = m + self.assertTrue(views.has_access(user, self.location_2)) + user.is_authenticated = False + self.assertFalse(views.has_access(user, self.location_2)) + + def test_course_index(self): + # UserFactory doesn't work? + self.user = MagicMock(is_staff = False, is_active = False) + self.user.is_authenticated.return_value = False + request = MagicMock(user = self.user) + # Instead of raising exception when has_access is False, redirects + self.assertIsInstance(views.course_index(request, 'edX', + 'full', '6.002_Spring_2012'), HttpResponseRedirect) + self.user_2 = MagicMock(is_staff = True, is_active = True) + self.user_2.is_authenticated.return_value = True + request_2 = MagicMock(user = self.user_2) + # Bug? Raises error because calls modulestore().get_item(location) + #NotImplementedError: XMLModuleStores can't guarantee that definitions + #are unique. Use get_instance. + print views.course_index(request_2, 'edX', + 'full', '6.002_Spring_2012') + + def test_edit_subsection(self): + self.user = MagicMock(is_staff = False, is_active = False) + self.user.is_authenticated.return_value = False + self.request = MagicMock(user = self.user) + self.assertIsInstance(views.edit_subscription(self.request, self.location_2), + HttpResponseRedirect) + diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 3150450648..f419e6f582 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -107,8 +107,7 @@ class ModuleRenderTestCase(PageLoader): mock_user_2 = MagicMock(User) mock_user_2.is_authenticated.return_value = True - mock_module = MagicMock() - mock_module.shared_state_key = 'key' + mock_module = MagicMock(shared_state_key = 'key') mock_module.location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') mock_module.get_shared_state.return_value = '{}' mock_cache = MagicMock() @@ -197,11 +196,9 @@ class ModuleRenderTestCase(PageLoader): # keep going def test_preview_chemcalc(self): - mock_request = MagicMock() - mock_request.method = 'notGET' + mock_request = MagicMock(method = 'notGET') self.assertRaises(Http404, render.preview_chemcalc, mock_request) - mock_request_2 = MagicMock() - mock_request_2.method = 'GET' + mock_request_2 = MagicMock(method = 'GET') mock_request_2.GET.get.return_value = None self.assertEquals(render.preview_chemcalc(mock_request_2).content, json.dumps({'preview':'', From e7450874557b48c5479dad6bc9f008c6c50100ce Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 29 Jan 2013 14:30:15 -0500 Subject: [PATCH 0248/1392] Fix permissions bug and add test cases for django comment client permissions. --- .../django_comment_client/permissions.py | 7 +- lms/djangoapps/django_comment_client/tests.py | 111 --------------- .../django_comment_client/tests/__init__.py | 0 .../tests/test_permissions.py | 128 ++++++++++++++++++ 4 files changed, 133 insertions(+), 113 deletions(-) delete mode 100644 lms/djangoapps/django_comment_client/tests.py create mode 100644 lms/djangoapps/django_comment_client/tests/__init__.py create mode 100644 lms/djangoapps/django_comment_client/tests/test_permissions.py diff --git a/lms/djangoapps/django_comment_client/permissions.py b/lms/djangoapps/django_comment_client/permissions.py index b95a890dda..b583c3fe74 100644 --- a/lms/djangoapps/django_comment_client/permissions.py +++ b/lms/djangoapps/django_comment_client/permissions.py @@ -29,6 +29,7 @@ def has_permission(user, permission, course_id=None): CONDITIONS = ['is_open', 'is_author'] +# data may be a json file def check_condition(user, condition, course_id, data): def check_open(user, condition, course_id, data): try: @@ -61,8 +62,10 @@ def check_conditions_permissions(user, permissions, course_id, **kwargs): def test(user, per, operator="or"): if isinstance(per, basestring): if per in CONDITIONS: - return check_condition(user, per, course_id, kwargs) + return check_condition(user, per, course_id, kwargs['data']) return cached_has_permission(user, per, course_id=course_id) + # TODO: refactor this to be more clear. + # e.g. the "and operator in" bit on the next line is not needed? elif isinstance(per, list) and operator in ["and", "or"]: results = [test(user, x, operator="and") for x in per] if operator == "or": @@ -102,4 +105,4 @@ def check_permissions_by_view(user, course_id, content, name): p = VIEW_PERMISSIONS[name] except KeyError: logging.warning("Permission for view named %s does not exist in permissions.py" % name) - return check_conditions_permissions(user, p, course_id, content=content) + return check_conditions_permissions(user, p, course_id, data=content) diff --git a/lms/djangoapps/django_comment_client/tests.py b/lms/djangoapps/django_comment_client/tests.py deleted file mode 100644 index ac059a1e3f..0000000000 --- a/lms/djangoapps/django_comment_client/tests.py +++ /dev/null @@ -1,111 +0,0 @@ -from django.contrib.auth.models import User, Group -from django.core.urlresolvers import reverse -from django.test import TestCase -from django.test.client import RequestFactory -from django.conf import settings - -from mock import Mock - -from override_settings import override_settings - -import xmodule.modulestore.django - -from student.models import CourseEnrollment - -from django.db.models.signals import m2m_changed, pre_delete, pre_save, post_delete, post_save -from django.dispatch.dispatcher import _make_id -import string -import random -from .permissions import has_permission -from .models import Role, Permission - -from xmodule.modulestore.django import modulestore -from xmodule.modulestore import Location -from xmodule.modulestore.xml_importer import import_from_xml -from xmodule.modulestore.xml import XMLModuleStore - -import comment_client - -from courseware.tests.tests import PageLoader, TEST_DATA_XML_MODULESTORE - -#@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -#class TestCohorting(PageLoader): -# """Check that cohorting works properly""" -# -# def setUp(self): -# xmodule.modulestore.django._MODULESTORES = {} -# -# # Assume courses are there -# self.toy = modulestore().get_course("edX/toy/2012_Fall") -# -# # Create two accounts -# self.student = 'view@test.com' -# self.student2 = 'view2@test.com' -# self.password = 'foo' -# self.create_account('u1', self.student, self.password) -# self.create_account('u2', self.student2, self.password) -# self.activate_user(self.student) -# self.activate_user(self.student2) -# -# def test_create_thread(self): -# my_save = Mock() -# comment_client.perform_request = my_save -# -# resp = self.client.post( -# reverse('django_comment_client.base.views.create_thread', -# kwargs={'course_id': 'edX/toy/2012_Fall', -# 'commentable_id': 'General'}), -# {'some': "some", -# 'data': 'data'}) -# self.assertTrue(my_save.called) -# -# #self.assertEqual(resp.status_code, 200) -# #self.assertEqual(my_save.something, "expected", "complaint if not true") -# -# self.toy.metadata["cohort_config"] = {"cohorted": True} -# -# # call the view again ... -# -# # assert that different things happened - - - -class PermissionsTestCase(TestCase): - def random_str(self, length=15, chars=string.ascii_uppercase + string.digits): - return ''.join(random.choice(chars) for x in range(length)) - - def setUp(self): - - self.course_id = "edX/toy/2012_Fall" - - self.moderator_role = Role.objects.get_or_create(name="Moderator", course_id=self.course_id)[0] - self.student_role = Role.objects.get_or_create(name="Student", course_id=self.course_id)[0] - - self.student = User.objects.create(username=self.random_str(), - password="123456", email="john@yahoo.com") - self.moderator = User.objects.create(username=self.random_str(), - password="123456", email="staff@edx.org") - self.moderator.is_staff = True - self.moderator.save() - self.student_enrollment = CourseEnrollment.objects.create(user=self.student, course_id=self.course_id) - self.moderator_enrollment = CourseEnrollment.objects.create(user=self.moderator, course_id=self.course_id) - - def tearDown(self): - self.student_enrollment.delete() - self.moderator_enrollment.delete() - -# Do we need to have this? We shouldn't be deleting students, ever -# self.student.delete() -# self.moderator.delete() - - def testDefaultRoles(self): - self.assertTrue(self.student_role in self.student.roles.all()) - self.assertTrue(self.moderator_role in self.moderator.roles.all()) - - def testPermission(self): - name = self.random_str() - self.moderator_role.add_permission(name) - self.assertTrue(has_permission(self.moderator, name, self.course_id)) - - self.student_role.add_permission(name) - self.assertTrue(has_permission(self.student, name, self.course_id)) diff --git a/lms/djangoapps/django_comment_client/tests/__init__.py b/lms/djangoapps/django_comment_client/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lms/djangoapps/django_comment_client/tests/test_permissions.py b/lms/djangoapps/django_comment_client/tests/test_permissions.py new file mode 100644 index 0000000000..44e1a3a128 --- /dev/null +++ b/lms/djangoapps/django_comment_client/tests/test_permissions.py @@ -0,0 +1,128 @@ +import string +import random +import collections + +import factory +from django.test import TestCase + +from django.contrib.auth.models import User +from student.models import UserProfile, CourseEnrollment +from django_comment_client.models import Role, Permission +import django_comment_client.permissions as p + +class UserFactory(factory.Factory): + FACTORY_FOR = User + username = 'robot' + password = '123456' + email = 'robot@edx.org' + is_active = True + is_staff = False + +class CourseEnrollmentFactory(factory.Factory): + FACTORY_FOR = CourseEnrollment + user = factory.SubFactory(UserFactory) + course_id = 'edX/toy/2012_Fall' + +class RoleFactory(factory.Factory): + FACTORY_FOR = Role + name = 'Student' + course_id = 'edX/toy/2012_Fall' + +class PermissionFactory(factory.Factory): + FACTORY_FOR = Permission + name = 'create_comment' + + +class PermissionsTestCase(TestCase): + def setUp(self): + self.course_id = "edX/toy/2012_Fall" + + self.student_role = RoleFactory(name='Student') + self.moderator_role = RoleFactory(name='Moderator') + self.student = UserFactory(username='student', email='student@edx.org') + self.moderator = UserFactory(username='moderator', email='staff@edx.org', is_staff=True) + self.update_thread_permission = PermissionFactory(name='update_thread') + self.update_thread_permission.roles.add(self.student_role) + self.update_thread_permission.roles.add(self.moderator_role) + self.manage_moderator_permission = PermissionFactory(name='manage_moderator') + self.manage_moderator_permission.roles.add(self.moderator_role) + self.student_enrollment = CourseEnrollmentFactory(user=self.student) + self.moderator_enrollment = CourseEnrollmentFactory(user=self.moderator) + + self.student_open_thread = {'content': { + 'closed': False, + 'user_id': str(self.student.id)} + } + self.student_closed_thread = {'content': { + 'closed': True, + 'user_id': str(self.student.id)} + } + + def test_user_has_permission(self): + s_ut = p.has_permission(self.student, 'update_thread', self.course_id) + m_ut = p.has_permission(self.moderator, 'update_thread', self.course_id) + s_mm = p.has_permission(self.student, 'manage_moderator', self.course_id) + m_mm = p.has_permission(self.moderator, 'manage_moderator', self.course_id) + self.assertTrue(s_ut) + self.assertTrue(m_ut) + self.assertFalse(s_mm) + self.assertTrue(m_mm) + + def test_check_conditions(self): + # Checks whether the discussion thread is open, or whether the author is user + s_o = p.check_condition(self.student, 'is_open', self.course_id, self.student_open_thread) + s_a = p.check_condition(self.student, 'is_author', self.course_id, self.student_open_thread) + m_c = p.check_condition(self.moderator, 'is_open', self.course_id, self.student_closed_thread) + m_a = p.check_condition(self.moderator,'is_author', self.course_id, self.student_open_thread) + self.assertTrue(s_o) + self.assertTrue(s_a) + self.assertFalse(m_c) + self.assertFalse(m_a) + + def test_check_conditions_and_permissions(self): + # Check conditions + ret = p.check_conditions_permissions(self.student, + 'is_open', + self.course_id, + data=self.student_open_thread) + self.assertTrue(ret) + + # Check permissions + ret = p.check_conditions_permissions(self.student, + 'update_thread', + self.course_id, + data=self.student_open_thread) + self.assertTrue(ret) + + # Check that a list of permissions/conditions will be OR'd + ret = p.check_conditions_permissions(self.moderator, + ['is_open','manage_moderator'], + self.course_id, + data=self.student_open_thread) + self.assertTrue(ret) + + # Check that a list of permissions will be OR'd + ret = p.check_conditions_permissions(self.student, + ['update_thread','manage_moderator'], + self.course_id, + data=self.student_open_thread) + self.assertTrue(ret) + + # Check that a list of list of permissions will be AND'd + ret = p.check_conditions_permissions(self.student, + [['update_thread','manage_moderator']], + self.course_id, + data=self.student_open_thread) + self.assertFalse(ret) + + def test_check_permissions_by_view(self): + ret = p.check_permissions_by_view(self.student, self.course_id, + self.student_open_thread, 'openclose_thread') + self.assertFalse(ret) + + # Check a view permission that includes both a condition and a permission + self.vote_permission = PermissionFactory(name='vote') + self.vote_permission.roles.add(self.student_role) + ret = p.check_permissions_by_view(self.student, self.course_id, + self.student_open_thread, 'vote_for_comment') + self.assertTrue(ret) \ No newline at end of file From 63d269acf1f122047163713bcf598b0940f430c6 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Tue, 29 Jan 2013 14:31:14 -0500 Subject: [PATCH 0249/1392] draggable is not the collapsed item :-( but ui.helper seems to be. --- cms/static/js/base.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cms/static/js/base.js b/cms/static/js/base.js index 14a467c066..fe43fe2d71 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -87,7 +87,7 @@ $(document).ready(function() { $('.unit').draggable({ axis: 'y', handle: '.drag-handle', - stack: '.unit', + stack: '.unit, .id-holder', start: initiateHesitate, drag: checkHoverState, stop: removeHesitate, @@ -296,7 +296,9 @@ function checkHoverState(event, ui) { y1 = (draggable.positionAbs || draggable.position.absolute).top + (draggable.helperProportions.height / 2); $('.collapsed').each(function() { // don't expand the thing being carried - if ($(draggable).is(this)) return; + if (ui.helper.is(this)) { + return; + } $.extend(this, {offset : $(this).offset()}); From 1f049410ae5a2638260b196d8f3bcd3d8ef11351 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 29 Jan 2013 14:31:27 -0500 Subject: [PATCH 0250/1392] Add tests for django comment client utils --- .../django_comment_client/tests/test_utils.py | 89 +++++++++++++++++++ lms/djangoapps/django_comment_client/utils.py | 1 + 2 files changed, 90 insertions(+) create mode 100644 lms/djangoapps/django_comment_client/tests/test_utils.py diff --git a/lms/djangoapps/django_comment_client/tests/test_utils.py b/lms/djangoapps/django_comment_client/tests/test_utils.py new file mode 100644 index 0000000000..2e24cbd837 --- /dev/null +++ b/lms/djangoapps/django_comment_client/tests/test_utils.py @@ -0,0 +1,89 @@ +import string +import random +import collections + +from django.test import TestCase + +import factory +from django.contrib.auth.models import User +from student.models import UserProfile, CourseEnrollment +from django_comment_client.models import Role, Permission + +import django_comment_client.models as models +import django_comment_client.utils as utils + +import xmodule.modulestore.django as django + +class UserFactory(factory.Factory): + FACTORY_FOR = User + username = 'robot' + password = '123456' + email = 'robot@edx.org' + is_active = True + is_staff = False + +class CourseEnrollmentFactory(factory.Factory): + FACTORY_FOR = CourseEnrollment + user = factory.SubFactory(UserFactory) + course_id = 'edX/toy/2012_Fall' + +class RoleFactory(factory.Factory): + FACTORY_FOR = Role + name = 'Student' + course_id = 'edX/toy/2012_Fall' + +class PermissionFactory(factory.Factory): + FACTORY_FOR = Permission + name = 'create_comment' + +class DictionaryTestCase(TestCase): + def test_extract(self): + d = {'cats': 'meow', 'dogs': 'woof'} + k = ['cats', 'dogs', 'hamsters'] + expected = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None} + self.assertEqual(utils.extract(d, k), expected) + + def test_strip_none(self): + d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None} + expected = {'cats': 'meow', 'dogs': 'woof'} + self.assertEqual(utils.strip_none(d), expected) + + def test_strip_blank(self): + d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': ' ', 'yetis': ''} + expected = {'cats': 'meow', 'dogs': 'woof'} + self.assertEqual(utils.strip_blank(d), expected) + + def test_merge_dict(self): + d1 ={'cats': 'meow', 'dogs': 'woof'} + d2 ={'lions': 'roar','ducks': 'quack'} + expected ={'cats': 'meow', 'dogs': 'woof','lions': 'roar','ducks': 'quack'} + self.assertEqual(utils.merge_dict(d1, d2), expected) + +class AccessUtilsTestCase(TestCase): + def setUp(self): + self.course_id = 'edX/toy/2012_Fall' + self.student_role = RoleFactory(name='Student', course_id=self.course_id) + self.moderator_role = RoleFactory(name='Moderator', course_id=self.course_id) + self.student1 = UserFactory(username='student', email='student@edx.org') + self.student1_enrollment = CourseEnrollmentFactory(user=self.student1) + self.student_role.users.add(self.student1) + self.student2 = UserFactory(username='student2', email='student2@edx.org') + self.student2_enrollment = CourseEnrollmentFactory(user=self.student2) + self.moderator = UserFactory(username='moderator', email='staff@edx.org', is_staff=True) + self.moderator_enrollment = CourseEnrollmentFactory(user=self.moderator) + self.moderator_role.users.add(self.moderator) + + def test_get_role_ids(self): + ret = utils.get_role_ids(self.course_id) + expected = {u'Moderator': [3], u'Student': [1, 2], 'Staff': [3]} + self.assertEqual(ret, expected) + + def test_has_forum_access(self): + ret = utils.has_forum_access('student', self.course_id, 'Student') + self.assertTrue(ret) + + ret = utils.has_forum_access('not_a_student', self.course_id, 'Student') + self.assertFalse(ret) + + ret = utils.has_forum_access('student', self.course_id, 'NotARole') + self.assertFalse(ret) diff --git a/lms/djangoapps/django_comment_client/utils.py b/lms/djangoapps/django_comment_client/utils.py index 3c9669ac37..b58e3b30e6 100644 --- a/lms/djangoapps/django_comment_client/utils.py +++ b/lms/djangoapps/django_comment_client/utils.py @@ -35,6 +35,7 @@ def strip_blank(dic): return isinstance(v, str) and len(v.strip()) == 0 return dict([(k, v) for k, v in dic.iteritems() if not _is_blank(v)]) +# TODO should we be checking if d1 and d2 have the same keys with different values? def merge_dict(dic1, dic2): return dict(dic1.items() + dic2.items()) From efc572c24d7fc6d4f99a0b3fd39deb05b064e80b Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 29 Jan 2013 14:36:27 -0500 Subject: [PATCH 0251/1392] Fix navigation jasmine tests --- lms/static/coffee/spec/navigation_spec.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lms/static/coffee/spec/navigation_spec.coffee b/lms/static/coffee/spec/navigation_spec.coffee index cb98c2b64c..1340984e52 100644 --- a/lms/static/coffee/spec/navigation_spec.coffee +++ b/lms/static/coffee/spec/navigation_spec.coffee @@ -16,6 +16,7 @@ describe 'Navigation', -> active: 1 header: 'h3' autoHeight: false + heightStyle: 'content' describe 'when there is no active section', -> beforeEach -> @@ -23,11 +24,12 @@ describe 'Navigation', -> $('#accordion').append('
    ') new Navigation - it 'activate the accordian with section 1 as active', -> + it 'activate the accordian with no section as active', -> expect($('#accordion').accordion).toHaveBeenCalledWith - active: 1 + active: 0 header: 'h3' autoHeight: false + heightStyle: 'content' it 'binds the accordionchange event', -> Navigation.bind() From 593b038780e261f10e9dbc704e16db0df5700a47 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 29 Jan 2013 14:43:28 -0500 Subject: [PATCH 0252/1392] Add tests for django-comment-client helpers --- lms/djangoapps/django_comment_client/helpers.py | 3 +++ .../django_comment_client/tests/test_helpers.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 lms/djangoapps/django_comment_client/tests/test_helpers.py diff --git a/lms/djangoapps/django_comment_client/helpers.py b/lms/djangoapps/django_comment_client/helpers.py index 96fd82d37c..0a1e8639ef 100644 --- a/lms/djangoapps/django_comment_client/helpers.py +++ b/lms/djangoapps/django_comment_client/helpers.py @@ -12,6 +12,9 @@ import pystache_custom as pystache import urllib import os +# This method is used to pluralize the words "discussion" and "comment" +# when referring to how many discussion threads or comments the user +# has contributed to. def pluralize(singular_term, count): if int(count) >= 2 or int(count) == 0: return singular_term + 's' diff --git a/lms/djangoapps/django_comment_client/tests/test_helpers.py b/lms/djangoapps/django_comment_client/tests/test_helpers.py new file mode 100644 index 0000000000..bd67830841 --- /dev/null +++ b/lms/djangoapps/django_comment_client/tests/test_helpers.py @@ -0,0 +1,15 @@ +import string +import random +import collections + +from django.test import TestCase + +from django_comment_client.helpers import pluralize + +class PluralizeTestCase(TestCase): + + def testPluralize(self): + self.term = "cat" + self.assertEqual(pluralize(self.term, 0), "cats") + self.assertEqual(pluralize(self.term, 1), "cat") + self.assertEqual(pluralize(self.term, 2), "cats") From d81da9df4dacbc30f85935248b827aa90e4b1610 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 29 Jan 2013 14:44:37 -0500 Subject: [PATCH 0253/1392] Add tests for django comment client mustache helpers --- .../django_comment_client/mustache_helpers.py | 2 ++ .../tests/test_mustache_helpers.py | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py diff --git a/lms/djangoapps/django_comment_client/mustache_helpers.py b/lms/djangoapps/django_comment_client/mustache_helpers.py index 6f04ca527c..9756294696 100644 --- a/lms/djangoapps/django_comment_client/mustache_helpers.py +++ b/lms/djangoapps/django_comment_client/mustache_helpers.py @@ -5,6 +5,8 @@ import urllib import sys import inspect +# This method is used to pluralize the words "discussion" and "comment" +# which is why you need to tack on an "s" for the case of 0 or two or more. def pluralize(content, text): num, word = text.split(' ') num = int(num or '0') diff --git a/lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py b/lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py new file mode 100644 index 0000000000..8638aba67e --- /dev/null +++ b/lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py @@ -0,0 +1,26 @@ +import string +import random +import collections + +from django.test import TestCase + +import django_comment_client.mustache_helpers as mustache_helpers + +class PluralizeTestCase(TestCase): + + def test_pluralize(self): + self.text1 = '0 goat' + self.text2 = '1 goat' + self.text3 = '7 goat' + self.content = 'unused argument' + self.assertEqual(mustache_helpers.pluralize(self.content, self.text1), 'goats') + self.assertEqual(mustache_helpers.pluralize(self.content, self.text2), 'goat') + self.assertEqual(mustache_helpers.pluralize(self.content, self.text3), 'goats') + +class CloseThreadTextTestCase(TestCase): + + def test_close_thread_text(self): + self.contentClosed = {'closed': True} + self.contentOpen = {'closed': False} + self.assertEqual(mustache_helpers.close_thread_text(self.contentClosed), 'Re-open thread') + self.assertEqual(mustache_helpers.close_thread_text(self.contentOpen), 'Close thread') From 053547453ec641feb755247a90cc61560a1f44c0 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 29 Jan 2013 14:45:35 -0500 Subject: [PATCH 0254/1392] Add tests for django-comment-client models --- .../django_comment_client/models.py | 8 +-- .../tests/test_models.py | 54 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 lms/djangoapps/django_comment_client/tests/test_models.py diff --git a/lms/djangoapps/django_comment_client/models.py b/lms/djangoapps/django_comment_client/models.py index 10c05c75e9..3c3ab2bb53 100644 --- a/lms/djangoapps/django_comment_client/models.py +++ b/lms/djangoapps/django_comment_client/models.py @@ -46,11 +46,13 @@ class Role(models.Model): def add_permission(self, permission): self.permissions.add(Permission.objects.get_or_create(name=permission)[0]) + def has_permission(self, permission): course = get_course_by_id(self.course_id) - if self.name == FORUM_ROLE_STUDENT and \ - (permission.startswith('edit') or permission.startswith('update') or permission.startswith('create')) and \ - (not course.forum_posts_allowed): + changing_comments = permission.startswith('edit') or \ + permission.startswith('update') or permission.startswith('create') + in_blackout_period = not course.forum_posts_allowed + if (self.name == FORUM_ROLE_STUDENT) and in_blackout_period and changing_comments: return False return self.permissions.filter(name=permission).exists() diff --git a/lms/djangoapps/django_comment_client/tests/test_models.py b/lms/djangoapps/django_comment_client/tests/test_models.py new file mode 100644 index 0000000000..3c9b05b202 --- /dev/null +++ b/lms/djangoapps/django_comment_client/tests/test_models.py @@ -0,0 +1,54 @@ +import django_comment_client.models as models +import django_comment_client.permissions as permissions +from django.test import TestCase +from nose.plugins.skip import SkipTest +from courseware.courses import get_course_by_id + +class RoleClassTestCase(TestCase): + def setUp(self): + self.course_id = "edX/toy/2012_Fall" + self.student_role = models.Role.objects.create(name="Student", + course_id=self.course_id) + + def test_unicode(self): + self.assertEqual(str(self.student_role), "Student for edX/toy/2012_Fall") + + self.admin_for_all = models.Role.objects.create(name="Administrator") + self.assertEqual(str(self.admin_for_all), "Administrator for all courses") + + def test_has_permission(self): + self.student_role.add_permission("delete_thread") + self.TA_role = models.Role.objects.create(name="Community TA", + course_id=self.course_id) + self.assertTrue(self.student_role.has_permission("delete_thread")) + self.assertFalse(self.TA_role.has_permission("delete_thread")) + + # Toy course does not have a blackout period defined. + def test_students_can_create_if_not_during_blackout(self): + self.student_role.add_permission("create_comment") + self.assertTrue(self.student_role.has_permission("create_comment")) + + def test_students_cannot_create_during_blackout(self): + # Not sure how to set up these conditions + raise SkipTest() + + def test_inherit_permissions(self): + self.student_role.add_permission("delete_thread") + self.TA_role = models.Role.objects.create(name="Community TA", + course_id=self.course_id) + self.TA_role.inherit_permissions(self.student_role) + self.assertTrue(self.TA_role.has_permission("delete_thread")) + + # TODO: You should not be able to inherit permissions across courses? + def test_inherit_permissions_across_courses(self): + raise SkipTest() + self.student_role.add_permission("delete_thread") + self.course_id_2 = "MITx/6.002x/2012_Fall" + self.admin_role = models.Role.objects.create(name="Administrator", + course_id=self.course_id_2) + self.admin_role.inherit_permissions(self.student_role) + +class PermissionClassTestCase(TestCase): + def test_unicode(self): + self.permission = permissions.Permission.objects.create(name="test") + self.assertEqual(str(self.permission), "test") From 1a398980d05af4daf5410c7c40f22c2e8f52d5f2 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 29 Jan 2013 14:47:05 -0500 Subject: [PATCH 0255/1392] Add tests for diango-comment-client middleware --- .../tests/test_middleware.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 lms/djangoapps/django_comment_client/tests/test_middleware.py diff --git a/lms/djangoapps/django_comment_client/tests/test_middleware.py b/lms/djangoapps/django_comment_client/tests/test_middleware.py new file mode 100644 index 0000000000..e3249551b3 --- /dev/null +++ b/lms/djangoapps/django_comment_client/tests/test_middleware.py @@ -0,0 +1,28 @@ +import string +import random +import collections + +from django.test import TestCase + +import comment_client +import django.http +import django_comment_client.middleware as middleware + +class AjaxExceptionTestCase(TestCase): + +# TODO: check whether the correct error message is produced. +# The error message should be the same as the argument to CommentClientError + def setUp(self): + self.a = middleware.AjaxExceptionMiddleware() + self.request1 = django.http.HttpRequest() + self.request0 = django.http.HttpRequest() + self.exception1 = comment_client.CommentClientError('{}') + self.exception0 = ValueError() + self.request1.META['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest" + self.request0.META['HTTP_X_REQUESTED_WITH'] = "SHADOWFAX" + + def test_process_exception(self): + self.assertIsInstance(self.a.process_exception(self.request1, self.exception1), middleware.JsonError) + self.assertIsNone(self.a.process_exception(self.request1, self.exception0)) + self.assertIsNone(self.a.process_exception(self.request0, self.exception1)) + self.assertIsNone(self.a.process_exception(self.request0, self.exception0)) From 574d6e8e28c5a840dd2931436d7326e99ec2b693 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Tue, 29 Jan 2013 15:00:49 -0500 Subject: [PATCH 0256/1392] Simple zIndex rather than fancy stack works best. --- cms/static/js/base.js | 6 +++--- cms/static/js/hesitate.js | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/cms/static/js/base.js b/cms/static/js/base.js index fe43fe2d71..41c1ee3cdb 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -87,7 +87,7 @@ $(document).ready(function() { $('.unit').draggable({ axis: 'y', handle: '.drag-handle', - stack: '.unit, .id-holder', + zIndex: 999, start: initiateHesitate, drag: checkHoverState, stop: removeHesitate, @@ -98,7 +98,7 @@ $(document).ready(function() { $('.id-holder').draggable({ axis: 'y', handle: '.section-item .drag-handle', - stack: '.id-holder', + zIndex: 999, start: initiateHesitate, drag: checkHoverState, stop: removeHesitate, @@ -339,7 +339,7 @@ function removeHesitate(event, ui) { function expandSection(event) { $(event.delegateTarget).removeClass('collapsed', 400); // don't descend to icon's on children (which aren't under first child) only to this element's icon - $(event.delegateTarget).children().first().find('.expand-collapse-icon').removeClass('expand', 400).addClass('collapse', 400); + $(event.delegateTarget).children().first().find('.expand-collapse-icon').removeClass('expand', 400).addClass('collapse'); } function onUnitReordered(event, ui) { diff --git a/cms/static/js/hesitate.js b/cms/static/js/hesitate.js index a261f036e6..c5848a6c0c 100644 --- a/cms/static/js/hesitate.js +++ b/cms/static/js/hesitate.js @@ -18,7 +18,7 @@ CMS.HesitateEvent = function(executeOnTimeOut, cancelSelector, onlyOnce) { this.timeoutEventId = null; this.originalEvent = null; this.onlyOnce = (onlyOnce === true); -} +}; CMS.HesitateEvent.DURATION = 800; @@ -28,17 +28,16 @@ CMS.HesitateEvent.prototype.trigger = function(event) { function() { event.data.fireEvent(event); }, CMS.HesitateEvent.DURATION); event.data.originalEvent = event; - // is it wrong to bind to the below v $(event.currentTarget)? $(event.data.originalEvent.delegateTarget).on(event.data.cancelSelector, event.data, event.data.untrigger); } -} +}; CMS.HesitateEvent.prototype.fireEvent = function(event) { event.data.timeoutEventId = null; $(event.data.originalEvent.delegateTarget).off(event.data.cancelSelector, event.data.untrigger); if (event.data.onlyOnce) $(event.data.originalEvent.delegateTarget).off(event.data.originalEvent.type, event.data.trigger); event.data.executeOnTimeOut(event.data.originalEvent); -} +}; CMS.HesitateEvent.prototype.untrigger = function(event) { if (event.data.timeoutEventId) { @@ -46,4 +45,4 @@ CMS.HesitateEvent.prototype.untrigger = function(event) { $(event.data.originalEvent.delegateTarget).off(event.data.cancelSelector, event.data.untrigger); } event.data.timeoutEventId = null; -} \ No newline at end of file +}; \ No newline at end of file From 3858362157d1638f222fc5e8da893bdbe38262d9 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 15:53:20 -0500 Subject: [PATCH 0257/1392] more tests --- cms/djangoapps/contentstore/tests/test_views.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index c1fa19624c..ed18e1cc8c 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -50,8 +50,14 @@ class ViewsTestCase(TestCase): self._MODULESTORES = {} self.course_id = 'edX/toy/2012_Fall' self.course_id_2 = 'edx/full/6.002_Spring_2012' - self.toy_course = modulestore().get_course(self.course_id) + #self.toy_course = modulestore().get_course(self.course_id) + # Problem: Classes persist, need to delete stuff from modulestore + self.course = CourseFactory.create() + print dir(self.course) + def tearDown(self): + pass + def test_has_access(self): user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) m = MagicMock() @@ -72,16 +78,15 @@ class ViewsTestCase(TestCase): self.user_2 = MagicMock(is_staff = True, is_active = True) self.user_2.is_authenticated.return_value = True request_2 = MagicMock(user = self.user_2) - # Bug? Raises error because calls modulestore().get_item(location) - #NotImplementedError: XMLModuleStores can't guarantee that definitions - #are unique. Use get_instance. + # Need to use XModuleStoreFactory? print views.course_index(request_2, 'edX', 'full', '6.002_Spring_2012') def test_edit_subsection(self): + # Redirects if request.user doesn't have access to location self.user = MagicMock(is_staff = False, is_active = False) self.user.is_authenticated.return_value = False self.request = MagicMock(user = self.user) - self.assertIsInstance(views.edit_subscription(self.request, self.location_2), + self.assertIsInstance(views.edit_subsection(self.request, self.location_2), HttpResponseRedirect) From 585f1c41d61aa962220c0d604058077093a77e95 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 29 Jan 2013 16:04:43 -0500 Subject: [PATCH 0258/1392] New jasmine tests for combined open ended problems. --- .../js/fixtures/combined-open-ended.html | 56 +++++++++++++++++++ .../combinedopenended/display_spec.coffee | 15 +++++ 2 files changed, 71 insertions(+) create mode 100644 common/lib/xmodule/xmodule/js/fixtures/combined-open-ended.html create mode 100644 common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee diff --git a/common/lib/xmodule/xmodule/js/fixtures/combined-open-ended.html b/common/lib/xmodule/xmodule/js/fixtures/combined-open-ended.html new file mode 100644 index 0000000000..c7170d3472 --- /dev/null +++ b/common/lib/xmodule/xmodule/js/fixtures/combined-open-ended.html @@ -0,0 +1,56 @@ +
    + +

    Problem 1

    +
    +

    Status

    +
    +
    + +
    + + Step 1 (Problem complete) : 1 / 1 + + +
    + +
    + + Step 2 (Being scored) : None / 1 + + +
    +
    +
    + +
    + +
    +

    Problem

    +
    +
    +
    + + Some prompt. + +
    +
    +
    + Submitted for grading. + +
    + +
    + + +
    +
    + + + + +
    + + +
    +
    +
    diff --git a/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee new file mode 100644 index 0000000000..60c73cf1fe --- /dev/null +++ b/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee @@ -0,0 +1,15 @@ +xdescribe 'CombinedOpenEnded', -> + beforeEach -> + spyOn Logger, 'log' + # load up some fixtures + loadFixtures 'combined-open-ended.html' + @element = $('.combined-open-ended') + + describe 'constructor', -> + beforeEach -> + @combined = new CombinedOpenEnded @element + + it 'set the element', -> + except(@combined.element).not.toEqual @element + + #it 'initialize the ajax url, state, and task count' From cb77209d3c4d8f435ab57e1aeac12369d5cb797e Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 29 Jan 2013 16:09:27 -0500 Subject: [PATCH 0259/1392] Add missing requirejs for xmodule jasmine tests --- common/lib/xmodule/jasmine_test_runner.html.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/common/lib/xmodule/jasmine_test_runner.html.erb b/common/lib/xmodule/jasmine_test_runner.html.erb index 3327ab4aea..fae6c14cbe 100644 --- a/common/lib/xmodule/jasmine_test_runner.html.erb +++ b/common/lib/xmodule/jasmine_test_runner.html.erb @@ -17,6 +17,7 @@ + + +
    +
    +

    City of Boston and edX partner to establish BostonX to improve educational access for residents

    +
    +
    +

    Pilot project offers online courses, educational support and jobs training through Boston community centers

    + +

    CAMBRIDGE, MA – January 29, 2013 – +EdX, the not-for-profit online learning initiative founded by Harvard University and the Massachusetts Institute of Technology (MIT), the not-for-profit online learning initiative founded by Harvard University and the Massachusetts Institute of Technology (MIT), announced today a pilot project with the City of Boston, Harvard and MIT to make online courses available through internet-connected Boston neighborhood community centers, high schools and libraries. A first-of-its-kind project, BostonX brings together innovators from the country’s center of higher education to offer Boston residents access to courses, internships, job training and placement services, and locations for edX students to gather, socialize and deepen learning.

    + +

    “We must connect adults and youth in our neighborhoods with the opportunities of the knowledge economy,†said Mayor Tom Menino. “BostonX will help update our neighbors’ skills and our community centers. As a first step, I’m pleased to announce a pilot with Harvard, MIT and edX, their online learning initiative, which will bring free courses and training to our community centers.â€

    + +

    BostonX builds on edX’s mission of expanding access to education and delivering high-quality courses on its cutting-edge platform using innovative tools and educational techniques. The City of Boston will provide BostonX sites at community centers with computer access and basic computer training, support for internships, career counseling, and job transitioning. Harvard, MIT and edX will work with the city to provide courses selected to eliminate skills gaps, in-person lessons from affiliated instructors, training in online learning best practices and certificates of mastery for those who successfully complete the courses.

    + +

    “EdX’s innovative content, learning methodologies and game-like laboratories and teaching methods are transforming education, from 16-year-old students in Bangladesh, to community college students at Bunker Hill and MassBay, and now learners across Boston,†said Anant Agarwal, President of edX. “We’re thrilled to be able to partner with Mayor Menino and the City of Boston to provide this first-ever experience and hope that this idea will spread and create a number of CityX’s around the world, including Cambridge, Massachusetts where edX was founded.â€

    + +

    This new pilot with the City of Boston follows another edX project with two Boston-area community colleges. This month, Bunker Hill and MassBay Community Colleges began offering an adapted version of the MITx 6.00x Introduction to Computer Science and Programming course at their respective campuses. The BostonX initiative goes one step further by allowing, encouraging and supporting residents of all ages, regardless of social status or neighborhood, to participate in life changing educational opportunities.

    + +

    About edX

    + +

    EdX is a not-for-profit enterprise of its founding partners Harvard University and the Massachusetts Institute of Technology focused on transforming online and on-campus learning through groundbreaking methodologies, game-like experiences and cutting-edge research. EdX provides inspirational and transformative knowledge to students of all ages, social status, and income who form worldwide communities of learners. EdX uses its open source technology to transcend physical and social borders. We’re focused on people, not profit. EdX is based in Cambridge, Massachusetts in the USA.

    + + +
    +

    Contact:

    +

    Brad Baker, Weber Shandwick for edX

    +

    BBaker@webershandwick.com

    +

    (617) 520-7043

    +
    + + +
    +
    +
    diff --git a/lms/urls.py b/lms/urls.py index 3353c8a6ba..f92b63aac2 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -117,12 +117,19 @@ urlpatterns = ('', url(r'^press/georgetown-joins-edx$', 'static_template_view.views.render', {'template': 'press_releases/Georgetown_joins_edX.html'}, name="press/georgetown-joins-edx"), url(r'^press/spring-courses$', 'static_template_view.views.render', - {'template': 'press_releases/Spring_2013_course_announcements.html'}, name="press/spring-courses"), + {'template': 'press_releases/Spring_2013_course_announcements.html'}, + name="press/spring-courses"), url(r'^press/lewin-course-announcement$', 'static_template_view.views.render', - {'template': 'press_releases/Lewin_course_announcement.html'}, name="press/lewin-course-announcement"), + {'template': 'press_releases/Lewin_course_announcement.html'}, + name="press/lewin-course-announcement"), + url(r'^press/bostonx-announcement$', 'static_template_view.views.render', + {'template': 'press_releases/bostonx_announcement.html'}, + name="press/bostonx-announcement"), + # Should this always update to point to the latest press release? - (r'^pressrelease$', 'django.views.generic.simple.redirect_to', {'url': '/press/lewin-course-announcement'}), + (r'^pressrelease$', 'django.views.generic.simple.redirect_to', + {'url': '/press/bostonx-announcement'}), (r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/static/images/favicon.ico'}), From 5bfd2c33b0ce96066a5b26befe57a7666e7776d0 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 29 Jan 2013 17:34:52 -0500 Subject: [PATCH 0266/1392] send cohort to post view context --- lms/djangoapps/django_comment_client/forum/views.py | 3 ++- lms/templates/discussion/_new_post.html | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index 29000a225f..9737d59537 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -11,7 +11,7 @@ from django.contrib.auth.models import User from mitxmako.shortcuts import render_to_response, render_to_string from courseware.courses import get_course_with_access -from course_groups.cohorts import get_cohort_id +from course_groups.cohorts import get_cohort_id, get_course_cohorts from courseware.access import has_access from urllib import urlencode @@ -166,6 +166,7 @@ def forum_form_discussion(request, course_id): 'category_map': category_map, 'roles': saxutils.escape(json.dumps(utils.get_role_ids(course_id)), escapedict), 'is_moderator': cached_has_permission(request.user, "see_all_cohorts", course_id), + 'cohorts': get_course_cohorts } # print "start rendering.." return render_to_response('discussion/index.html', context) diff --git a/lms/templates/discussion/_new_post.html b/lms/templates/discussion/_new_post.html index 26c886c6ac..c733704d09 100644 --- a/lms/templates/discussion/_new_post.html +++ b/lms/templates/discussion/_new_post.html @@ -45,13 +45,15 @@ %elif course.metadata.get("allow_anonymous_to_peers", False): %endif - % if true: + % if is_moderator:
    Make visible to:
    %endif From f1973dc660a5de9bfa24300a51e032fde151ee9c Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 29 Jan 2013 17:34:54 -0500 Subject: [PATCH 0267/1392] minor update to new jasmine test --- .../xmodule/js/spec/combinedopenended/display_spec.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee index 60c73cf1fe..3ccf504948 100644 --- a/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/combinedopenended/display_spec.coffee @@ -12,4 +12,5 @@ xdescribe 'CombinedOpenEnded', -> it 'set the element', -> except(@combined.element).not.toEqual @element - #it 'initialize the ajax url, state, and task count' + #it 'initialize the ajax url, state, and task count', -> + From 7b65f56121f5bc7627890a057d377d6073ecf8d3 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 17 Jan 2013 15:15:58 -0500 Subject: [PATCH 0268/1392] Add service to query controller for eta of submission and to check if name is unique --- .../controller_query_service.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 lms/djangoapps/open_ended_grading/controller_query_service.py diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py new file mode 100644 index 0000000000..608e37ea09 --- /dev/null +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -0,0 +1,37 @@ +import json +import logging +import requests +from requests.exceptions import RequestException, ConnectionError, HTTPError +import sys +from grading_service import GradingService +from grading_service import GradingServiceError + +from django.conf import settings +from django.http import HttpResponse, Http404 + +log = logging.getLogger(__name__) + +class ControllerQueryService(GradingService): + """ + Interface to staff grading backend. + """ + def __init__(self, config): + super(ControllerQuery, self).__init__(config) + self.check_eta_url = self.url + '/get_submission_eta/' + self.is_unique_url = self.url + '/is_name_unique/' + + def check_if_name_is_unique(self, location, problem_id, course_id): + params = { + 'course_id': course_id, + 'location' : location, + 'problem_id' : problem_id + } + response = self.get(self.is_unique_url, params) + return response + + def check_for_eta(self, location): + params = { + 'location' : location, + } + response = self.get(self.check_eta_url, params) + return response From 43783e4ff07c9a2ff9f9a11b92515d49e66abcb2 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 17 Jan 2013 15:18:39 -0500 Subject: [PATCH 0269/1392] Add in an item to check for combined notifications --- .../open_ended_grading/controller_query_service.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py index 608e37ea09..7ab8712c71 100644 --- a/lms/djangoapps/open_ended_grading/controller_query_service.py +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -19,6 +19,7 @@ class ControllerQueryService(GradingService): super(ControllerQuery, self).__init__(config) self.check_eta_url = self.url + '/get_submission_eta/' self.is_unique_url = self.url + '/is_name_unique/' + self.combined_notifications_url = self.url + '/combined_notifications/' def check_if_name_is_unique(self, location, problem_id, course_id): params = { @@ -35,3 +36,12 @@ class ControllerQueryService(GradingService): } response = self.get(self.check_eta_url, params) return response + + def check_combined_notifications(self, course_id, student_id): + params= { + 'student_id' : student_id, + 'course_id' : course_id, + } + response = self.get(self.combined_notifications_url,params) + return response + From c62ce7822e282ac4c34e9deb38d91ca3ecc9ab17 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 17 Jan 2013 16:16:13 -0500 Subject: [PATCH 0270/1392] Add in service support for getting the grading status list --- .../open_ended_grading/controller_query_service.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py index 7ab8712c71..220bc276db 100644 --- a/lms/djangoapps/open_ended_grading/controller_query_service.py +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -20,6 +20,7 @@ class ControllerQueryService(GradingService): self.check_eta_url = self.url + '/get_submission_eta/' self.is_unique_url = self.url + '/is_name_unique/' self.combined_notifications_url = self.url + '/combined_notifications/' + self.grading_status_list_url = self.url + '/get_grading_status_list/' def check_if_name_is_unique(self, location, problem_id, course_id): params = { @@ -37,11 +38,20 @@ class ControllerQueryService(GradingService): response = self.get(self.check_eta_url, params) return response - def check_combined_notifications(self, course_id, student_id): + def check_combined_notifications(self, course_id, student_id, user_is_staff, last_time_viewed): params= { 'student_id' : student_id, 'course_id' : course_id, + 'user_is_staff' : user_is_staff, + 'last_time_viewed' : last_time_viewed, } response = self.get(self.combined_notifications_url,params) return response + def get_grading_status_list(self, course_id, student_id): + params = { + 'student_id' : student_id, + 'course_id' : course_id, + } + + response = self.get(self.grading_status_list_url, params) From d28228639ec86b7733ec23057fa78a04eca3c28b Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 17 Jan 2013 16:58:35 -0500 Subject: [PATCH 0271/1392] Add in controller query stuff --- lms/djangoapps/courseware/tabs.py | 75 ++++++++++++++++------ lms/djangoapps/open_ended_grading/views.py | 40 ++++++++++++ 2 files changed, 95 insertions(+), 20 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 2ece7f0404..fe37dcde39 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -18,20 +18,12 @@ from django.core.urlresolvers import reverse from fs.errors import ResourceNotFoundError -from lxml.html import rewrite_links - -from module_render import get_module from courseware.access import has_access from static_replace import replace_urls -from xmodule.modulestore import Location -from xmodule.modulestore.django import modulestore -from xmodule.modulestore.xml import XMLModuleStore -from xmodule.x_module import XModule - - from open_ended_grading.peer_grading_service import PeerGradingService from open_ended_grading.staff_grading_service import StaffGradingService +from open_ended_grading.controller_query_service import ControllerQueryService from student.models import unique_id_for_user log = logging.getLogger(__name__) @@ -161,6 +153,38 @@ def _peer_grading(tab, user, course, active_page): return tab return [] +def _combined_open_ended_grading(tab, user, course, active_page): + if user.is_authenticated: + link = reverse('peer_grading', args=[course.id]) + peer_grading_url = settings.PEER_GRADING_INTERFACE + split_url = peer_grading_url.split("/") + controller_url = "http://" + split_url[2] + "/grading_controller" + log.debug(controller_url) + peer_gs = ControllerQueryService(controller_url) + student_id = unique_id_for_user(user) + course_id = course.id + user_is_staff = has_access(user, course, 'staff') + last_time_viewed = 1 + pending_grading= False + tab_name = "Peer grading" + img_path= "" + try: + notifications = json.loads(peer_gs.get_notifications(course.id,)) + if notifications['success']: + if notifications['student_needs_to_peer_grade']: + pending_grading=True + except: + #Non catastrophic error, so no real action + log.info("Problem with getting notifications from peer grading service.") + + if pending_grading: + img_path = "/static/images/slider-handle.png" + + tab = [CourseTab(tab_name, link, active_page == "peer_grading", pending_grading, img_path)] + return tab + return [] + + #### Validators @@ -314,16 +338,27 @@ def get_static_tab_by_slug(course, tab_slug): return None -def get_static_tab_contents(request, cache, course, tab): - loc = Location(course.location.tag, course.location.org, course.location.course, 'static_tab', tab['url_slug']) - tab_module = get_module(request.user, request, loc, cache, course.id) +def get_static_tab_contents(course, tab): + """ + Given a course and a static tab config dict, load the tab contents, + returning None if not found. - logging.debug('course_module = {0}'.format(tab_module)) - - html = '' - - if tab_module is not None: - html = tab_module.get_html() - - return html + Looks in tabs/{course_url_name}/{tab_slug}.html first, then tabs/{tab_slug}.html. + """ + slug = tab['url_slug'] + paths = ['tabs/{0}/{1}.html'.format(course.url_name, slug), + 'tabs/{0}.html'.format(slug)] + fs = course.system.resources_fs + for p in paths: + if fs.exists(p): + try: + with fs.open(p) as tabfile: + # TODO: redundant with module_render.py. Want to be helper methods in static_replace or something. + text = tabfile.read().decode('utf-8') + contents = replace_urls(text, course.metadata['data_dir']) + return replace_urls(contents, staticfiles_prefix='/courses/'+course.id, replace_prefix='/course/') + except (ResourceNotFoundError) as err: + log.exception("Couldn't load tab contents from '{0}': {1}".format(p, err)) + return None + return None diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 858c9a4fd5..c92ce21e21 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -114,5 +114,45 @@ def peer_grading_problem(request, course_id): 'ajax_url': ajax_url, # Checked above 'staff_access': False, }) + +@cache_control(no_cache=True, no_store=True, must_revalidate=True) +def student_problem_list(request, course_id, student_id): + ''' + Show a student problem list + ''' + course = get_course_with_access(request.user, course_id, 'load') + + # call problem list service + success = False + error_text = "" + problem_list = [] + try: + problem_list_json = peer_gs.get_problem_list(course_id, unique_id_for_user(request.user)) + problem_list_dict = json.loads(problem_list_json) + success = problem_list_dict['success'] + if 'error' in problem_list_dict: + error_text = problem_list_dict['error'] + + problem_list = problem_list_dict['problem_list'] + + except GradingServiceError: + error_text = "Error occured while contacting the grading service" + success = False + # catch error if if the json loads fails + except ValueError: + error_text = "Could not get problem list" + success = False + + ajax_url = _reverse_with_slash('peer_grading', course_id) + + return render_to_response('peer_grading/peer_grading.html', { + 'course': course, + 'course_id': course_id, + 'ajax_url': ajax_url, + 'success': success, + 'problem_list': problem_list, + 'error_text': error_text, + # Checked above + 'staff_access': False, }) From 5e63a4690be87a50ed5c6678faa578b18c4396de Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:18:04 -0500 Subject: [PATCH 0272/1392] Work on getting combined notifications --- lms/djangoapps/courseware/tabs.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index fe37dcde39..90c7687142 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -25,6 +25,8 @@ from open_ended_grading.peer_grading_service import PeerGradingService from open_ended_grading.staff_grading_service import StaffGradingService from open_ended_grading.controller_query_service import ControllerQueryService from student.models import unique_id_for_user +from models import StudentModule +import datetime log = logging.getLogger(__name__) @@ -160,27 +162,31 @@ def _combined_open_ended_grading(tab, user, course, active_page): split_url = peer_grading_url.split("/") controller_url = "http://" + split_url[2] + "/grading_controller" log.debug(controller_url) - peer_gs = ControllerQueryService(controller_url) + controller_qs = ControllerQueryService(controller_url) student_id = unique_id_for_user(user) course_id = course.id user_is_staff = has_access(user, course, 'staff') - last_time_viewed = 1 + + min_time_to_query = user.last_login + last_module_seen = StudentModule.objects.all(student=user, course_id = course_id, modified>min_time_to_query).values('modified').order_by('-modified')[0] + + last_time_viewed = last_module_seen['modified'] pending_grading= False - tab_name = "Peer grading" + tab_name = "Open Ended Questions" img_path= "" try: - notifications = json.loads(peer_gs.get_notifications(course.id,)) + notifications = json.loads(controller_qs.get_notifications(course.id,student_id, user_is_staff, last_time_viewed)) if notifications['success']: if notifications['student_needs_to_peer_grade']: pending_grading=True except: #Non catastrophic error, so no real action - log.info("Problem with getting notifications from peer grading service.") + log.info("Problem with getting notifications from controller query service.") if pending_grading: img_path = "/static/images/slider-handle.png" - tab = [CourseTab(tab_name, link, active_page == "peer_grading", pending_grading, img_path)] + tab = [CourseTab(tab_name, link, active_page == "controller_query", pending_grading, img_path)] return tab return [] From fe77bb00c411c88597ba5c9ea13e94b557487447 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:19:34 -0500 Subject: [PATCH 0273/1392] Fix naming for overall need to check --- lms/djangoapps/courseware/tabs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 90c7687142..1850ae3faf 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -177,7 +177,7 @@ def _combined_open_ended_grading(tab, user, course, active_page): try: notifications = json.loads(controller_qs.get_notifications(course.id,student_id, user_is_staff, last_time_viewed)) if notifications['success']: - if notifications['student_needs_to_peer_grade']: + if notifications['overall_need_to_check']: pending_grading=True except: #Non catastrophic error, so no real action From 2191f3e228548119ca624ffb13870c0a3d14123a Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:30:03 -0500 Subject: [PATCH 0274/1392] Add in open ended problems view --- lms/djangoapps/courseware/tabs.py | 2 +- lms/djangoapps/open_ended_grading/views.py | 9 +++-- .../open_ended_problems.html | 36 +++++++++++++++++++ lms/urls.py | 6 +++- 4 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 lms/templates/open_ended_problems/open_ended_problems.html diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 1850ae3faf..80c353c748 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -157,7 +157,7 @@ def _peer_grading(tab, user, course, active_page): def _combined_open_ended_grading(tab, user, course, active_page): if user.is_authenticated: - link = reverse('peer_grading', args=[course.id]) + link = reverse('open_ended_problems', args=[course.id]) peer_grading_url = settings.PEER_GRADING_INTERFACE split_url = peer_grading_url.split("/") controller_url = "http://" + split_url[2] + "/grading_controller" diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index c92ce21e21..471e00f5f0 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -13,6 +13,7 @@ from courseware.courses import get_course_with_access from peer_grading_service import PeerGradingService from peer_grading_service import MockPeerGradingService +from controller_query_service import ControllerQueryService from grading_service import GradingServiceError import json from .staff_grading import StaffGrading @@ -26,6 +27,8 @@ if settings.MOCK_PEER_GRADING: else: peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) +controller_qs = ControllerQueryService(settings.PEER_GRADING_INTERFACE) + """ Reverses the URL from the name and the course id, and then adds a trailing slash if it does not exist yet @@ -127,7 +130,7 @@ def student_problem_list(request, course_id, student_id): error_text = "" problem_list = [] try: - problem_list_json = peer_gs.get_problem_list(course_id, unique_id_for_user(request.user)) + problem_list_json = controller_qs.get_grading_status_list(course_id, unique_id_for_user(request.user)) problem_list_dict = json.loads(problem_list_json) success = problem_list_dict['success'] if 'error' in problem_list_dict: @@ -143,9 +146,9 @@ def student_problem_list(request, course_id, student_id): error_text = "Could not get problem list" success = False - ajax_url = _reverse_with_slash('peer_grading', course_id) + ajax_url = _reverse_with_slash('open_ended_problems', course_id) - return render_to_response('peer_grading/peer_grading.html', { + return render_to_response('open_ended_problems/open_ended_problems.html', { 'course': course, 'course_id': course_id, 'ajax_url': ajax_url, diff --git a/lms/templates/open_ended_problems/open_ended_problems.html b/lms/templates/open_ended_problems/open_ended_problems.html new file mode 100644 index 0000000000..ec648afab8 --- /dev/null +++ b/lms/templates/open_ended_problems/open_ended_problems.html @@ -0,0 +1,36 @@ +<%inherit file="/main.html" /> +<%block name="bodyclass">${course.css_class} +<%namespace name='static' file='/static_content.html'/> + +<%block name="headextra"> +<%static:css group='course'/> + + +<%block name="title">${course.number} Open Ended Problems + +<%include file="/courseware/course_navigation.html" args="active_page='open_ended_problems'" /> + + +
    +
    +
    ${error_text}
    +

    Open Ended Problems

    +

    Instructions

    +

    Here are a list of open ended problems for this course.

    + % if success: + % if len(problem_list) == 0: +
    + You have not attempted any open ended problems yet. +
    + %else: + + %endif + %endif +
    +
    \ No newline at end of file diff --git a/lms/urls.py b/lms/urls.py index f92b63aac2..c7c4f231f9 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -282,7 +282,11 @@ if settings.COURSEWARE_ENABLED: url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/peer_grading/save_calibration_essay$', 'open_ended_grading.peer_grading_service.save_calibration_essay', name='peer_grading_save_calibration_essay'), - # Cohorts management + # Open Ended problem list + url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_problems$', + 'open_ended_grading.views.student_problem_list', name='open_ended_problems'), + + # Cohorts management url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/cohorts$', 'course_groups.views.list_cohorts', name="cohorts"), url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/cohorts/add$', From b0599ea133d00bdff3b54975258d786620dd746f Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:34:48 -0500 Subject: [PATCH 0275/1392] Fix queries and some controller query stuff --- lms/djangoapps/courseware/tabs.py | 2 +- lms/djangoapps/open_ended_grading/controller_query_service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 80c353c748..75bb61b59a 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -168,7 +168,7 @@ def _combined_open_ended_grading(tab, user, course, active_page): user_is_staff = has_access(user, course, 'staff') min_time_to_query = user.last_login - last_module_seen = StudentModule.objects.all(student=user, course_id = course_id, modified>min_time_to_query).values('modified').order_by('-modified')[0] + last_module_seen = StudentModule.objects.all(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified')[0] last_time_viewed = last_module_seen['modified'] pending_grading= False diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py index 220bc276db..649f65dfac 100644 --- a/lms/djangoapps/open_ended_grading/controller_query_service.py +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -16,7 +16,7 @@ class ControllerQueryService(GradingService): Interface to staff grading backend. """ def __init__(self, config): - super(ControllerQuery, self).__init__(config) + super(ControllerQueryService, self).__init__(config) self.check_eta_url = self.url + '/get_submission_eta/' self.is_unique_url = self.url + '/is_name_unique/' self.combined_notifications_url = self.url + '/combined_notifications/' From e6dd07a41e3b2b31c9317ab5b22445db605781f2 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:39:49 -0500 Subject: [PATCH 0276/1392] Fix parameter passing --- lms/djangoapps/open_ended_grading/views.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 471e00f5f0..27be3d0939 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -17,6 +17,7 @@ from controller_query_service import ControllerQueryService from grading_service import GradingServiceError import json from .staff_grading import StaffGrading +from student.models import unique_id_for_user log = logging.getLogger(__name__) @@ -119,11 +120,12 @@ def peer_grading_problem(request, course_id): 'staff_access': False, }) @cache_control(no_cache=True, no_store=True, must_revalidate=True) -def student_problem_list(request, course_id, student_id): +def student_problem_list(request, course_id): ''' Show a student problem list ''' course = get_course_with_access(request.user, course_id, 'load') + student_id = unique_id_for_user(request.user) # call problem list service success = False From 693337593e928c2bb8d52d42b7691908b4f4b9e5 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:43:08 -0500 Subject: [PATCH 0277/1392] Properly parse url for grading controller --- lms/djangoapps/courseware/tabs.py | 7 +++---- lms/djangoapps/open_ended_grading/open_ended_util.py | 7 +++++++ lms/djangoapps/open_ended_grading/views.py | 5 ++++- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 lms/djangoapps/open_ended_grading/open_ended_util.py diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 75bb61b59a..01742092aa 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -24,6 +24,7 @@ from static_replace import replace_urls from open_ended_grading.peer_grading_service import PeerGradingService from open_ended_grading.staff_grading_service import StaffGradingService from open_ended_grading.controller_query_service import ControllerQueryService +from open_ended_grading import open_ended_util from student.models import unique_id_for_user from models import StudentModule import datetime @@ -158,10 +159,8 @@ def _peer_grading(tab, user, course, active_page): def _combined_open_ended_grading(tab, user, course, active_page): if user.is_authenticated: link = reverse('open_ended_problems', args=[course.id]) - peer_grading_url = settings.PEER_GRADING_INTERFACE - split_url = peer_grading_url.split("/") - controller_url = "http://" + split_url[2] + "/grading_controller" - log.debug(controller_url) + + controller_url = open_ended_util.get_controller_url() controller_qs = ControllerQueryService(controller_url) student_id = unique_id_for_user(user) course_id = course.id diff --git a/lms/djangoapps/open_ended_grading/open_ended_util.py b/lms/djangoapps/open_ended_grading/open_ended_util.py new file mode 100644 index 0000000000..b50cf3afb2 --- /dev/null +++ b/lms/djangoapps/open_ended_grading/open_ended_util.py @@ -0,0 +1,7 @@ +from django.conf import settings + +def get_controller_url(): + peer_grading_url = settings.PEER_GRADING_INTERFACE + split_url = peer_grading_url.split("/") + controller_url = "http://" + split_url[2] + "/grading_controller" + return controller_url diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 27be3d0939..3928fb7b85 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -19,6 +19,8 @@ import json from .staff_grading import StaffGrading from student.models import unique_id_for_user +import open_ended_util + log = logging.getLogger(__name__) @@ -28,7 +30,8 @@ if settings.MOCK_PEER_GRADING: else: peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) -controller_qs = ControllerQueryService(settings.PEER_GRADING_INTERFACE) +controller_url = open_ended_util.get_controller_url() +controller_qs = ControllerQueryService(controller_url) """ Reverses the URL from the name and the course id, and then adds a trailing slash if From f4574c75db61af0db9a99d571b7569ad11a60d4e Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:54:14 -0500 Subject: [PATCH 0278/1392] Proper config dictionary generation for controller query --- lms/djangoapps/open_ended_grading/open_ended_util.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/open_ended_util.py b/lms/djangoapps/open_ended_grading/open_ended_util.py index b50cf3afb2..772e3cd08e 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_util.py +++ b/lms/djangoapps/open_ended_grading/open_ended_util.py @@ -1,7 +1,12 @@ from django.conf import settings +import logging + +log=logging.getLogger(__name__) def get_controller_url(): - peer_grading_url = settings.PEER_GRADING_INTERFACE + peer_grading_url = settings.PEER_GRADING_INTERFACE['url'] split_url = peer_grading_url.split("/") controller_url = "http://" + split_url[2] + "/grading_controller" - return controller_url + controller_settings=settings.PEER_GRADING_INTERFACE + controller_settings['url'] = controller_url + return controller_settings From 61d62f274e526fe6a366312dc2b90285fd4a4c8b Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:57:20 -0500 Subject: [PATCH 0279/1392] Fix issue with parsing of open ended list --- lms/djangoapps/open_ended_grading/controller_query_service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py index 649f65dfac..a111cfe58d 100644 --- a/lms/djangoapps/open_ended_grading/controller_query_service.py +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -55,3 +55,4 @@ class ControllerQueryService(GradingService): } response = self.get(self.grading_status_list_url, params) + return response From 68db8b0d77f906994108a5c876260e26867b74e7 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 11:46:46 -0500 Subject: [PATCH 0280/1392] Refactor tab logic, start adding in combined notifications view --- lms/djangoapps/courseware/tabs.py | 64 ++--------------- .../open_ended_notifications.py | 72 +++++++++++++++++++ lms/djangoapps/open_ended_grading/views.py | 4 +- .../combined_notifications.html | 41 +++++++++++ 4 files changed, 121 insertions(+), 60 deletions(-) create mode 100644 lms/djangoapps/open_ended_grading/open_ended_notifications.py create mode 100644 lms/templates/open_ended_problems/combined_notifications.html diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 01742092aa..326c1a5cbd 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -21,13 +21,7 @@ from fs.errors import ResourceNotFoundError from courseware.access import has_access from static_replace import replace_urls -from open_ended_grading.peer_grading_service import PeerGradingService -from open_ended_grading.staff_grading_service import StaffGradingService -from open_ended_grading.controller_query_service import ControllerQueryService -from open_ended_grading import open_ended_util -from student.models import unique_id_for_user -from models import StudentModule -import datetime +from open_ended_grading import open_ended_notifications log = logging.getLogger(__name__) @@ -113,21 +107,8 @@ def _textbooks(tab, user, course, active_page): def _staff_grading(tab, user, course, active_page): if has_access(user, course, 'staff'): link = reverse('staff_grading', args=[course.id]) - staff_gs = StaffGradingService(settings.STAFF_GRADING_INTERFACE) - pending_grading=False tab_name = "Staff grading" - img_path= "" - try: - notifications = json.loads(staff_gs.get_notifications(course.id)) - if notifications['success']: - if notifications['staff_needs_to_grade']: - pending_grading=True - except: - #Non catastrophic error, so no real action - log.info("Problem with getting notifications from staff grading service.") - - if pending_grading: - img_path = "/static/images/slider-handle.png" + pending_grading, img_path = open_ended_notifications.staff_grading_notifications(course) tab = [CourseTab(tab_name, link, active_page == "staff_grading", pending_grading, img_path)] return tab @@ -136,21 +117,8 @@ def _staff_grading(tab, user, course, active_page): def _peer_grading(tab, user, course, active_page): if user.is_authenticated(): link = reverse('peer_grading', args=[course.id]) - peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) - pending_grading=False tab_name = "Peer grading" - img_path= "" - try: - notifications = json.loads(peer_gs.get_notifications(course.id,unique_id_for_user(user))) - if notifications['success']: - if notifications['student_needs_to_peer_grade']: - pending_grading=True - except: - #Non catastrophic error, so no real action - log.info("Problem with getting notifications from peer grading service.") - - if pending_grading: - img_path = "/static/images/slider-handle.png" + pending_grading, img_path = open_ended_notifications.peer_grading_notifications(course, user) tab = [CourseTab(tab_name, link, active_page == "peer_grading", pending_grading, img_path)] return tab @@ -159,31 +127,9 @@ def _peer_grading(tab, user, course, active_page): def _combined_open_ended_grading(tab, user, course, active_page): if user.is_authenticated: link = reverse('open_ended_problems', args=[course.id]) - - controller_url = open_ended_util.get_controller_url() - controller_qs = ControllerQueryService(controller_url) - student_id = unique_id_for_user(user) - course_id = course.id - user_is_staff = has_access(user, course, 'staff') - - min_time_to_query = user.last_login - last_module_seen = StudentModule.objects.all(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified')[0] - - last_time_viewed = last_module_seen['modified'] - pending_grading= False tab_name = "Open Ended Questions" - img_path= "" - try: - notifications = json.loads(controller_qs.get_notifications(course.id,student_id, user_is_staff, last_time_viewed)) - if notifications['success']: - if notifications['overall_need_to_check']: - pending_grading=True - except: - #Non catastrophic error, so no real action - log.info("Problem with getting notifications from controller query service.") - - if pending_grading: - img_path = "/static/images/slider-handle.png" + + pending_grading, img_path = open_ended_notifications.combined_notifications(course, user) tab = [CourseTab(tab_name, link, active_page == "controller_query", pending_grading, img_path)] return tab diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py new file mode 100644 index 0000000000..68f1509891 --- /dev/null +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -0,0 +1,72 @@ +from django.conf import settings +from staff_grading_service import StaffGradingService +from peer_grading_service import PeerGradingService +from open_ended_grading.controller_query_service import ControllerQueryService +import json +from student.models import unique_id_for_user +import open_ended_util +from courseware.models import StudentModule + +def staff_grading_notifications(course): + staff_gs = StaffGradingService(settings.STAFF_GRADING_INTERFACE) + pending_grading=False + img_path= "" + try: + notifications = json.loads(staff_gs.get_notifications(course.id)) + if notifications['success']: + if notifications['staff_needs_to_grade']: + pending_grading=True + except: + #Non catastrophic error, so no real action + log.info("Problem with getting notifications from staff grading service.") + + if pending_grading: + img_path = "/static/images/slider-handle.png" + + return pending_grading, img_path + +def peer_grading_notifications(course, user): + peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) + pending_grading=False + img_path= "" + try: + notifications = json.loads(peer_gs.get_notifications(course.id,unique_id_for_user(user))) + if notifications['success']: + if notifications['student_needs_to_peer_grade']: + pending_grading=True + except: + #Non catastrophic error, so no real action + log.info("Problem with getting notifications from peer grading service.") + + if pending_grading: + img_path = "/static/images/slider-handle.png" + + return pending_grading, img_path + +def combined_notifications(course, user): + controller_url = open_ended_util.get_controller_url() + controller_qs = ControllerQueryService(controller_url) + student_id = unique_id_for_user(user) + course_id = course.id + user_is_staff = has_access(user, course, 'staff') + + min_time_to_query = user.last_login + last_module_seen = StudentModule.objects.all(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified')[0] + + last_time_viewed = last_module_seen['modified'] + pending_grading= False + + img_path= "" + try: + notifications = json.loads(controller_qs.get_notifications(course.id,student_id, user_is_staff, last_time_viewed)) + if notifications['success']: + if notifications['overall_need_to_check']: + pending_grading=True + except: + #Non catastrophic error, so no real action + log.info("Problem with getting notifications from controller query service.") + + if pending_grading: + img_path = "/static/images/slider-handle.png" + + return pending_grading, img_path \ No newline at end of file diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 3928fb7b85..3da1fb0835 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -21,7 +21,6 @@ from student.models import unique_id_for_user import open_ended_util - log = logging.getLogger(__name__) template_imports = {'urllib': urllib} @@ -162,5 +161,8 @@ def student_problem_list(request, course_id): 'error_text': error_text, # Checked above 'staff_access': False, }) + +def combined_notifications(request, course_id): + pass diff --git a/lms/templates/open_ended_problems/combined_notifications.html b/lms/templates/open_ended_problems/combined_notifications.html new file mode 100644 index 0000000000..6cd2a095dc --- /dev/null +++ b/lms/templates/open_ended_problems/combined_notifications.html @@ -0,0 +1,41 @@ +<%inherit file="/main.html" /> +<%block name="bodyclass">${course.css_class} +<%namespace name='static' file='/static_content.html'/> + +<%block name="headextra"> +<%static:css group='course'/> + + +<%block name="title">${course.number} Combined Notifications + +<%include file="/courseware/course_navigation.html" args="active_page='combined_notifications'" /> + + +
    +
    +
    ${error_text}
    +

    Open Ended Console

    +

    Instructions

    +

    Here are items that could potentially need your attention.

    + % if success: + % if len(item_list) == 0: +
    + No items require attention at the moment. +
    + %else: + + %endif + %endif +
    +
    \ No newline at end of file From 4112f8ad8e0949823863f3af1e016536fe0fbc66 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 11:53:46 -0500 Subject: [PATCH 0281/1392] Pass back dictionaries where needed from notifications functions --- lms/djangoapps/courseware/tabs.py | 16 ++++++++++++---- .../open_ended_notifications.py | 6 +++--- lms/djangoapps/open_ended_grading/views.py | 4 +++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 326c1a5cbd..dfe5cb14b9 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -108,7 +108,10 @@ def _staff_grading(tab, user, course, active_page): if has_access(user, course, 'staff'): link = reverse('staff_grading', args=[course.id]) tab_name = "Staff grading" - pending_grading, img_path = open_ended_notifications.staff_grading_notifications(course) + + notifications = open_ended_notifications.staff_grading_notifications(course) + pending_grading = notifications['pending_grading'] + img_path = notifications['img_path'] tab = [CourseTab(tab_name, link, active_page == "staff_grading", pending_grading, img_path)] return tab @@ -118,7 +121,10 @@ def _peer_grading(tab, user, course, active_page): if user.is_authenticated(): link = reverse('peer_grading', args=[course.id]) tab_name = "Peer grading" - pending_grading, img_path = open_ended_notifications.peer_grading_notifications(course, user) + + notifications = open_ended_notifications.peer_grading_notifications(course, user) + pending_grading = notifications['pending_grading'] + img_path = notifications['img_path'] tab = [CourseTab(tab_name, link, active_page == "peer_grading", pending_grading, img_path)] return tab @@ -128,8 +134,10 @@ def _combined_open_ended_grading(tab, user, course, active_page): if user.is_authenticated: link = reverse('open_ended_problems', args=[course.id]) tab_name = "Open Ended Questions" - - pending_grading, img_path = open_ended_notifications.combined_notifications(course, user) + + notifications = open_ended_notifications.combined_notifications(course, user) + pending_grading = notifications['pending_grading'] + img_path = notifications['img_path'] tab = [CourseTab(tab_name, link, active_page == "controller_query", pending_grading, img_path)] return tab diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 68f1509891..d394769f1e 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -23,7 +23,7 @@ def staff_grading_notifications(course): if pending_grading: img_path = "/static/images/slider-handle.png" - return pending_grading, img_path + return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} def peer_grading_notifications(course, user): peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) @@ -41,7 +41,7 @@ def peer_grading_notifications(course, user): if pending_grading: img_path = "/static/images/slider-handle.png" - return pending_grading, img_path + return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} def combined_notifications(course, user): controller_url = open_ended_util.get_controller_url() @@ -69,4 +69,4 @@ def combined_notifications(course, user): if pending_grading: img_path = "/static/images/slider-handle.png" - return pending_grading, img_path \ No newline at end of file + return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} \ No newline at end of file diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 3da1fb0835..e6841ccbd3 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -20,6 +20,7 @@ from .staff_grading import StaffGrading from student.models import unique_id_for_user import open_ended_util +import open_ended_notifications log = logging.getLogger(__name__) @@ -163,6 +164,7 @@ def student_problem_list(request, course_id): 'staff_access': False, }) def combined_notifications(request, course_id): - pass + user = request.user + From 22a2bdaa3d735b175d312cf26e85f066239775dc Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 11:57:26 -0500 Subject: [PATCH 0282/1392] Disable student problem list caching, build out notifications --- lms/djangoapps/courseware/tabs.py | 8 ++++---- .../open_ended_grading/open_ended_notifications.py | 11 +++++------ lms/djangoapps/open_ended_grading/views.py | 3 +++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index dfe5cb14b9..7a8367a42b 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -108,8 +108,8 @@ def _staff_grading(tab, user, course, active_page): if has_access(user, course, 'staff'): link = reverse('staff_grading', args=[course.id]) tab_name = "Staff grading" - - notifications = open_ended_notifications.staff_grading_notifications(course) + + notifications = open_ended_notifications.staff_grading_notifications(course_id) pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] @@ -122,7 +122,7 @@ def _peer_grading(tab, user, course, active_page): link = reverse('peer_grading', args=[course.id]) tab_name = "Peer grading" - notifications = open_ended_notifications.peer_grading_notifications(course, user) + notifications = open_ended_notifications.peer_grading_notifications(course_id, user) pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] @@ -135,7 +135,7 @@ def _combined_open_ended_grading(tab, user, course, active_page): link = reverse('open_ended_problems', args=[course.id]) tab_name = "Open Ended Questions" - notifications = open_ended_notifications.combined_notifications(course, user) + notifications = open_ended_notifications.combined_notifications(course_id, user) pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index d394769f1e..31b7a40dff 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -7,12 +7,12 @@ from student.models import unique_id_for_user import open_ended_util from courseware.models import StudentModule -def staff_grading_notifications(course): +def staff_grading_notifications(course_id): staff_gs = StaffGradingService(settings.STAFF_GRADING_INTERFACE) pending_grading=False img_path= "" try: - notifications = json.loads(staff_gs.get_notifications(course.id)) + notifications = json.loads(staff_gs.get_notifications(course_id)) if notifications['success']: if notifications['staff_needs_to_grade']: pending_grading=True @@ -25,12 +25,12 @@ def staff_grading_notifications(course): return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} -def peer_grading_notifications(course, user): +def peer_grading_notifications(course_id, user): peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) pending_grading=False img_path= "" try: - notifications = json.loads(peer_gs.get_notifications(course.id,unique_id_for_user(user))) + notifications = json.loads(peer_gs.get_notifications(course_id,unique_id_for_user(user))) if notifications['success']: if notifications['student_needs_to_peer_grade']: pending_grading=True @@ -43,11 +43,10 @@ def peer_grading_notifications(course, user): return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} -def combined_notifications(course, user): +def combined_notifications(course_id, user): controller_url = open_ended_util.get_controller_url() controller_qs = ControllerQueryService(controller_url) student_id = unique_id_for_user(user) - course_id = course.id user_is_staff = has_access(user, course, 'staff') min_time_to_query = user.last_login diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index e6841ccbd3..3797c2fbb2 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -163,8 +163,11 @@ def student_problem_list(request, course_id): # Checked above 'staff_access': False, }) +@cache_control(no_cache=True, no_store=True, must_revalidate=True) def combined_notifications(request, course_id): user = request.user + notifications = open_ended_notifications.combined_notifications(course_id, user) + response = notifications['response'] From 6b7ba3799993c2a8a48d78f6b39fccc4e303ae5b Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 12:09:34 -0500 Subject: [PATCH 0283/1392] Combined notification view --- .../open_ended_notifications.py | 6 +++++ lms/djangoapps/open_ended_grading/views.py | 25 +++++++++++++++++++ .../combined_notifications.html | 6 ++--- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 31b7a40dff..516b19e326 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -7,6 +7,12 @@ from student.models import unique_id_for_user import open_ended_util from courseware.models import StudentModule +NOTIFICATION_TYPES = ( + ('student_needs_to_peer_grade', 'peer_grading', 'Peer Grading'), + ('staff_needs_to_grade', 'staff_grading', 'Staff Grading'), + ('overall_need_to_check', 'open_ended_problems', 'Problems you have submitted') + ) + def staff_grading_notifications(course_id): staff_gs = StaffGradingService(settings.STAFF_GRADING_INTERFACE) pending_grading=False diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 3797c2fbb2..a1907ae230 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -168,6 +168,31 @@ def combined_notifications(request, course_id): user = request.user notifications = open_ended_notifications.combined_notifications(course_id, user) response = notifications['response'] + notificaton_tuples=open_ended_notifications.NOTIFICATION_TYPES + notification_list = [] + for response_num in xrange(0,len(notification_tuples)): + tag=notification_tuples[response_num][0] + if tag in response: + url_name = notification_tuples[response_num][1] + human_name = notification_tuples[response_num][2] + url = _reverse_with_slash(url_name, course_id) + has_img = response[tag] + img_path = "/static/images/slider-handle.png" + + notification_item = { + 'url' : url, + 'name' : human_name, + 'has_img' : has_img, + 'img' : img_path, + } + notification_list.append(notification_item) + + combined_dict = { + 'error_text' : "", + 'notification_list' : notification_list, + } + + return combined_dict diff --git a/lms/templates/open_ended_problems/combined_notifications.html b/lms/templates/open_ended_problems/combined_notifications.html index 6cd2a095dc..9fdedb2555 100644 --- a/lms/templates/open_ended_problems/combined_notifications.html +++ b/lms/templates/open_ended_problems/combined_notifications.html @@ -18,7 +18,7 @@

    Instructions

    Here are items that could potentially need your attention.

    % if success: - % if len(item_list) == 0: + % if len(notification_list) == 0:
    No items require attention at the moment.
    @@ -28,8 +28,8 @@
  • {notification['name']} - % if notification.has_img == True: - + % if notification['has_img'] == True: + %endif
  • From 0f212cc8f291847efa799c329dcc66dddac93b83 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 12:53:20 -0500 Subject: [PATCH 0284/1392] Fix course id passing, template rendering --- lms/djangoapps/courseware/tabs.py | 6 +++--- .../open_ended_notifications.py | 21 ++++++++++++++----- lms/djangoapps/open_ended_grading/views.py | 11 +++++++--- lms/urls.py | 5 ++++- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 7a8367a42b..3aa502e95e 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -109,7 +109,7 @@ def _staff_grading(tab, user, course, active_page): link = reverse('staff_grading', args=[course.id]) tab_name = "Staff grading" - notifications = open_ended_notifications.staff_grading_notifications(course_id) + notifications = open_ended_notifications.staff_grading_notifications(course) pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] @@ -122,7 +122,7 @@ def _peer_grading(tab, user, course, active_page): link = reverse('peer_grading', args=[course.id]) tab_name = "Peer grading" - notifications = open_ended_notifications.peer_grading_notifications(course_id, user) + notifications = open_ended_notifications.peer_grading_notifications(course, user) pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] @@ -135,7 +135,7 @@ def _combined_open_ended_grading(tab, user, course, active_page): link = reverse('open_ended_problems', args=[course.id]) tab_name = "Open Ended Questions" - notifications = open_ended_notifications.combined_notifications(course_id, user) + notifications = open_ended_notifications.combined_notifications(course, user) pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 516b19e326..9ab75833ca 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -6,6 +6,10 @@ import json from student.models import unique_id_for_user import open_ended_util from courseware.models import StudentModule +import logging +from courseware.access import has_access + +log=logging.getLogger(__name__) NOTIFICATION_TYPES = ( ('student_needs_to_peer_grade', 'peer_grading', 'Peer Grading'), @@ -13,10 +17,11 @@ NOTIFICATION_TYPES = ( ('overall_need_to_check', 'open_ended_problems', 'Problems you have submitted') ) -def staff_grading_notifications(course_id): +def staff_grading_notifications(course): staff_gs = StaffGradingService(settings.STAFF_GRADING_INTERFACE) pending_grading=False img_path= "" + course_id = course.id try: notifications = json.loads(staff_gs.get_notifications(course_id)) if notifications['success']: @@ -24,6 +29,7 @@ def staff_grading_notifications(course_id): pending_grading=True except: #Non catastrophic error, so no real action + notifications = {} log.info("Problem with getting notifications from staff grading service.") if pending_grading: @@ -31,10 +37,12 @@ def staff_grading_notifications(course_id): return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} -def peer_grading_notifications(course_id, user): +def peer_grading_notifications(course, user): peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) pending_grading=False img_path= "" + course_id = course.id + try: notifications = json.loads(peer_gs.get_notifications(course_id,unique_id_for_user(user))) if notifications['success']: @@ -42,6 +50,7 @@ def peer_grading_notifications(course_id, user): pending_grading=True except: #Non catastrophic error, so no real action + notifications = {} log.info("Problem with getting notifications from peer grading service.") if pending_grading: @@ -49,14 +58,15 @@ def peer_grading_notifications(course_id, user): return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} -def combined_notifications(course_id, user): +def combined_notifications(course, user): controller_url = open_ended_util.get_controller_url() controller_qs = ControllerQueryService(controller_url) student_id = unique_id_for_user(user) - user_is_staff = has_access(user, course, 'staff') + user_is_staff = has_access(user, course, 'staff') + course_id = course.id min_time_to_query = user.last_login - last_module_seen = StudentModule.objects.all(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified')[0] + last_module_seen = StudentModule.objects.filter(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified')[0] last_time_viewed = last_module_seen['modified'] pending_grading= False @@ -69,6 +79,7 @@ def combined_notifications(course_id, user): pending_grading=True except: #Non catastrophic error, so no real action + notifications = {} log.info("Problem with getting notifications from controller query service.") if pending_grading: diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index a1907ae230..c617eaac3f 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -165,10 +165,12 @@ def student_problem_list(request, course_id): @cache_control(no_cache=True, no_store=True, must_revalidate=True) def combined_notifications(request, course_id): + course = get_course_with_access(request.user, course_id, 'load') user = request.user - notifications = open_ended_notifications.combined_notifications(course_id, user) + notifications = open_ended_notifications.combined_notifications(course, user) response = notifications['response'] - notificaton_tuples=open_ended_notifications.NOTIFICATION_TYPES + notification_tuples=open_ended_notifications.NOTIFICATION_TYPES + notification_list = [] for response_num in xrange(0,len(notification_tuples)): @@ -191,8 +193,11 @@ def combined_notifications(request, course_id): combined_dict = { 'error_text' : "", 'notification_list' : notification_list, + 'course' : course, } - return combined_dict + return render_to_response('open_ended_problems/combined_notifications.html', + combined_dict + ) diff --git a/lms/urls.py b/lms/urls.py index c7c4f231f9..4b3cc94cab 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -285,7 +285,7 @@ if settings.COURSEWARE_ENABLED: # Open Ended problem list url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_problems$', 'open_ended_grading.views.student_problem_list', name='open_ended_problems'), - + # Cohorts management url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/cohorts$', 'course_groups.views.list_cohorts', name="cohorts"), @@ -305,6 +305,9 @@ if settings.COURSEWARE_ENABLED: 'course_groups.views.debug_cohort_mgmt', name="debug_cohort_mgmt"), + # Open Ended Notifications + url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_notifications$', + 'open_ended_grading.views.combined_notifications', name='open_ended_notifications'), ) # discussion forums live within courseware, so courseware must be enabled first From 8602e1595bf7819dd7ff1aad13f4c350d18e63a4 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 13:13:57 -0500 Subject: [PATCH 0285/1392] Pass proper parameters, fix templating --- .../open_ended_notifications.py | 6 ++-- .../open_ended_grading/open_ended_util.py | 2 +- lms/djangoapps/open_ended_grading/views.py | 7 +++- .../combined_notifications.html | 36 +++++++++---------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 9ab75833ca..a5faef1011 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -73,14 +73,16 @@ def combined_notifications(course, user): img_path= "" try: - notifications = json.loads(controller_qs.get_notifications(course.id,student_id, user_is_staff, last_time_viewed)) + controller_response = controller_qs.check_combined_notifications(course.id,student_id, user_is_staff, last_time_viewed) + log.debug(controller_response) + notifications = json.loads(controller_response) if notifications['success']: if notifications['overall_need_to_check']: pending_grading=True except: #Non catastrophic error, so no real action notifications = {} - log.info("Problem with getting notifications from controller query service.") + log.exception("Problem with getting notifications from controller query service.") if pending_grading: img_path = "/static/images/slider-handle.png" diff --git a/lms/djangoapps/open_ended_grading/open_ended_util.py b/lms/djangoapps/open_ended_grading/open_ended_util.py index 772e3cd08e..07744d7d2c 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_util.py +++ b/lms/djangoapps/open_ended_grading/open_ended_util.py @@ -7,6 +7,6 @@ def get_controller_url(): peer_grading_url = settings.PEER_GRADING_INTERFACE['url'] split_url = peer_grading_url.split("/") controller_url = "http://" + split_url[2] + "/grading_controller" - controller_settings=settings.PEER_GRADING_INTERFACE + controller_settings=settings.PEER_GRADING_INTERFACE.copy() controller_settings['url'] = controller_url return controller_settings diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index c617eaac3f..bfa7d89337 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -168,10 +168,10 @@ def combined_notifications(request, course_id): course = get_course_with_access(request.user, course_id, 'load') user = request.user notifications = open_ended_notifications.combined_notifications(course, user) + log.debug(notifications) response = notifications['response'] notification_tuples=open_ended_notifications.NOTIFICATION_TYPES - notification_list = [] for response_num in xrange(0,len(notification_tuples)): tag=notification_tuples[response_num][0] @@ -190,12 +190,17 @@ def combined_notifications(request, course_id): } notification_list.append(notification_item) + ajax_url = _reverse_with_slash('open_ended_notifications', course_id) combined_dict = { 'error_text' : "", 'notification_list' : notification_list, 'course' : course, + 'success' : True, + 'ajax_url' : ajax_url, } + log.debug(combined_dict) + return render_to_response('open_ended_problems/combined_notifications.html', combined_dict ) diff --git a/lms/templates/open_ended_problems/combined_notifications.html b/lms/templates/open_ended_problems/combined_notifications.html index 9fdedb2555..d14b2b9d9c 100644 --- a/lms/templates/open_ended_problems/combined_notifications.html +++ b/lms/templates/open_ended_problems/combined_notifications.html @@ -18,24 +18,24 @@

    Instructions

    Here are items that could potentially need your attention.

    % if success: - % if len(notification_list) == 0: -
    - No items require attention at the moment. -
    - %else: - - %endif + % if len(notification_list) == 0: +
    + No items require attention at the moment. +
    + %else: + + %endif %endif
    \ No newline at end of file From f47c431fafb4bba475ab0b093910aa07b21174c6 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 13:22:30 -0500 Subject: [PATCH 0286/1392] Fix templating --- .../open_ended_grading/controller_query_service.py | 1 + lms/djangoapps/open_ended_grading/views.py | 7 +++++-- .../open_ended_problems/combined_notifications.html | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py index a111cfe58d..7d515e2475 100644 --- a/lms/djangoapps/open_ended_grading/controller_query_service.py +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -45,6 +45,7 @@ class ControllerQueryService(GradingService): 'user_is_staff' : user_is_staff, 'last_time_viewed' : last_time_viewed, } + log.debug(self.combined_notifications_url) response = self.get(self.combined_notifications_url,params) return response diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index bfa7d89337..84bf14bf0e 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -39,11 +39,14 @@ it does not exist yet """ def _reverse_with_slash(url_name, course_id): - ajax_url = reverse(url_name, kwargs={'course_id': course_id}) + ajax_url = _reverse_without_slash(url_name, course_id) if not ajax_url.endswith('/'): ajax_url += '/' return ajax_url +def _reverse_without_slash(url_name, course_id): + ajax_url = reverse(url_name, kwargs={'course_id': course_id}) + return ajax_url @cache_control(no_cache=True, no_store=True, must_revalidate=True) def staff_grading(request, course_id): @@ -178,7 +181,7 @@ def combined_notifications(request, course_id): if tag in response: url_name = notification_tuples[response_num][1] human_name = notification_tuples[response_num][2] - url = _reverse_with_slash(url_name, course_id) + url = _reverse_without_slash(url_name, course_id) has_img = response[tag] img_path = "/static/images/slider-handle.png" diff --git a/lms/templates/open_ended_problems/combined_notifications.html b/lms/templates/open_ended_problems/combined_notifications.html index d14b2b9d9c..6d8541b567 100644 --- a/lms/templates/open_ended_problems/combined_notifications.html +++ b/lms/templates/open_ended_problems/combined_notifications.html @@ -27,7 +27,7 @@ %for notification in notification_list:
  • - {notification['name']} + ${notification['name']} % if notification['has_img'] == True: %endif From 457afaaedab2f57fe7a872b5ef37ebc2323c7e75 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 14:14:28 -0500 Subject: [PATCH 0287/1392] Making tab render properly for open ended notifications --- lms/djangoapps/courseware/tabs.py | 1 + lms/djangoapps/open_ended_grading/views.py | 19 ++++++++++++++++++- .../open_ended_problems.html | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 3aa502e95e..b1e56ead08 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -181,6 +181,7 @@ VALID_TAB_TYPES = { 'static_tab': TabImpl(key_checker(['name', 'url_slug']), _static_tab), 'peer_grading': TabImpl(null_validator, _peer_grading), 'staff_grading': TabImpl(null_validator, _staff_grading), + 'open_ended': TabImpl(null_validator, _combined_open_ended_grading), } diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 84bf14bf0e..29c3c3ebd3 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -22,6 +22,9 @@ from student.models import unique_id_for_user import open_ended_util import open_ended_notifications +from xmodule.modulestore.django import modulestore +from xmodule.modulestore import search + log = logging.getLogger(__name__) template_imports = {'urllib': urllib} @@ -137,6 +140,8 @@ def student_problem_list(request, course_id): success = False error_text = "" problem_list = [] + base_course_url = reverse('courses') + try: problem_list_json = controller_qs.get_grading_status_list(course_id, unique_id_for_user(request.user)) problem_list_dict = json.loads(problem_list_json) @@ -146,6 +151,19 @@ def student_problem_list(request, course_id): problem_list = problem_list_dict['problem_list'] + for i in xrange(0,len(problem_list)): + problem_url_parts = search.path_to_location(modulestore(), course.id, problem_list[i]['location']) + log.debug(problem_url_parts) + problem_url = base_course_url + "/" + for z in xrange(0,len(problem_url_parts)): + part = problem_url_parts[z] + if part is not None: + if z==1: + problem_url += "courseware/" + problem_url += part + "/" + + problem_list[i].update({'actual_url' : problem_url}) + except GradingServiceError: error_text = "Error occured while contacting the grading service" success = False @@ -171,7 +189,6 @@ def combined_notifications(request, course_id): course = get_course_with_access(request.user, course_id, 'load') user = request.user notifications = open_ended_notifications.combined_notifications(course, user) - log.debug(notifications) response = notifications['response'] notification_tuples=open_ended_notifications.NOTIFICATION_TYPES diff --git a/lms/templates/open_ended_problems/open_ended_problems.html b/lms/templates/open_ended_problems/open_ended_problems.html index ec648afab8..da309664eb 100644 --- a/lms/templates/open_ended_problems/open_ended_problems.html +++ b/lms/templates/open_ended_problems/open_ended_problems.html @@ -26,7 +26,7 @@ From d3d4e557d69da545f26d20d724a46853056295ec Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 14:16:18 -0500 Subject: [PATCH 0288/1392] Fix notification display --- lms/djangoapps/courseware/tabs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index b1e56ead08..7224657b60 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -132,8 +132,8 @@ def _peer_grading(tab, user, course, active_page): def _combined_open_ended_grading(tab, user, course, active_page): if user.is_authenticated: - link = reverse('open_ended_problems', args=[course.id]) - tab_name = "Open Ended Questions" + link = reverse('open_ended_notifications', args=[course.id]) + tab_name = "Open Ended Panel" notifications = open_ended_notifications.combined_notifications(course, user) pending_grading = notifications['pending_grading'] From bb55792b2bbf333812f0a3f4fbfdd9cd082102f7 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 14:21:17 -0500 Subject: [PATCH 0289/1392] Make things less noisy (remove debug statements) --- lms/djangoapps/open_ended_grading/views.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 29c3c3ebd3..55f4907687 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -153,7 +153,6 @@ def student_problem_list(request, course_id): for i in xrange(0,len(problem_list)): problem_url_parts = search.path_to_location(modulestore(), course.id, problem_list[i]['location']) - log.debug(problem_url_parts) problem_url = base_course_url + "/" for z in xrange(0,len(problem_url_parts)): part = problem_url_parts[z] @@ -219,8 +218,6 @@ def combined_notifications(request, course_id): 'ajax_url' : ajax_url, } - log.debug(combined_dict) - return render_to_response('open_ended_problems/combined_notifications.html', combined_dict ) From 6412eb40809ed2140192a2764abfd9556d489471 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 10:19:34 -0500 Subject: [PATCH 0290/1392] Fix naming for overall need to check --- lms/djangoapps/courseware/tabs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 7224657b60..a53e4bfb0a 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -107,6 +107,7 @@ def _textbooks(tab, user, course, active_page): def _staff_grading(tab, user, course, active_page): if has_access(user, course, 'staff'): link = reverse('staff_grading', args=[course.id]) + tab_name = "Staff grading" notifications = open_ended_notifications.staff_grading_notifications(course) @@ -118,6 +119,7 @@ def _staff_grading(tab, user, course, active_page): return [] def _peer_grading(tab, user, course, active_page): + if user.is_authenticated(): link = reverse('peer_grading', args=[course.id]) tab_name = "Peer grading" From 0630f59c06bba9c75d6ba8cef9ac75e2ad7e5c69 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 13:13:57 -0500 Subject: [PATCH 0291/1392] Pass proper parameters, fix templating --- lms/djangoapps/open_ended_grading/views.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 55f4907687..ad59262536 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -188,6 +188,7 @@ def combined_notifications(request, course_id): course = get_course_with_access(request.user, course_id, 'load') user = request.user notifications = open_ended_notifications.combined_notifications(course, user) + log.debug(notifications) response = notifications['response'] notification_tuples=open_ended_notifications.NOTIFICATION_TYPES @@ -218,6 +219,8 @@ def combined_notifications(request, course_id): 'ajax_url' : ajax_url, } + log.debug(combined_dict) + return render_to_response('open_ended_problems/combined_notifications.html', combined_dict ) From 33003e65d443cd6d36c0de6bceb045a035160cf1 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 14:21:17 -0500 Subject: [PATCH 0292/1392] Make things less noisy (remove debug statements) --- lms/djangoapps/open_ended_grading/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index ad59262536..931cbb7337 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -219,8 +219,6 @@ def combined_notifications(request, course_id): 'ajax_url' : ajax_url, } - log.debug(combined_dict) - return render_to_response('open_ended_problems/combined_notifications.html', combined_dict ) From 5291271591e8eb856517b6c3f13e893509fb51db Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 14:33:18 -0500 Subject: [PATCH 0293/1392] Add in some minimal checking to make sure that the max score and scores for each rubric point are 3 --- .../lib/xmodule/xmodule/combined_open_ended_module.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index aa4b1f18ad..98018e5d80 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -141,11 +141,11 @@ class CombinedOpenEndedModule(XModule): self._max_score = int(self.metadata.get('max_score', MAX_SCORE)) rubric_renderer = CombinedOpenEndedRubric(system, True) - try: - rubric_feedback = rubric_renderer.render_rubric(stringify_children(definition['rubric'])) - except RubricParsingError: - log.error("Failed to parse rubric in location: {1}".format(location)) - raise + success, rubric_feedback = rubric_renderer.render_rubric(stringify_children(definition['rubric'])) + if not success: + error_message="Could not parse rubric : {0}".format(definition['rubric']) + log.exception(error_message) + raise Exception #Static data is passed to the child modules to render self.static_data = { 'max_score': self._max_score, From 29f738f7ce3480dd17f971fb4a7dc9f785cfb9ac Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 14:34:08 -0500 Subject: [PATCH 0294/1392] Minor count fix --- .../xmodule/combined_open_ended_module.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 98018e5d80..53bfcf7673 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -35,6 +35,9 @@ MAX_ATTEMPTS = 10000 # Overriden by max_score specified in xml. MAX_SCORE = 1 +#The highest score allowed for the overall xmodule and for each rubric point +MAX_SCORE_ALLOWED = 3 + class CombinedOpenEndedModule(XModule): """ This is a module that encapsulates all open ended grading (self assessment, peer assessment, etc). @@ -140,12 +143,25 @@ class CombinedOpenEndedModule(XModule): # completion (doesn't matter if you self-assessed correct/incorrect). self._max_score = int(self.metadata.get('max_score', MAX_SCORE)) + if self._max_score>MAX_SCORE_ALLOWED: + error_message="Max score {0} is higher than max score allowed {1}".format(self._max_score, MAX_SCORE_ALLOWED) + log.exception(error_message) + raise Exception + rubric_renderer = CombinedOpenEndedRubric(system, True) success, rubric_feedback = rubric_renderer.render_rubric(stringify_children(definition['rubric'])) if not success: error_message="Could not parse rubric : {0}".format(definition['rubric']) log.exception(error_message) raise Exception + + rubric_categories = rubric_renderer.extract_categories(stringify_children(definition['rubric'])) + for category in rubric_categories: + if len(category['options'])>MAX_SCORE_ALLOWED: + error_message="Number of score points in rubric higher than the max allowed, which is {0} : {1}".format(MAX_SCORE_ALLOWED, definition['rubric']) + log.exception(error_message) + raise Exception + #Static data is passed to the child modules to render self.static_data = { 'max_score': self._max_score, From 3531bce7d3c0726d2bcf0ad4bbf0fa357768eff0 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 15:10:12 -0500 Subject: [PATCH 0295/1392] Fix score checking, latest post assessment scraping --- common/lib/xmodule/xmodule/combined_open_ended_module.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 53bfcf7673..df8efc30c6 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -157,8 +157,8 @@ class CombinedOpenEndedModule(XModule): rubric_categories = rubric_renderer.extract_categories(stringify_children(definition['rubric'])) for category in rubric_categories: - if len(category['options'])>MAX_SCORE_ALLOWED: - error_message="Number of score points in rubric higher than the max allowed, which is {0} : {1}".format(MAX_SCORE_ALLOWED, definition['rubric']) + if len(category['options'])>(MAX_SCORE_ALLOWED+1): + error_message="Number of score points in rubric {0} higher than the max allowed, which is {1}".format(len(category['options']) , MAX_SCORE_ALLOWED) log.exception(error_message) raise Exception From 8b8c1dbe60b71997e2149ac882fe9c576738f715 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 17:29:09 -0500 Subject: [PATCH 0296/1392] Fix query error --- .../open_ended_grading/open_ended_notifications.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index a5faef1011..3529e124b4 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -66,9 +66,14 @@ def combined_notifications(course, user): course_id = course.id min_time_to_query = user.last_login - last_module_seen = StudentModule.objects.filter(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified')[0] + last_module_seen = StudentModule.objects.filter(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified') + last_module_seen_count = last_module_seen.count() + + if last_module_seen_count>0: + last_time_viewed = last_module_seen[0]['modified'] + else: + last_time_viewed = user.last_login - last_time_viewed = last_module_seen['modified'] pending_grading= False img_path= "" From 68f563a178e09be74aa0cd447972aa4d2e94ba77 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Tue, 22 Jan 2013 17:35:40 -0500 Subject: [PATCH 0297/1392] Fix naming issue --- lms/djangoapps/open_ended_grading/open_ended_notifications.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 3529e124b4..d6621e468a 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -14,7 +14,7 @@ log=logging.getLogger(__name__) NOTIFICATION_TYPES = ( ('student_needs_to_peer_grade', 'peer_grading', 'Peer Grading'), ('staff_needs_to_grade', 'staff_grading', 'Staff Grading'), - ('overall_need_to_check', 'open_ended_problems', 'Problems you have submitted') + ('new_student_grading_to_view', 'open_ended_problems', 'Problems you have submitted') ) def staff_grading_notifications(course): From 665fb707b1f6c81c645c49d4efced853d7bb25fc Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 23 Jan 2013 10:43:45 -0500 Subject: [PATCH 0298/1392] Cache notifications for 5 mins so that we don't hit the grading server on every web request --- lms/djangoapps/courseware/tabs.py | 2 +- .../open_ended_notifications.py | 72 +++++++++++++++++-- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index a53e4bfb0a..b52324b360 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -110,7 +110,7 @@ def _staff_grading(tab, user, course, active_page): tab_name = "Staff grading" - notifications = open_ended_notifications.staff_grading_notifications(course) + notifications = open_ended_notifications.staff_grading_notifications(course, user) pending_grading = notifications['pending_grading'] img_path = notifications['img_path'] diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index d6621e468a..80f17352e9 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -8,20 +8,31 @@ import open_ended_util from courseware.models import StudentModule import logging from courseware.access import has_access +from util.cache import cache log=logging.getLogger(__name__) +NOTIFICATION_CACHE_TIME = 300 +KEY_PREFIX = "open_ended_" + NOTIFICATION_TYPES = ( ('student_needs_to_peer_grade', 'peer_grading', 'Peer Grading'), ('staff_needs_to_grade', 'staff_grading', 'Staff Grading'), ('new_student_grading_to_view', 'open_ended_problems', 'Problems you have submitted') ) -def staff_grading_notifications(course): +def staff_grading_notifications(course, user): staff_gs = StaffGradingService(settings.STAFF_GRADING_INTERFACE) pending_grading=False img_path= "" course_id = course.id + student_id = unique_id_for_user(user) + notification_type = "staff" + + success, notification_dict = get_value_from_cache(student_id, course_id, notification_type) + if success: + return notification_dict + try: notifications = json.loads(staff_gs.get_notifications(course_id)) if notifications['success']: @@ -35,16 +46,26 @@ def staff_grading_notifications(course): if pending_grading: img_path = "/static/images/slider-handle.png" - return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + notification_dict = {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + + set_value_in_cache(student_id, course_id, notification_type, notification_dict) + + return notification_dict def peer_grading_notifications(course, user): peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE) pending_grading=False img_path= "" course_id = course.id + student_id = unique_id_for_user(user) + notification_type = "peer" + + success, notification_dict = get_value_from_cache(student_id, course_id, notification_type) + if success: + return notification_dict try: - notifications = json.loads(peer_gs.get_notifications(course_id,unique_id_for_user(user))) + notifications = json.loads(peer_gs.get_notifications(course_id,student_id)) if notifications['success']: if notifications['student_needs_to_peer_grade']: pending_grading=True @@ -56,7 +77,11 @@ def peer_grading_notifications(course, user): if pending_grading: img_path = "/static/images/slider-handle.png" - return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + notification_dict = {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + + set_value_in_cache(student_id, course_id, notification_type, notification_dict) + + return notification_dict def combined_notifications(course, user): controller_url = open_ended_util.get_controller_url() @@ -64,6 +89,11 @@ def combined_notifications(course, user): student_id = unique_id_for_user(user) user_is_staff = has_access(user, course, 'staff') course_id = course.id + notification_type = "combined" + + success, notification_dict = get_value_from_cache(student_id, course_id, notification_type) + if success: + return notification_dict min_time_to_query = user.last_login last_module_seen = StudentModule.objects.filter(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified') @@ -92,4 +122,36 @@ def combined_notifications(course, user): if pending_grading: img_path = "/static/images/slider-handle.png" - return {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} \ No newline at end of file + notification_dict = {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + + set_value_in_cache(student_id, course_id, notification_type, notification_dict) + + return notification_dict + +def get_value_from_cache(student_id, course_id, notification_type): + key_name = create_key_name(student_id, course_id, notification_type) + success, value = _get_value_from_cache(key_name) + return success, value + +def set_value_in_cache(student_id, course_id, notification_type, value): + key_name = create_key_name(student_id, course_id, notification_type) + _set_value_in_cache(key_name, value) + +def create_key_name(student_id, course_id, notification_type): + key_name = "{prefix}{type}_{course}_{student}".format(prefix=KEY_PREFIX, type=notification_type, course=course_id, student=student_id) + return key_name + +def _get_value_from_cache(key_name): + value = cache.get(key_name) + success = False + if value is None: + return success , value + try: + value = json.loads(value) + success = True + except: + pass + return success , value + +def _set_value_in_cache(key_name, value): + cache.set(key_name, json.dumps(value), NOTIFICATION_CACHE_TIME) \ No newline at end of file From d07bf0157e41cde06d28722832999c99273c9c28 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 23 Jan 2013 10:55:30 -0500 Subject: [PATCH 0299/1392] UI updates to the Open Ended Problems page --- lms/static/sass/course.scss | 2 ++ .../sass/course/_open_ended_grading.scss | 17 +++++++++++++ .../open_ended_problems.html | 25 ++++++++++++++----- 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 lms/static/sass/course/_open_ended_grading.scss diff --git a/lms/static/sass/course.scss b/lms/static/sass/course.scss index e900e589b2..17406782fe 100644 --- a/lms/static/sass/course.scss +++ b/lms/static/sass/course.scss @@ -44,6 +44,8 @@ @import "course/gradebook"; @import "course/tabs"; @import "course/staff_grading"; +@import "course/open_ended_grading"; + // instructor @import "course/instructor/instructor"; diff --git a/lms/static/sass/course/_open_ended_grading.scss b/lms/static/sass/course/_open_ended_grading.scss new file mode 100644 index 0000000000..86ab5f4aa0 --- /dev/null +++ b/lms/static/sass/course/_open_ended_grading.scss @@ -0,0 +1,17 @@ +.open-ended-problems, +.combined-notifications +{ + padding: 40px; + .problem-list + { + table-layout: auto; + margin-top: 10px; + width:70%; + text-align: center; + td, th + { + padding: 7px; + } + } + +} diff --git a/lms/templates/open_ended_problems/open_ended_problems.html b/lms/templates/open_ended_problems/open_ended_problems.html index da309664eb..f891947079 100644 --- a/lms/templates/open_ended_problems/open_ended_problems.html +++ b/lms/templates/open_ended_problems/open_ended_problems.html @@ -23,14 +23,27 @@ You have not attempted any open ended problems yet. %else: -
      + + + + + + %for problem in problem_list: -
    • - ${problem['problem_name']} (${problem['state']} , ${problem['grader_type']} ) -
    • + + + + + %endfor - +
      Problem NameStatusGrader Type
      + ${problem['problem_name']} + + ${problem['state']} + + ${problem['grader_type']} +
      %endif %endif - \ No newline at end of file + From 252e54fef500a4ee6a546e8a2dea6d37f69a0d40 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 23 Jan 2013 12:31:58 -0500 Subject: [PATCH 0300/1392] Add in is_scored boolean, remove some noisy debug statements --- .../xmodule/combined_open_ended_module.py | 38 ++++++++++++++++++- .../lib/xmodule/xmodule/open_ended_module.py | 2 - 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index df8efc30c6..3bc57dd121 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -38,6 +38,8 @@ MAX_SCORE = 1 #The highest score allowed for the overall xmodule and for each rubric point MAX_SCORE_ALLOWED = 3 +IS_SCORED=False + class CombinedOpenEndedModule(XModule): """ This is a module that encapsulates all open ended grading (self assessment, peer assessment, etc). @@ -138,6 +140,9 @@ class CombinedOpenEndedModule(XModule): #Allow reset is true if student has failed the criteria to move to the next child task self.allow_reset = instance_state.get('ready_to_reset', False) self.max_attempts = int(self.metadata.get('attempts', MAX_ATTEMPTS)) + self.is_scored = (self.metadata.get('is_graded', IS_SCORED)=="True") + + log.debug(self.metadata.get('is_graded', IS_SCORED)) # Used for progress / grading. Currently get credit just for # completion (doesn't matter if you self-assessed correct/incorrect). @@ -281,7 +286,6 @@ class CombinedOpenEndedModule(XModule): self.current_task_parsed_xml, self.current_task_descriptor, self.static_data, instance_state=current_task_state) - log.debug(current_task_state) return True def check_allow_reset(self): @@ -563,6 +567,38 @@ class CombinedOpenEndedModule(XModule): return status_html + def get_score(self): + """ + Score the student received on the problem, or None if there is no + score. + + Returns: + dictionary + {'score': integer, from 0 to get_max_score(), + 'total': get_max_score()} + """ + max_score = None + if (self.state == self.DONE or self.allow_reset) and self.is_scored: + last_response = self.get_last_response(self.current_task_number -1) + max_score = last_response['max_score'] + score = last_response['score'] + return { + 'score' : score, + 'total' : max_score, + } + + def max_score(self): + ''' Maximum score. Two notes: + + * This is generic; in abstract, a problem could be 3/5 points on one + randomization, and 5/7 on another + ''' + max_score = None + if (self.state == self.DONE or self.allow_reset) and self.is_scored: + last_response = self.get_last_response(self.current_task_number -1) + max_score = last_response['max_score'] + return max_score + class CombinedOpenEndedDescriptor(XmlDescriptor, EditingDescriptor): """ diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index 3117d9566a..c17f95a360 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -378,7 +378,6 @@ class OpenEndedModule(openendedchild.OpenEndedChild): Return error message or feedback template """ - log.debug(response_items) rubric_feedback="" feedback = self._convert_longform_feedback_to_html(response_items) if response_items['rubric_scores_complete']==True: @@ -603,7 +602,6 @@ class OpenEndedModule(openendedchild.OpenEndedChild): 'child_type': 'openended', 'correct': correct, } - log.debug(context) html = system.render_template('open_ended.html', context) return html From cee69bb765099db31590572a2d2885aa085571dc Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 23 Jan 2013 12:46:21 -0500 Subject: [PATCH 0301/1392] Fix return of score to progress tab --- .../xmodule/combined_open_ended_module.py | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 3bc57dd121..44c8583067 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -578,14 +578,19 @@ class CombinedOpenEndedModule(XModule): 'total': get_max_score()} """ max_score = None + score = None if (self.state == self.DONE or self.allow_reset) and self.is_scored: - last_response = self.get_last_response(self.current_task_number -1) + last_response = self.get_last_response(self.current_task_number) max_score = last_response['max_score'] score = last_response['score'] - return { + log.debug(last_response) + + score_dict = { 'score' : score, 'total' : max_score, - } + } + + return score_dict def max_score(self): ''' Maximum score. Two notes: @@ -595,10 +600,25 @@ class CombinedOpenEndedModule(XModule): ''' max_score = None if (self.state == self.DONE or self.allow_reset) and self.is_scored: - last_response = self.get_last_response(self.current_task_number -1) + last_response = self.get_last_response(self.current_task_number) max_score = last_response['max_score'] return max_score + def get_progress(self): + ''' Return a progress.Progress object that represents how far the + student has gone in this module. Must be implemented to get correct + progress tracking behavior in nesting modules like sequence and + vertical. + + If this module has no notion of progress, return None. + ''' + progress_object = None + if (self.state == self.DONE or self.allow_reset) and self.is_scored: + score_dict = self.get_score() + progress_object = Progress(score_dict['score'], score_dict['total']) + + return progress_object + class CombinedOpenEndedDescriptor(XmlDescriptor, EditingDescriptor): """ From 4140b74e475f35c1155ac31ef5dc13c7b5d45b25 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 23 Jan 2013 12:49:18 -0500 Subject: [PATCH 0302/1392] Fix progress return --- common/lib/xmodule/xmodule/combined_open_ended_module.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 44c8583067..efb80bd204 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -613,9 +613,7 @@ class CombinedOpenEndedModule(XModule): If this module has no notion of progress, return None. ''' progress_object = None - if (self.state == self.DONE or self.allow_reset) and self.is_scored: - score_dict = self.get_score() - progress_object = Progress(score_dict['score'], score_dict['total']) + progress_object = Progress(self.current_task_number, len(self.task_xml)) return progress_object From 9f19eafcf07cdee659a0ccbcf14953a736660421 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 23 Jan 2013 14:12:06 -0500 Subject: [PATCH 0303/1392] Update main notification dashboard with new styles. --- lms/djangoapps/open_ended_grading/views.py | 10 +++-- .../sass/course/_open_ended_grading.scss | 38 +++++++++++++++++++ .../combined_notifications.html | 24 +++++++----- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 931cbb7337..2269ff0bac 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -193,6 +193,11 @@ def combined_notifications(request, course_id): notification_tuples=open_ended_notifications.NOTIFICATION_TYPES notification_list = [] + description_dict = { + 'Peer Grading': "View all problems that require peer assessment in this particular course.", + 'Staff Grading': "View ungraded submissions submitted by your students for the open ended problems in the course.", + 'Problems you have submitted': "View open ended problems that you have previously submitted for grading." + } for response_num in xrange(0,len(notification_tuples)): tag=notification_tuples[response_num][0] if tag in response: @@ -200,13 +205,12 @@ def combined_notifications(request, course_id): human_name = notification_tuples[response_num][2] url = _reverse_without_slash(url_name, course_id) has_img = response[tag] - img_path = "/static/images/slider-handle.png" notification_item = { 'url' : url, 'name' : human_name, - 'has_img' : has_img, - 'img' : img_path, + 'alert' : has_img, + 'description': description_dict[human_name] } notification_list.append(notification_item) diff --git a/lms/static/sass/course/_open_ended_grading.scss b/lms/static/sass/course/_open_ended_grading.scss index 86ab5f4aa0..b7a28cbe0c 100644 --- a/lms/static/sass/course/_open_ended_grading.scss +++ b/lms/static/sass/course/_open_ended_grading.scss @@ -13,5 +13,43 @@ padding: 7px; } } + .notification-container + { + margin: 30px 0px; + } + + .alert + { + background-color: red; + } + .notification + { + margin: 10px; + width: 30%; + @include inline-block; + vertical-align: top; + .notification-link + { + display:block; + height: 8em; + padding: 10px; + border: 1px solid black; + text-align: center; + } + .notification-title + { + text-transform: uppercase; + } + .notification-link:hover + { + background-color: #eee; + color: black; + } + .notification-description + { + padding-top:5%; + } + @include clearfix; + } } diff --git a/lms/templates/open_ended_problems/combined_notifications.html b/lms/templates/open_ended_problems/combined_notifications.html index 6d8541b567..f8267d9704 100644 --- a/lms/templates/open_ended_problems/combined_notifications.html +++ b/lms/templates/open_ended_problems/combined_notifications.html @@ -23,19 +23,23 @@ No items require attention at the moment. %else: - + %endif %endif - \ No newline at end of file + From 486753a2636568f24b029941e729b20656a130dc Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 23 Jan 2013 15:41:18 -0500 Subject: [PATCH 0304/1392] Display alerts from notifications on the panel. --- lms/djangoapps/open_ended_grading/views.py | 10 +++++-- .../sass/course/_open_ended_grading.scss | 26 +++++++++++++------ .../combined_notifications.html | 3 +++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 2269ff0bac..41a3c6d9ba 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -195,9 +195,14 @@ def combined_notifications(request, course_id): notification_list = [] description_dict = { 'Peer Grading': "View all problems that require peer assessment in this particular course.", - 'Staff Grading': "View ungraded submissions submitted by your students for the open ended problems in the course.", + 'Staff Grading': "View ungraded submissions submitted by students for the open ended problems in the course.", 'Problems you have submitted': "View open ended problems that you have previously submitted for grading." } + alert_dict = { + 'Peer Grading': "New submissions to grade", + 'Staff Grading': "New submissions to grade", + 'Problems you have submitted': "New grades have been returned" + } for response_num in xrange(0,len(notification_tuples)): tag=notification_tuples[response_num][0] if tag in response: @@ -210,7 +215,8 @@ def combined_notifications(request, course_id): 'url' : url, 'name' : human_name, 'alert' : has_img, - 'description': description_dict[human_name] + 'description': description_dict[human_name], + 'alert_message': alert_dict[human_name] } notification_list.append(notification_item) diff --git a/lms/static/sass/course/_open_ended_grading.scss b/lms/static/sass/course/_open_ended_grading.scss index b7a28cbe0c..b526d1adf2 100644 --- a/lms/static/sass/course/_open_ended_grading.scss +++ b/lms/static/sass/course/_open_ended_grading.scss @@ -7,7 +7,6 @@ table-layout: auto; margin-top: 10px; width:70%; - text-align: center; td, th { padding: 7px; @@ -18,10 +17,6 @@ margin: 30px 0px; } - .alert - { - background-color: red; - } .notification { margin: 10px; @@ -31,24 +26,39 @@ .notification-link { display:block; - height: 8em; + height: 9em; padding: 10px; border: 1px solid black; text-align: center; + p + { + font-size: .9em; + text-align: center; + } } - .notification-title + .notification-title { text-transform: uppercase; + background: #1d9dd9; + color: white; + padding: 5px 0px; + font-size: 1.1em; } .notification-link:hover { background-color: #eee; - color: black; } .notification-description { padding-top:5%; } + .alert-message + { + img + { + vertical-align: baseline; + } + } @include clearfix; } diff --git a/lms/templates/open_ended_problems/combined_notifications.html b/lms/templates/open_ended_problems/combined_notifications.html index f8267d9704..a24d150d25 100644 --- a/lms/templates/open_ended_problems/combined_notifications.html +++ b/lms/templates/open_ended_problems/combined_notifications.html @@ -32,6 +32,9 @@ % endif
      ${notification['name']}
      + %if notification['alert']: +

      ${notification['alert_message']}

      + %endif

      ${notification['description']}

      From a2db72e10fba821e81cc7534230ae97a22b3a951 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Wed, 23 Jan 2013 15:48:42 -0500 Subject: [PATCH 0305/1392] Update text. --- lms/templates/open_ended_problems/open_ended_problems.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/templates/open_ended_problems/open_ended_problems.html b/lms/templates/open_ended_problems/open_ended_problems.html index f891947079..07d379fe32 100644 --- a/lms/templates/open_ended_problems/open_ended_problems.html +++ b/lms/templates/open_ended_problems/open_ended_problems.html @@ -27,7 +27,7 @@
  • Problem Name StatusGrader TypeType of Grading
    + + + + + + + %for problem in problem_list: + + + + + + + %endfor +
    Problem NameStudent IDStudent ResponseSubmission ID
    + ${problem['problem_name']} + + ${problem['student_id']} + + ${problem['student_response']} + + ${problem['submission_id']} +
    + %endif + %endif + + From dd72297f73ed9af5e22a8703709a25cd53bb74e6 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 20:39:53 -0500 Subject: [PATCH 0394/1392] Wire up flagged problem list --- lms/djangoapps/open_ended_grading/views.py | 21 ++++--------------- .../open_ended_flagged_problems.html | 2 +- lms/urls.py | 4 ++++ 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index fd43921761..6a4131dc6f 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -208,25 +208,13 @@ def flagged_problem_list(request, course_id): base_course_url = reverse('courses') try: - problem_list_json = controller_qs.get_grading_status_list(course_id, unique_id_for_user(request.user)) + problem_list_json = controller_qs.get_flagged_problem_list(course_id) problem_list_dict = json.loads(problem_list_json) success = problem_list_dict['success'] if 'error' in problem_list_dict: error_text = problem_list_dict['error'] - problem_list = problem_list_dict['problem_list'] - - for i in xrange(0,len(problem_list)): - problem_url_parts = search.path_to_location(modulestore(), course.id, problem_list[i]['location']) - problem_url = base_course_url + "/" - for z in xrange(0,len(problem_url_parts)): - part = problem_url_parts[z] - if part is not None: - if z==1: - problem_url += "courseware/" - problem_url += part + "/" - - problem_list[i].update({'actual_url' : problem_url}) + problem_list = problem_list_dict['flagged_submissions'] except GradingServiceError: error_text = "Error occured while contacting the grading service" @@ -238,7 +226,7 @@ def flagged_problem_list(request, course_id): ajax_url = _reverse_with_slash('open_ended_problems', course_id) - return render_to_response('open_ended_problems/open_ended_problems.html', { + return render_to_response('open_ended_problems/open_ended_flagged_problems.html', { 'course': course, 'course_id': course_id, 'ajax_url': ajax_url, @@ -246,14 +234,13 @@ def flagged_problem_list(request, course_id): 'problem_list': problem_list, 'error_text': error_text, # Checked above - 'staff_access': False, }) + 'staff_access': True, }) @cache_control(no_cache=True, no_store=True, must_revalidate=True) def combined_notifications(request, course_id): course = get_course_with_access(request.user, course_id, 'load') user = request.user notifications = open_ended_notifications.combined_notifications(course, user) - log.debug(notifications) response = notifications['response'] notification_tuples=open_ended_notifications.NOTIFICATION_TYPES diff --git a/lms/templates/open_ended_problems/open_ended_flagged_problems.html b/lms/templates/open_ended_problems/open_ended_flagged_problems.html index 447a34ff45..054c028071 100644 --- a/lms/templates/open_ended_problems/open_ended_flagged_problems.html +++ b/lms/templates/open_ended_problems/open_ended_flagged_problems.html @@ -8,7 +8,7 @@ <%block name="title">${course.number} Flagged Open Ended Problems -<%include file="/courseware/course_navigation.html" args="active_page='flagged_open_ended_problems'" /> +<%include file="/courseware/course_navigation.html" args="active_page='open_ended_flagged_problems'" />
    diff --git a/lms/urls.py b/lms/urls.py index 4b3cc94cab..f122635821 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -285,6 +285,10 @@ if settings.COURSEWARE_ENABLED: # Open Ended problem list url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_problems$', 'open_ended_grading.views.student_problem_list', name='open_ended_problems'), + + # Open Ended flagged problem list + url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems$', + 'open_ended_grading.views.flagged_problem_list', name='open_ended_flagged_problems'), # Cohorts management url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/cohorts$', From b6f77f6f8e8f1ba5d2cab867d50b7baf3e7e9334 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 20:43:57 -0500 Subject: [PATCH 0395/1392] Fix rendering for flagged problems view --- .../open_ended_problems/open_ended_flagged_problems.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lms/templates/open_ended_problems/open_ended_flagged_problems.html b/lms/templates/open_ended_problems/open_ended_flagged_problems.html index 054c028071..bf70906637 100644 --- a/lms/templates/open_ended_problems/open_ended_flagged_problems.html +++ b/lms/templates/open_ended_problems/open_ended_flagged_problems.html @@ -28,6 +28,7 @@ Student ID Student Response Submission ID + Location %for problem in problem_list: @@ -43,6 +44,9 @@ ${problem['submission_id']} + + ${problem['location']} + %endfor From e89196e0dd89bed02de4b153c74e7426088de2c0 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 20:47:00 -0500 Subject: [PATCH 0396/1392] Add in flagged problem list return --- lms/djangoapps/open_ended_grading/views.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 6a4131dc6f..f1a9d41974 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -158,8 +158,9 @@ def student_problem_list(request, course_id): success = problem_list_dict['success'] if 'error' in problem_list_dict: error_text = problem_list_dict['error'] - - problem_list = problem_list_dict['problem_list'] + problem_list = [] + else: + problem_list = problem_list_dict['problem_list'] for i in xrange(0,len(problem_list)): problem_url_parts = search.path_to_location(modulestore(), course.id, problem_list[i]['location']) @@ -213,8 +214,9 @@ def flagged_problem_list(request, course_id): success = problem_list_dict['success'] if 'error' in problem_list_dict: error_text = problem_list_dict['error'] - - problem_list = problem_list_dict['flagged_submissions'] + problem_list=[] + else: + problem_list = problem_list_dict['flagged_submissions'] except GradingServiceError: error_text = "Error occured while contacting the grading service" From f89e36b5b9bd7fc21fa26f636635f39804c0019e Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 20:54:02 -0500 Subject: [PATCH 0397/1392] Flagged list renders properly --- .../open_ended_flagged_problems.html | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lms/templates/open_ended_problems/open_ended_flagged_problems.html b/lms/templates/open_ended_problems/open_ended_flagged_problems.html index bf70906637..eb7b34d8e6 100644 --- a/lms/templates/open_ended_problems/open_ended_flagged_problems.html +++ b/lms/templates/open_ended_problems/open_ended_flagged_problems.html @@ -17,18 +17,17 @@

    Instructions

    Here are a list of open ended problems for this course that have been flagged by students as potentially inappropriate.

    % if success: - % if len(flagged_list) == 0: + % if len(problem_list) == 0:
    No flagged problems exist.
    %else: - + - - - + + %for problem in problem_list: @@ -38,14 +37,11 @@ - %endfor From b248a0957254071c4b0db85cd1aaa0300fe74e8e Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:06:54 -0500 Subject: [PATCH 0398/1392] Work on adding in ban actions --- .../controller_query_service.py | 4 ++- .../peer_grading_service.py | 2 +- lms/djangoapps/open_ended_grading/views.py | 27 +++++++++++++++++++ .../open_ended_flagged_problems.html | 16 +++++++---- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py index 7c75d44287..d40c9b4428 100644 --- a/lms/djangoapps/open_ended_grading/controller_query_service.py +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -68,12 +68,14 @@ class ControllerQueryService(GradingService): response = self.get(self.flagged_problem_list_url, params) return response - def take_action_on_flags(self, course_id, student_id, submission_id): + def take_action_on_flags(self, course_id, student_id, submission_id, action_type): params = { 'course_id' : course_id, 'student_id' : student_id, 'submission_id' : submission_id, + 'action_type' : action_type } response = self.post(self.take_action_on_flags_url, params) return response + diff --git a/lms/djangoapps/open_ended_grading/peer_grading_service.py b/lms/djangoapps/open_ended_grading/peer_grading_service.py index 76f54bb12c..994ba0b2be 100644 --- a/lms/djangoapps/open_ended_grading/peer_grading_service.py +++ b/lms/djangoapps/open_ended_grading/peer_grading_service.py @@ -377,4 +377,4 @@ def save_calibration_essay(request, course_id): return HttpResponse(response, mimetype="application/json") except GradingServiceError: log.exception("Error saving calibration grade, location: {0}, submission_id: {1}, submission_key: {2}, grader_id: {3}".format(location, submission_id, submission_key, grader_id)) - return _err_response('Could not connect to grading service') + return _err_response('Could not connect to grading service') \ No newline at end of file diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index f1a9d41974..717a33ec61 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -287,5 +287,32 @@ def combined_notifications(request, course_id): return render_to_response('open_ended_problems/combined_notifications.html', combined_dict ) + +def take_action_on_flags(request, course_id): + """ + + """ + if request.method != 'POST': + raise Http404 + + + required = ['submission_id', 'action_type', 'student_id'] + for key in required: + if key not in request.POST: + return HttpResponse(json.dumps({'success': False, 'error': 'Missing key {0}'.format(key)}), + mimetype="application/json") + + p = request.POST + submission_id = p['submission_id'] + action_type = p['action_type'] + student_id = p['student_id'] + + try: + controller_qs = ControllerQueryService() + response = controller_qs.save_calibration_essay(course_id, student_id, course_id, action_type) + return HttpResponse(response, mimetype="application/json") + except GradingServiceError: + log.exception("Error saving calibration grade, location: {0}, submission_id: {1}, submission_key: {2}, grader_id: {3}".format(location, submission_id, submission_key, grader_id)) + return _err_response('Could not connect to grading service') diff --git a/lms/templates/open_ended_problems/open_ended_flagged_problems.html b/lms/templates/open_ended_problems/open_ended_flagged_problems.html index eb7b34d8e6..97f1e03c18 100644 --- a/lms/templates/open_ended_problems/open_ended_flagged_problems.html +++ b/lms/templates/open_ended_problems/open_ended_flagged_problems.html @@ -25,9 +25,9 @@
    Problem NameName Student IDStudent ResponseSubmission IDLocationIDResponse
    ${problem['student_id']} - ${problem['student_response']} - ${problem['submission_id']} - ${problem['location']} + ${problem['student_response']}
    - - + + %for problem in problem_list: @@ -35,13 +35,19 @@ ${problem['problem_name']} + + - %endfor From 17fce100bb0a41e43a2c8aed6127c9f3e7cb0ed3 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:10:48 -0500 Subject: [PATCH 0399/1392] Add in ban actions to table --- lms/djangoapps/open_ended_grading/views.py | 2 +- .../open_ended_problems/open_ended_flagged_problems.html | 8 ++++---- lms/urls.py | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 717a33ec61..aaee9f4c98 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -309,7 +309,7 @@ def take_action_on_flags(request, course_id): try: controller_qs = ControllerQueryService() - response = controller_qs.save_calibration_essay(course_id, student_id, course_id, action_type) + response = controller_qs.take_action_on_flags(course_id, student_id, course_id, action_type) return HttpResponse(response, mimetype="application/json") except GradingServiceError: log.exception("Error saving calibration grade, location: {0}, submission_id: {1}, submission_key: {2}, grader_id: {3}".format(location, submission_id, submission_key, grader_id)) diff --git a/lms/templates/open_ended_problems/open_ended_flagged_problems.html b/lms/templates/open_ended_problems/open_ended_flagged_problems.html index 97f1e03c18..2397e1a70e 100644 --- a/lms/templates/open_ended_problems/open_ended_flagged_problems.html +++ b/lms/templates/open_ended_problems/open_ended_flagged_problems.html @@ -26,8 +26,8 @@ - - + + %for problem in problem_list: @@ -38,10 +38,10 @@ ${problem['student_response']} + From a61746609cb35231b8394c2b73dfd45bdc9753af Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 31 Jan 2013 12:18:42 -0500 Subject: [PATCH 0417/1392] Fix keyerror --- common/lib/xmodule/xmodule/tests/test_self_assessment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/tests/test_self_assessment.py b/common/lib/xmodule/xmodule/tests/test_self_assessment.py index 7b13770a9e..a98d9622e1 100644 --- a/common/lib/xmodule/xmodule/tests/test_self_assessment.py +++ b/common/lib/xmodule/xmodule/tests/test_self_assessment.py @@ -44,7 +44,7 @@ class SelfAssessmentTest(unittest.TestCase): 'prompt': prompt, 'max_score': 1, 'display_name': "Name", - 'accept_file_uploads' : False, + 'accept_file_upload' : False, } module = SelfAssessmentModule(test_system, self.location, From e41172d55df9f1a0cb142b6a59625eef59dfa519 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Sun, 20 Jan 2013 11:50:51 -0500 Subject: [PATCH 0418/1392] Add start of test framework for capa --- .../xmodule/xmodule/tests/test_capa_module.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 common/lib/xmodule/xmodule/tests/test_capa_module.py diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py new file mode 100644 index 0000000000..148fd893ff --- /dev/null +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -0,0 +1,60 @@ +import json +from mock import Mock +import unittest + +from xmodule.capa_module import CapaModule +from xmodule.modulestore import Location +from lxml import etree + +from . import test_system + +class CapaFactory(object): + """ + A helper class to create problem modules with various parameters for testing. + """ + + sample_problem_xml = """ + + +

    What is pi, to two decimal placs?

    +
    + + + +
    +""" + + num = 0 + @staticmethod + def next_num(): + CapaFactory.num += 1 + return CapaFactory.num + + @staticmethod + def create(): + definition = {'data': CapaFactory.sample_problem_xml,} + location = Location(["i4x", "edX", "capa_test", "problem", + "SampleProblem{0}".format(CapaFactory.next_num())]) + metadata = {} + descriptor = Mock(weight="1") + instance_state = None + + module = CapaModule(test_system, location, + definition, descriptor, + instance_state, None, metadata=metadata) + + return module + + + +class CapaModuleTest(unittest.TestCase): + + def test_import(self): + module = CapaFactory.create() + self.assertEqual(module.get_score()['score'], 0) + + other_module = CapaFactory.create() + self.assertEqual(module.get_score()['score'], 0) + self.assertNotEqual(module.url_name, other_module.url_name, + "Factory should be creating unique names for each problem") + From 025b074b87b5fc60c712292d541449d0d470152b Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Sun, 20 Jan 2013 12:17:22 -0500 Subject: [PATCH 0419/1392] Add simple test for showanswer, fix test_system --- common/lib/xmodule/xmodule/tests/__init__.py | 2 +- .../xmodule/xmodule/tests/test_capa_module.py | 60 ++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index a07f1ddfaf..1f323834a9 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -26,7 +26,7 @@ test_system = ModuleSystem( # "render" to just the context... render_template=lambda template, context: str(context), replace_urls=Mock(), - user=Mock(), + user=Mock(is_staff=False), filestore=Mock(), debug=True, xqueue={'interface':None, 'callback_url':'/', 'default_queuename': 'testqueue', 'waittime': 10}, diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py index 148fd893ff..7537cb537c 100644 --- a/common/lib/xmodule/xmodule/tests/test_capa_module.py +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -1,7 +1,9 @@ import json from mock import Mock +from pprint import pprint import unittest + from xmodule.capa_module import CapaModule from xmodule.modulestore import Location from lxml import etree @@ -31,13 +33,59 @@ class CapaFactory(object): return CapaFactory.num @staticmethod - def create(): + def create(graceperiod=None, + due=None, + max_attempts=None, + showanswer=None, + rerandomize=None, + force_save_button=None, + attempts=None, + problem_state=None, + ): + """ + All parameters are optional, and are added to the created problem if specified. + + Arguments: + graceperiod: + due: + max_attempts: + showanswer: + force_save_button: + rerandomize: all strings, as specified in the policy for the problem + + problem_state: a dict to to be serialized into the instance_state of the + module. + + attempts: also added to instance state. Should be a number. + """ definition = {'data': CapaFactory.sample_problem_xml,} location = Location(["i4x", "edX", "capa_test", "problem", "SampleProblem{0}".format(CapaFactory.next_num())]) metadata = {} + if graceperiod is not None: + metadata['graceperiod'] = graceperiod + if due is not None: + metadata['due'] = due + if max_attempts is not None: + metadata['attempts'] = max_attempts + if showanswer is not None: + metadata['showanswer'] = showanswer + if force_save_button is not None: + metadata['force_save_button'] = force_save_button + if rerandomize is not None: + metadata['rerandomize'] = rerandomize + + descriptor = Mock(weight="1") - instance_state = None + instance_state_dict = {} + if problem_state is not None: + instance_state_dict = problem_state + if attempts is not None: + instance_state_dict['attempts'] = attempts + if len(instance_state_dict) > 0: + instance_state = json.dumps(instance_state_dict) + else: + instance_state = None module = CapaModule(test_system, location, definition, descriptor, @@ -58,3 +106,11 @@ class CapaModuleTest(unittest.TestCase): self.assertNotEqual(module.url_name, other_module.url_name, "Factory should be creating unique names for each problem") + def test_showanswer(self): + """ + Make sure the show answer logic does the right thing. + """ + # default, no due date, showanswer 'closed' + problem = CapaFactory.create() + pprint(problem.__dict__) + self.assertFalse(problem.answer_available()) From ea091a6eb83b09fbc5bafbe4f0f5011b69c8db7b Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Sun, 20 Jan 2013 12:49:05 -0500 Subject: [PATCH 0420/1392] Add tests for showanswer --- .../xmodule/xmodule/tests/test_capa_module.py | 68 +++++++++++++++++-- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py index 7537cb537c..506c7faf9f 100644 --- a/common/lib/xmodule/xmodule/tests/test_capa_module.py +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -1,9 +1,9 @@ +import datetime import json from mock import Mock from pprint import pprint import unittest - from xmodule.capa_module import CapaModule from xmodule.modulestore import Location from lxml import etree @@ -56,7 +56,7 @@ class CapaFactory(object): problem_state: a dict to to be serialized into the instance_state of the module. - attempts: also added to instance state. Should be a number. + attempts: also added to instance state. Will be converted to an int. """ definition = {'data': CapaFactory.sample_problem_xml,} location = Location(["i4x", "edX", "capa_test", "problem", @@ -81,7 +81,9 @@ class CapaFactory(object): if problem_state is not None: instance_state_dict = problem_state if attempts is not None: - instance_state_dict['attempts'] = attempts + # converting to int here because I keep putting "0" and "1" in the tests + # since everything else is a string. + instance_state_dict['attempts'] = int(attempts) if len(instance_state_dict) > 0: instance_state = json.dumps(instance_state_dict) else: @@ -97,6 +99,17 @@ class CapaFactory(object): class CapaModuleTest(unittest.TestCase): + + def setUp(self): + now = datetime.datetime.now() + day_delta = datetime.timedelta(days=1) + self.yesterday_str = str(now - day_delta) + self.today_str = str(now) + self.tomorrow_str = str(now + day_delta) + + # in the capa grace period format, not in time delta format + self.two_day_delta_str = "2 days" + def test_import(self): module = CapaFactory.create() self.assertEqual(module.get_score()['score'], 0) @@ -106,11 +119,54 @@ class CapaModuleTest(unittest.TestCase): self.assertNotEqual(module.url_name, other_module.url_name, "Factory should be creating unique names for each problem") - def test_showanswer(self): + def test_showanswer_default(self): """ Make sure the show answer logic does the right thing. """ - # default, no due date, showanswer 'closed' + # default, no due date, showanswer 'closed', so problem is open, and show_answer + # not visible. problem = CapaFactory.create() - pprint(problem.__dict__) self.assertFalse(problem.answer_available()) + + + def test_showanswer_attempted(self): + problem = CapaFactory.create(showanswer='attempted') + self.assertFalse(problem.answer_available()) + problem.attempts = 1 + self.assertTrue(problem.answer_available()) + + + def test_showanswer_closed(self): + + # can see after attempts used up + used_all_attempts = CapaFactory.create(showanswer='closed', + max_attempts="1", + attempts="1") + self.assertTrue(used_all_attempts.answer_available()) + + + # can see after due date + after_due_date = CapaFactory.create(showanswer='closed', + max_attempts="1", + attempts="0", + due=self.yesterday_str) + self.assertTrue(after_due_date.answer_available()) + + # can't see because attempts left + attempts_left_open = CapaFactory.create(showanswer='closed', + max_attempts="1", + attempts="0", + due=self.tomorrow_str) + self.assertFalse(attempts_left_open.answer_available()) + + # Can't see because grace period hasn't expired + still_in_grace = CapaFactory.create(showanswer='closed', + max_attempts="1", + attempts="0", + due=self.yesterday_str, + graceperiod=self.two_day_delta_str) + self.assertFalse(still_in_grace.answer_available()) + + + + From 6088a926cc0697094c1bd6ae095581895fcc4563 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Sun, 20 Jan 2013 17:35:03 -0500 Subject: [PATCH 0421/1392] Add showanswer="past_due" and tests --- common/lib/xmodule/xmodule/capa_module.py | 35 ++++++++------ .../xmodule/xmodule/tests/test_capa_module.py | 47 ++++++++++++++++++- 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index f33da6e3a4..6d258e61ed 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -389,38 +389,43 @@ class CapaModule(XModule): }) return json.dumps(d, cls=ComplexEncoder) + def is_past_due(self): + """ + Is it now past this problem's due date, including grace period? + """ + return (self.close_date is not None and + datetime.datetime.utcnow() > self.close_date) + def closed(self): ''' Is the student still allowed to submit answers? ''' if self.attempts == self.max_attempts: return True - if self.close_date is not None and datetime.datetime.utcnow() > self.close_date: + if self.is_past_due(): return True return False def answer_available(self): - ''' Is the user allowed to see an answer? + ''' + Is the user allowed to see an answer? ''' if self.show_answer == '': return False - - if self.show_answer == "never": + elif self.show_answer == "never": return False - - # Admins can see the answer, unless the problem explicitly prevents it - if self.system.user_is_staff: + elif self.system.user_is_staff: + # This i after the 'never' check because admins can see the answer + # unless the problem explicitly prevents it return True - - if self.show_answer == 'attempted': + elif self.show_answer == 'attempted': return self.attempts > 0 - - if self.show_answer == 'answered': + elif self.show_answer == 'answered': return self.lcp.done - - if self.show_answer == 'closed': + elif self.show_answer == 'closed': return self.closed() - - if self.show_answer == 'always': + elif self.show_answer == 'past_due': + return self.is_past_due() + elif self.show_answer == 'always': return True return False diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py index 506c7faf9f..e8f639e3c9 100644 --- a/common/lib/xmodule/xmodule/tests/test_capa_module.py +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -138,10 +138,11 @@ class CapaModuleTest(unittest.TestCase): def test_showanswer_closed(self): - # can see after attempts used up + # can see after attempts used up, even with due date in the future used_all_attempts = CapaFactory.create(showanswer='closed', max_attempts="1", - attempts="1") + attempts="1", + due=self.tomorrow_str) self.assertTrue(used_all_attempts.answer_available()) @@ -152,6 +153,7 @@ class CapaModuleTest(unittest.TestCase): due=self.yesterday_str) self.assertTrue(after_due_date.answer_available()) + # can't see because attempts left attempts_left_open = CapaFactory.create(showanswer='closed', max_attempts="1", @@ -169,4 +171,45 @@ class CapaModuleTest(unittest.TestCase): + def test_showanswer_past_due(self): + """ + With showanswer="past_due" should only show answer after the problem is closed + for everyone--e.g. after due date + grace period. + """ + + # can see after attempts used up, even with due date in the future + used_all_attempts = CapaFactory.create(showanswer='past_due', + max_attempts="1", + attempts="1", + due=self.tomorrow_str) + self.assertFalse(used_all_attempts.answer_available()) + + + # can see after due date + past_due_date = CapaFactory.create(showanswer='past_due', + max_attempts="1", + attempts="0", + due=self.yesterday_str) + self.assertTrue(past_due_date.answer_available()) + + + # can't see because attempts left + attempts_left_open = CapaFactory.create(showanswer='past_due', + max_attempts="1", + attempts="0", + due=self.tomorrow_str) + self.assertFalse(attempts_left_open.answer_available()) + + # Can't see because grace period hasn't expired, even though have no more + # attempts. + still_in_grace = CapaFactory.create(showanswer='past_due', + max_attempts="1", + attempts="1", + due=self.yesterday_str, + graceperiod=self.two_day_delta_str) + self.assertFalse(still_in_grace.answer_available()) + + + + From 279747ab144b145a35058ab5fd899db19fe1a7f8 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Thu, 31 Jan 2013 12:40:05 -0500 Subject: [PATCH 0422/1392] Fixed missing jasmine includes --- cms/static/coffee/files.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cms/static/coffee/files.json b/cms/static/coffee/files.json index ec596063a9..9e84c39f03 100644 --- a/cms/static/coffee/files.json +++ b/cms/static/coffee/files.json @@ -1,9 +1,12 @@ { "js_files": [ + "/static/js/vendor/RequireJS.js", "/static/js/vendor/jquery.min.js", + "js/vendor/jquery-ui.min.js", + "js/vendor/jquery.ui.draggable.js", + "js/vendor/jquery.cookie.js", "/static/js/vendor/json2.js", "/static/js/vendor/underscore-min.js", - "/static/js/vendor/backbone-min.js", - "/static/js/vendor/RequireJS.js" + "/static/js/vendor/backbone-min.js" ] } From f3f509da3b7a63b9d5a14939c02f9a9780104337 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 31 Jan 2013 12:45:48 -0500 Subject: [PATCH 0423/1392] Fix input area styling --- .../xmodule/xmodule/css/combinedopenended/display.scss | 5 +++-- .../xmodule/js/src/combinedopenended/display.coffee | 2 +- lms/static/coffee/src/open_ended/open_ended.coffee | 9 +++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/common/lib/xmodule/xmodule/css/combinedopenended/display.scss b/common/lib/xmodule/xmodule/css/combinedopenended/display.scss index 41896e6173..38fd6ba01c 100644 --- a/common/lib/xmodule/xmodule/css/combinedopenended/display.scss +++ b/common/lib/xmodule/xmodule/css/combinedopenended/display.scss @@ -442,12 +442,13 @@ section.open-ended-child { margin: 10px; } - span.short-form-response { - padding: 9px; + div.short-form-response { background: #F6F6F6; border: 1px solid #ddd; border-top: 0; margin-bottom: 20px; + overflow-y: auto; + height: 200px; @include clearfix; } diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee index 2aabd35771..89954deb23 100644 --- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee @@ -351,5 +351,5 @@ class @CombinedOpenEnded answer_id = @answer_area.attr('id') answer_val = @answer_area.val() new_text = '' - new_text = "#{answer_val}" + new_text = "
    #{answer_val}
    " @answer_area.replaceWith(new_text) diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee index 558d712c46..aff1e5fc67 100644 --- a/lms/static/coffee/src/open_ended/open_ended.coffee +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -44,13 +44,14 @@ class OpenEnded .error => callback({success: false, error: "Error occured while performing this operation"}) after_action_wrapper: (target, action_type) -> + tr_parent = target.parent().parent() + tr_children = tr_parent.children() + action_taken = tr_children[4].firstElementChild + action_taken.innerText = "#{action_type} done for student." return @handle_after_action handle_after_action: (data) -> - tr_parent = target.parent().parent() - tr_children = tr_parent.children() - action_taken = tr_children[4].children()[0] - action_taken.replaceWith('
    #{action_type} done for student.
    ') + blah = "blah" gentle_alert: (msg) => if $('.message-container').length From f257f12124be03a8bdd057cbc1169dc7e5f6bc3a Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Thu, 31 Jan 2013 12:56:18 -0500 Subject: [PATCH 0424/1392] Meant to add the file here --- cms/static/coffee/files.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cms/static/coffee/files.json b/cms/static/coffee/files.json index ec596063a9..9e84c39f03 100644 --- a/cms/static/coffee/files.json +++ b/cms/static/coffee/files.json @@ -1,9 +1,12 @@ { "js_files": [ + "/static/js/vendor/RequireJS.js", "/static/js/vendor/jquery.min.js", + "js/vendor/jquery-ui.min.js", + "js/vendor/jquery.ui.draggable.js", + "js/vendor/jquery.cookie.js", "/static/js/vendor/json2.js", "/static/js/vendor/underscore-min.js", - "/static/js/vendor/backbone-min.js", - "/static/js/vendor/RequireJS.js" + "/static/js/vendor/backbone-min.js" ] } From 309ac7aa5c1f217f0f5b85cbbbeba0938e4e0268 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Thu, 31 Jan 2013 13:27:46 -0500 Subject: [PATCH 0425/1392] Refactor rubric CSS into a single file. --- .../css/combinedopenended/display.scss | 41 --------------- lms/static/sass/course.scss | 1 + lms/static/sass/course/_rubric.scss | 52 +++++++++++++++++++ lms/static/sass/course/_staff_grading.scss | 47 +---------------- 4 files changed, 54 insertions(+), 87 deletions(-) create mode 100644 lms/static/sass/course/_rubric.scss diff --git a/common/lib/xmodule/xmodule/css/combinedopenended/display.scss b/common/lib/xmodule/xmodule/css/combinedopenended/display.scss index a4045c9dad..1917471879 100644 --- a/common/lib/xmodule/xmodule/css/combinedopenended/display.scss +++ b/common/lib/xmodule/xmodule/css/combinedopenended/display.scss @@ -231,47 +231,6 @@ div.result-container { } } -div.result-container, section.open-ended-child { - .rubric { - margin-bottom:25px; - tr { - margin:10px 0px; - height: 100%; - } - td { - padding: 20px 0px 25px 0px; - margin: 10px 0px; - height: 100%; - } - th { - padding: 5px; - margin: 5px; - } - label, - .view-only { - margin:2px; - position: relative; - padding: 10px 15px 25px 15px; - width: 145px; - height:100%; - display: inline-block; - min-height: 50px; - min-width: 50px; - background-color: #CCC; - font-size: .85em; - } - .grade { - position: absolute; - bottom:0px; - right:0px; - margin:10px; - } - .selected-grade { - background: #666; - color: white; - } - } -} section.open-ended-child { @media print { diff --git a/lms/static/sass/course.scss b/lms/static/sass/course.scss index e900e589b2..d5f620be82 100644 --- a/lms/static/sass/course.scss +++ b/lms/static/sass/course.scss @@ -44,6 +44,7 @@ @import "course/gradebook"; @import "course/tabs"; @import "course/staff_grading"; +@import "course/rubric"; // instructor @import "course/instructor/instructor"; diff --git a/lms/static/sass/course/_rubric.scss b/lms/static/sass/course/_rubric.scss new file mode 100644 index 0000000000..c82d929fac --- /dev/null +++ b/lms/static/sass/course/_rubric.scss @@ -0,0 +1,52 @@ +.rubric { + padding: 40px 0px; + tr { + margin:10px 0px; + height: 100%; + } + td { + padding: 20px 0px 25px 0px; + height: 100%; + border: 1px black solid; + } + th { + padding: 5px; + margin: 5px; + text-align: center; + } + .points-header th { + padding: 0px; + } + label, + .view-only { + margin:2px; + position: relative; + padding: 15px 15px 25px 15px; + width: 130px; + height:100%; + min-height: 50px; + min-width: 50px; + font-size: .9em; + background-color: white; + display: block; + } + .grade { + position: absolute; + bottom:0px; + right:0px; + margin:10px; + } + .selected-grade { + background: #666; + color: white; + } + input[type=radio]:checked + label { + background: #666; + color: white; } + input[class='score-selection'] { + position: relative; + margin-left: 10px; + font-size: 16px; + } +} + diff --git a/lms/static/sass/course/_staff_grading.scss b/lms/static/sass/course/_staff_grading.scss index 177bd9e5e2..4d4da484de 100644 --- a/lms/static/sass/course/_staff_grading.scss +++ b/lms/static/sass/course/_staff_grading.scss @@ -12,7 +12,7 @@ div.peer-grading{ label { margin: 10px; padding: 5px; - display: inline-block; + @include inline-block; min-width: 50px; background-color: #CCC; text-size: 1.5em; @@ -176,49 +176,4 @@ div.peer-grading{ } } padding: 40px; - .rubric { - tr { - margin:10px 0px; - height: 100%; - } - td { - padding: 20px 0px 25px 0px; - height: 100%; - } - th { - padding: 5px; - margin: 5px; - } - label, - .view-only { - margin:2px; - position: relative; - padding: 15px 15px 25px 15px; - width: 150px; - height:100%; - display: inline-block; - min-height: 50px; - min-width: 50px; - background-color: #CCC; - font-size: .9em; - } - .grade { - position: absolute; - bottom:0px; - right:0px; - margin:10px; - } - .selected-grade { - background: #666; - color: white; - } - input[type=radio]:checked + label { - background: #666; - color: white; } - input[class='score-selection'] { - display: none; - } - } - } - From 683976d7adf4eebedd84894d79b13572072f8dfb Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Thu, 31 Jan 2013 13:28:19 -0500 Subject: [PATCH 0426/1392] Add scores to the top of the rubric, remove from individual cells --- common/lib/xmodule/xmodule/combined_open_ended_rubric.py | 5 ++++- lms/templates/open_ended_rubric.html | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py index 4380e32d5b..50ec22f033 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py @@ -25,10 +25,13 @@ class CombinedOpenEndedRubric(object): ''' try: rubric_categories = self.extract_categories(rubric_xml) + max_scores = map((lambda cat: cat['options'][-1]['points']), rubric_categories) + max_score = max(max_scores) html = self.system.render_template('open_ended_rubric.html', {'categories' : rubric_categories, 'has_score': self.has_score, - 'view_only': self.view_only}) + 'view_only': self.view_only, + 'max_score': max_score}) except: raise RubricParsingError("[render_rubric] Could not parse the rubric with xml: {0}".format(rubric_xml)) return html diff --git a/lms/templates/open_ended_rubric.html b/lms/templates/open_ended_rubric.html index 8d40c7d2b8..b92ad04bde 100644 --- a/lms/templates/open_ended_rubric.html +++ b/lms/templates/open_ended_rubric.html @@ -8,6 +8,14 @@

    Select the criteria you feel best represents this submission in each category.

    % endif
    NameStudent IDID ResponseUnflagBan
    - ${problem['student_id']} + ${problem['student_response']} + + + + ${problem['submission_id']} - ${problem['student_response']} + + ${problem['student_id']}
    Name ResponseUnflagBan
    - + Unflag - + Ban ${problem['submission_id']} diff --git a/lms/urls.py b/lms/urls.py index f122635821..41e8e9fff1 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -287,6 +287,8 @@ if settings.COURSEWARE_ENABLED: 'open_ended_grading.views.student_problem_list', name='open_ended_problems'), # Open Ended flagged problem list + url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems$', + 'open_ended_grading.views.flagged_problem_list', name='open_ended_flagged_problems'), url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems$', 'open_ended_grading.views.flagged_problem_list', name='open_ended_flagged_problems'), From 4c164795691c126ef3d08d5be0e7cba04cfabd0d Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:22:59 -0500 Subject: [PATCH 0400/1392] Working on frontend JS for posting --- lms/djangoapps/open_ended_grading/views.py | 2 +- .../coffee/src/open_ended/open_ended.coffee | 33 +++++++++++++++++++ .../open_ended_flagged_problems.html | 8 +++-- 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 lms/static/coffee/src/open_ended/open_ended.coffee diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index aaee9f4c98..137cff7803 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -309,7 +309,7 @@ def take_action_on_flags(request, course_id): try: controller_qs = ControllerQueryService() - response = controller_qs.take_action_on_flags(course_id, student_id, course_id, action_type) + response = controller_qs.take_action_on_flags(course_id, student_id, submission_id, action_type) return HttpResponse(response, mimetype="application/json") except GradingServiceError: log.exception("Error saving calibration grade, location: {0}, submission_id: {1}, submission_key: {2}, grader_id: {3}".format(location, submission_id, submission_key, grader_id)) diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee new file mode 100644 index 0000000000..f45efeb8a7 --- /dev/null +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -0,0 +1,33 @@ +# This is a simple class that just hides the error container +# and message container when they are empty +# Can (and should be) expanded upon when our problem list +# becomes more sophisticated +class OpenEnded + constructor: (ajax_url) -> + @ajax_url = ajax_url + @error_container = $('.error-container') + @error_container.toggle(not @error_container.is(':empty')) + + @message_container = $('.message-container') + @message_container.toggle(not @message_container.is(':empty')) + + @problem_list = $('.problem-list') + + @ban_button = $('.ban-button') + @unflag_button = $('.unflag-button') + @ban_button.click @ban + @unflag_button.click @unflag + + unflag: (event) => + event.preventDefault() + + ban: (event) => + event.preventDefault() + + post: (cmd, data, callback) -> + # if this post request fails, the error callback will catch it + $.post(@ajax_url + cmd, data, callback) + .error => callback({success: false, error: "Error occured while performing this operation"}) + +ajax_url = $('.open-ended-problems').data('ajax_url') +$(document).ready(() -> new OpenEnded(ajax_url)) diff --git a/lms/templates/open_ended_problems/open_ended_flagged_problems.html b/lms/templates/open_ended_problems/open_ended_flagged_problems.html index 2397e1a70e..9265ad4663 100644 --- a/lms/templates/open_ended_problems/open_ended_flagged_problems.html +++ b/lms/templates/open_ended_problems/open_ended_flagged_problems.html @@ -10,6 +10,10 @@ <%include file="/courseware/course_navigation.html" args="active_page='open_ended_flagged_problems'" /> +<%block name="js_extra"> + <%static:js group='open_ended'/> + +
    ${error_text}
    @@ -38,10 +42,10 @@ ${problem['student_response']}
    - Unflag + Unflag - Ban + Ban ${problem['submission_id']} From 10c7155d4d061d51eee8572a4a5b6fd5f1da03eb Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:28:42 -0500 Subject: [PATCH 0401/1392] Add open ended to JS pipeline --- lms/envs/common.py | 7 ++++++- lms/static/coffee/src/open_ended/open_ended.coffee | 9 +++++++++ lms/urls.py | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lms/envs/common.py b/lms/envs/common.py index 16472795e0..426c29c7d0 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -438,6 +438,7 @@ main_vendor_js = [ discussion_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/discussion/**/*.coffee')) staff_grading_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/staff_grading/**/*.coffee')) peer_grading_js = sorted(rooted_glob(PROJECT_ROOT / 'static','coffee/src/peer_grading/**/*.coffee')) +open_ended_js = sorted(rooted_glob(PROJECT_ROOT / 'static','coffee/src/open_ended/**/*.coffee')) PIPELINE_CSS = { 'application': { @@ -468,7 +469,7 @@ PIPELINE_JS = { 'source_filenames': sorted( set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.coffee') + rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.coffee')) - - set(courseware_js + discussion_js + staff_grading_js + peer_grading_js) + set(courseware_js + discussion_js + staff_grading_js + peer_grading_js + open_ended_js) ) + [ 'js/form.ext.js', 'js/my_courses_dropdown.js', @@ -501,6 +502,10 @@ PIPELINE_JS = { 'peer_grading' : { 'source_filenames': peer_grading_js, 'output_filename': 'js/peer_grading.js' + }, + 'open_ended' : { + 'source_filenames': open_ended_js, + 'output_filename': 'js/open_ended.js' } } diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee index f45efeb8a7..5c0f455ce7 100644 --- a/lms/static/coffee/src/open_ended/open_ended.coffee +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -20,14 +20,23 @@ class OpenEnded unflag: (event) => event.preventDefault() + @gentle_alert "Unflag" ban: (event) => event.preventDefault() + @gentle_alert "Ban" post: (cmd, data, callback) -> # if this post request fails, the error callback will catch it $.post(@ajax_url + cmd, data, callback) .error => callback({success: false, error: "Error occured while performing this operation"}) + gentle_alert: (msg) => + if $('.message-container').length + $('.message-container').remove() + alert_elem = "
    " + msg + "
    " + $('.error-container').after(alert_elem) + $('.message-container').css(opacity: 0).animate(opacity: 1, 700) + ajax_url = $('.open-ended-problems').data('ajax_url') $(document).ready(() -> new OpenEnded(ajax_url)) diff --git a/lms/urls.py b/lms/urls.py index 41e8e9fff1..260f55dd05 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -289,8 +289,8 @@ if settings.COURSEWARE_ENABLED: # Open Ended flagged problem list url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems$', 'open_ended_grading.views.flagged_problem_list', name='open_ended_flagged_problems'), - url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems$', - 'open_ended_grading.views.flagged_problem_list', name='open_ended_flagged_problems'), + url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems/take_action_on_flag$', + 'open_ended_grading.views.take_action_on_flags', name='open_ended_flagged_problems_take_action'), # Cohorts management url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/cohorts$', From 8e9ec501a777a374491db1c48b5cd5a8c461df24 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:44:21 -0500 Subject: [PATCH 0402/1392] Implement flagging, fix urls --- lms/djangoapps/open_ended_grading/views.py | 3 +-- lms/static/coffee/src/open_ended/open_ended.coffee | 11 ++++++++++- lms/urls.py | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 137cff7803..a0ef8239f3 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -226,7 +226,7 @@ def flagged_problem_list(request, course_id): error_text = "Could not get problem list" success = False - ajax_url = _reverse_with_slash('open_ended_problems', course_id) + ajax_url = _reverse_with_slash('open_ended_flagged_problems', course_id) return render_to_response('open_ended_problems/open_ended_flagged_problems.html', { 'course': course, @@ -308,7 +308,6 @@ def take_action_on_flags(request, course_id): student_id = p['student_id'] try: - controller_qs = ControllerQueryService() response = controller_qs.take_action_on_flags(course_id, student_id, submission_id, action_type) return HttpResponse(response, mimetype="application/json") except GradingServiceError: diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee index 5c0f455ce7..07b84c8af5 100644 --- a/lms/static/coffee/src/open_ended/open_ended.coffee +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -24,13 +24,22 @@ class OpenEnded ban: (event) => event.preventDefault() - @gentle_alert "Ban" + parent_tr = $(event.target).parent().parent() + tr_children = parent_tr.children() + action_type = "ban" + submission_id = tr_children[4].innerText + student_id = tr_children[5].innerText + @gentle_alert student_id + @post('take_action_on_flags', {'submission_id' : submission_id, 'student_id' : student_id, 'action_type' : action_type}, @handle_after_action) post: (cmd, data, callback) -> # if this post request fails, the error callback will catch it $.post(@ajax_url + cmd, data, callback) .error => callback({success: false, error: "Error occured while performing this operation"}) + handle_after_action: (data) -> + @gentle_alert data + gentle_alert: (msg) => if $('.message-container').length $('.message-container').remove() diff --git a/lms/urls.py b/lms/urls.py index 260f55dd05..e4494e0166 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -289,7 +289,7 @@ if settings.COURSEWARE_ENABLED: # Open Ended flagged problem list url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems$', 'open_ended_grading.views.flagged_problem_list', name='open_ended_flagged_problems'), - url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems/take_action_on_flag$', + url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems/take_action_on_flags$', 'open_ended_grading.views.take_action_on_flags', name='open_ended_flagged_problems_take_action'), # Cohorts management From b4c80da22498f36aa6da563e96f0fef5e34dbd2d Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:50:24 -0500 Subject: [PATCH 0403/1392] Trim whitespace --- lms/djangoapps/open_ended_grading/views.py | 6 +++++- lms/static/coffee/src/open_ended/open_ended.coffee | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index a0ef8239f3..984c544d93 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -25,6 +25,8 @@ import open_ended_notifications from xmodule.modulestore.django import modulestore from xmodule.modulestore import search +from django.http import HttpResponse, Http404 + log = logging.getLogger(__name__) template_imports = {'urllib': urllib} @@ -306,7 +308,9 @@ def take_action_on_flags(request, course_id): submission_id = p['submission_id'] action_type = p['action_type'] student_id = p['student_id'] - + student_id = student_id.strip(' \t\n\r') + submission_id = submission_id.strip(' \t\n\r') + action_type = action_type.lower().strip(' \t\n\r') try: response = controller_qs.take_action_on_flags(course_id, student_id, submission_id, action_type) return HttpResponse(response, mimetype="application/json") diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee index 07b84c8af5..e54198e2aa 100644 --- a/lms/static/coffee/src/open_ended/open_ended.coffee +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -29,7 +29,6 @@ class OpenEnded action_type = "ban" submission_id = tr_children[4].innerText student_id = tr_children[5].innerText - @gentle_alert student_id @post('take_action_on_flags', {'submission_id' : submission_id, 'student_id' : student_id, 'action_type' : action_type}, @handle_after_action) post: (cmd, data, callback) -> From 2affd4760bef18906c858451dcaa8b80af688485 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:53:33 -0500 Subject: [PATCH 0404/1392] Add in wiring for unflag action --- lms/static/coffee/src/open_ended/open_ended.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee index e54198e2aa..227cf2fd76 100644 --- a/lms/static/coffee/src/open_ended/open_ended.coffee +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -20,7 +20,12 @@ class OpenEnded unflag: (event) => event.preventDefault() - @gentle_alert "Unflag" + parent_tr = $(event.target).parent().parent() + tr_children = parent_tr.children() + action_type = "unflag" + submission_id = tr_children[4].innerText + student_id = tr_children[5].innerText + @post('take_action_on_flags', {'submission_id' : submission_id, 'student_id' : student_id, 'action_type' : action_type}, @handle_after_action) ban: (event) => event.preventDefault() From b0e46085586524caf67b7c76b8907ee23403388d Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 30 Jan 2013 21:56:52 -0500 Subject: [PATCH 0405/1392] Fix callback alert --- lms/static/coffee/src/open_ended/open_ended.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee index 227cf2fd76..45de3a4fcc 100644 --- a/lms/static/coffee/src/open_ended/open_ended.coffee +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -42,7 +42,7 @@ class OpenEnded .error => callback({success: false, error: "Error occured while performing this operation"}) handle_after_action: (data) -> - @gentle_alert data + @gentle_alert data.data gentle_alert: (msg) => if $('.message-container').length From 32524727ce6b31a343e1afcbbb8d838ae1eeb8f6 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Thu, 31 Jan 2013 09:00:06 -0500 Subject: [PATCH 0406/1392] Create a test framework and make it so that we force a mock backend when we don't have an ajax url --- lms/static/coffee/fixtures/staff_grading.html | 76 +++++++++++++++++++ .../coffee/spec/staff_grading_spec.coffee | 11 +++ .../src/staff_grading/staff_grading.coffee | 8 +- 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 lms/static/coffee/fixtures/staff_grading.html create mode 100644 lms/static/coffee/spec/staff_grading_spec.coffee diff --git a/lms/static/coffee/fixtures/staff_grading.html b/lms/static/coffee/fixtures/staff_grading.html new file mode 100644 index 0000000000..2fe5a39a17 --- /dev/null +++ b/lms/static/coffee/fixtures/staff_grading.html @@ -0,0 +1,76 @@ +
    + +
    +

    Staff grading

    + +
    +
    +
    +
    + + +
    +

    Instructions

    +
    +

    This is the list of problems that current need to be graded in order to train the machine learning models. Each problem needs to be trained separately, and we have indicated the number of student submissions that need to be graded in order for a model to be generated. You can grade more than the minimum required number of submissions--this will improve the accuracy of machine learning, though with diminishing returns. You can see the current accuracy of machine learning while grading.

    +
    + +

    Problem List

    + +
    +
    + + + +
    +

    +
    +

    Problem Information

    +
    +
    +

    Maching Learning Information

    +
    +
    +
    +
    +

    Question

    +
    +
    +
    + +
    + +
    + +
    + +
    +

    Grading

    + +
    +
    +

    Student Submission

    +
    +
    +
    +
    +

    +

    +

    +

    + +
    + + +
    + + +
    + +
    + +
    +
    + diff --git a/lms/static/coffee/spec/staff_grading_spec.coffee b/lms/static/coffee/spec/staff_grading_spec.coffee new file mode 100644 index 0000000000..595a9eb550 --- /dev/null +++ b/lms/static/coffee/spec/staff_grading_spec.coffee @@ -0,0 +1,11 @@ +describe 'StaffGrading', -> + beforeEach -> + spyOn Logger, 'log' + @mockBackend = new StaffGradingBackend('url', true) + + describe 'constructor', -> + beforeEach -> + @staff_grading = new StaffGrading(@mockBackend) + + it 'we are originally in the list view', -> + expect(@staff_grading.list_view).toBe(true) diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index c7a8a01bab..005a8e682e 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -9,9 +9,13 @@ state_graded = "graded" state_no_data = "no_data" state_error = "error" -class StaffGradingBackend +class @StaffGradingBackend constructor: (ajax_url, mock_backend) -> @ajax_url = ajax_url + # prevent this from trying to make requests when we don't have + # a proper url + if !ajax_url + mock_backend = true @mock_backend = mock_backend if @mock_backend @mock_cnt = 0 @@ -142,7 +146,7 @@ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for t .error => callback({success: false, error: "Error occured while performing this operation"}) -class StaffGrading +class @StaffGrading constructor: (backend) -> @backend = backend From 0d20c192b9955a955cc2a235c0d27fc87aa3d3ab Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Thu, 31 Jan 2013 09:57:07 -0500 Subject: [PATCH 0407/1392] add exporting of course info --- common/lib/xmodule/xmodule/modulestore/xml_exporter.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/lib/xmodule/xmodule/modulestore/xml_exporter.py b/common/lib/xmodule/xmodule/modulestore/xml_exporter.py index 5e85cd6fc5..3522b45718 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_exporter.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_exporter.py @@ -23,6 +23,9 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d # export the custom tags export_extra_content(export_fs, modulestore, course_location, 'custom_tag_template', 'custom_tags') + # export the course updates + export_extra_content(export_fs, modulestore, course_location, 'course_info', 'info', '.html') + def export_extra_content(export_fs, modulestore, course_location, category_type, dirname, file_suffix = ''): query_loc = Location('i4x', course_location.org, course_location.course, category_type, None) From ada9ff7f27925b21da41e26873b39b8f04a61ed0 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Thu, 31 Jan 2013 10:45:11 -0500 Subject: [PATCH 0408/1392] Fix randomization bug in capa. (Note: capa_problem was still doing randomization internally, but now it does what's actually intended) --- common/lib/xmodule/xmodule/capa_module.py | 33 ++++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index f33da6e3a4..27bf0c4cb1 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -2,6 +2,7 @@ import cgi import datetime import dateutil import dateutil.parser +import hashlib import json import logging import traceback @@ -25,6 +26,22 @@ log = logging.getLogger("mitx.courseware") #----------------------------------------------------------------------------- TIMEDELTA_REGEX = re.compile(r'^((?P\d+?) day(?:s?))?(\s)?((?P\d+?) hour(?:s?))?(\s)?((?P\d+?) minute(?:s)?)?(\s)?((?P\d+?) second(?:s)?)?$') +# Generated this many different variants of problems with rerandomize=per_student +NUM_RANDOMIZATION_BINS = 20 + +def randomization_bin(seed, problem_id): + """ + Pick a randomization bin for the problem given the user's seed and a problem id. + + We do this because we only want e.g. 20 randomizations of a problem to make analytics + interesting. To avoid having sets of students that always get the same problems, + we'll combine the system's per-student seed with the problem id in picking the bin. + """ + h = hashlib.sha1() + h.update(str(seed)) + h.update(str(problem_id)) + # get the first few digits of the hash, convert to an int, then mod. + return int(h.hexdigest()[:7], 16) % NUM_RANDOMIZATION_BINS def only_one(lst, default="", process=lambda x: x): """ @@ -138,13 +155,9 @@ class CapaModule(XModule): if self.rerandomize == 'never': self.seed = 1 - elif self.rerandomize == "per_student" and hasattr(self.system, 'id'): - # TODO: This line is badly broken: - # (1) We're passing student ID to xmodule. - # (2) There aren't bins of students. -- we only want 10 or 20 randomizations, and want to assign students - # to these bins, and may not want cohorts. So e.g. hash(your-id, problem_id) % num_bins. - # - analytics really needs small number of bins. - self.seed = system.id + elif self.rerandomize == "per_student" and hasattr(self.system, 'seed'): + # see comment on randomization_bin + self.seed = randomization_bin(system.seed, self.location.url) else: self.seed = None @@ -669,18 +682,18 @@ class CapaDescriptor(RawDescriptor): # TODO (vshnayder): do problems have any other metadata? Do they # actually use type and points? metadata_attributes = RawDescriptor.metadata_attributes + ('type', 'points') - + def get_context(self): _context = RawDescriptor.get_context(self) _context.update({'markdown': self.metadata.get('markdown', '')}) return _context - + @property def editable_metadata_fields(self): """Remove metadata from the editable fields since it has its own editor""" subset = super(CapaDescriptor,self).editable_metadata_fields if 'markdown' in subset: - subset.remove('markdown') + subset.remove('markdown') return subset From fc57e7afdb8bfd54e934bbebb4cfd13a35adc673 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Thu, 31 Jan 2013 10:51:20 -0500 Subject: [PATCH 0409/1392] add testing for course info export. Plus DRY things out a bit --- cms/djangoapps/contentstore/tests/tests.py | 34 +++++++++++----------- common/test/data/full/tabs/resources.html | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 8c520eb39c..b503a1819d 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -418,6 +418,17 @@ class ContentStoreTest(TestCase): items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) self.assertEqual(len(items), 0) + def verify_content_existence(self, modulestore, root_dir, location, dirname, category_name, filename_suffix=''): + fs = OSFS(root_dir / 'test_export') + self.assertTrue(fs.exists(dirname)) + + query_loc = Location('i4x', location.org, location.course, category_name, None) + items = modulestore.get_items(query_loc) + + for item in items: + fs = OSFS(root_dir / ('test_export/' + dirname)) + self.assertTrue(fs.exists(item.location.name + filename_suffix)) + def test_export_course(self): ms = modulestore('direct') cs = contentstore() @@ -433,26 +444,14 @@ class ContentStoreTest(TestCase): export_to_xml(ms, cs, location, root_dir, 'test_export') # check for static tabs - fs = OSFS(root_dir / 'test_export') - self.assertTrue(fs.exists('tabs')) - - static_tabs_query_loc = Location('i4x', location.org, location.course, 'static_tab', None) - static_tabs = ms.get_items(static_tabs_query_loc) - - for static_tab in static_tabs: - fs = OSFS(root_dir / 'test_export/tabs') - self.assertTrue(fs.exists(static_tab.location.name + '.html')) + self.verify_content_existence(ms, root_dir, location, 'tabs', 'static_tab', '.html') # check for custom_tags - fs = OSFS(root_dir / 'test_export') - self.assertTrue(fs.exists('custom_tags')) + self.verify_content_existence(ms, root_dir, location, 'info', 'course_info', '.html') - custom_tags_query_loc = Location('i4x', location.org, location.course, 'custom_tag_template', None) - custom_tags = ms.get_items(custom_tags_query_loc) - - for custom_tag in custom_tags: - fs = OSFS(root_dir / 'test_export/custom_tags') - self.assertTrue(fs.exists(custom_tag.location.name)) + # check for custom_tags + self.verify_content_existence(ms, root_dir, location, 'custom_tags', 'custom_tag_template') + # remove old course delete_course(ms, cs, location) @@ -469,6 +468,7 @@ class ContentStoreTest(TestCase): shutil.rmtree(root_dir) + def test_course_handouts_rewrites(self): ms = modulestore('direct') cs = contentstore() diff --git a/common/test/data/full/tabs/resources.html b/common/test/data/full/tabs/resources.html index 62e77a8416..bf78c92fb1 100644 --- a/common/test/data/full/tabs/resources.html +++ b/common/test/data/full/tabs/resources.html @@ -1 +1 @@ -This is another sample tab \ No newline at end of file +

    This is another sample tab

    \ No newline at end of file From ee06afcb27361034b10dfeb7210801a3177738b0 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 31 Jan 2013 11:06:12 -0500 Subject: [PATCH 0410/1392] Possibly fix self assessment tests --- common/lib/xmodule/xmodule/tests/test_self_assessment.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/tests/test_self_assessment.py b/common/lib/xmodule/xmodule/tests/test_self_assessment.py index 9013794dbb..7b13770a9e 100644 --- a/common/lib/xmodule/xmodule/tests/test_self_assessment.py +++ b/common/lib/xmodule/xmodule/tests/test_self_assessment.py @@ -43,7 +43,8 @@ class SelfAssessmentTest(unittest.TestCase): 'rubric': etree.XML(rubric), 'prompt': prompt, 'max_score': 1, - 'display_name': "Name" + 'display_name': "Name", + 'accept_file_uploads' : False, } module = SelfAssessmentModule(test_system, self.location, From 78f9f63466e6ffce90df07385c80378168af74c7 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 31 Jan 2013 11:19:15 -0500 Subject: [PATCH 0411/1392] Add in notification type for flagged submissions --- .../open_ended_grading/open_ended_notifications.py | 3 ++- lms/djangoapps/open_ended_grading/views.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 43259f3e1b..fec893894f 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -19,7 +19,8 @@ KEY_PREFIX = "open_ended_" NOTIFICATION_TYPES = ( ('student_needs_to_peer_grade', 'peer_grading', 'Peer Grading'), ('staff_needs_to_grade', 'staff_grading', 'Staff Grading'), - ('new_student_grading_to_view', 'open_ended_problems', 'Problems you have submitted') + ('new_student_grading_to_view', 'open_ended_problems', 'Problems you have submitted'), + ('flagged_submissions_exist', 'open_ended_flagged_problems', 'Flagged Submissions') ) def staff_grading_notifications(course, user): diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 984c544d93..1777f26e2e 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -56,12 +56,14 @@ def _reverse_without_slash(url_name, course_id): DESCRIPTION_DICT = { 'Peer Grading': "View all problems that require peer assessment in this particular course.", 'Staff Grading': "View ungraded submissions submitted by students for the open ended problems in the course.", - 'Problems you have submitted': "View open ended problems that you have previously submitted for grading." + 'Problems you have submitted': "View open ended problems that you have previously submitted for grading.", + 'Flagged Submissions' : "View submissions that have been flagged by students as inappropriate." } ALERT_DICT = { 'Peer Grading': "New submissions to grade", 'Staff Grading': "New submissions to grade", - 'Problems you have submitted': "New grades have been returned" + 'Problems you have submitted': "New grades have been returned", + 'Flagged Submissions' : "Submissions have been flagged for review" } @cache_control(no_cache=True, no_store=True, must_revalidate=True) def staff_grading(request, course_id): From 7d871ddfc9f3440452dab0e7c3a81498e4a2198c Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Thu, 31 Jan 2013 11:50:07 -0500 Subject: [PATCH 0412/1392] studio - revised manual policy UI: added key tips on focus, moved error messages to bottom of pairings --- cms/static/sass/_settings.scss | 13 +++++++++++++ cms/templates/settings.html | 32 ++++++++++---------------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/cms/static/sass/_settings.scss b/cms/static/sass/_settings.scss index 5f14b83a9b..51c9489254 100644 --- a/cms/static/sass/_settings.scss +++ b/cms/static/sass/_settings.scss @@ -582,6 +582,18 @@ input { width: 100%; } + + .tip { + @include transition (opacity 0.5s ease-in-out 0s); + opacity: 0; + } + + input:focus { + + & + .tip { + opacity: 1.0; + } + } } } @@ -599,6 +611,7 @@ } .message-error { + float: left; margin: 0 0 10px 0; } } diff --git a/cms/templates/settings.html b/cms/templates/settings.html index 7153b6daa3..6dd4d3eed6 100644 --- a/cms/templates/settings.html +++ b/cms/templates/settings.html @@ -746,6 +746,7 @@ from contentstore import utils
    + Keys are case sensitive and cannot contain spaces or start with a number
    @@ -760,12 +761,12 @@ from contentstore import utils
  • - This policy key, $KEYNAME, already exists.
    + Keys are case sensitive and cannot contain spaces or start with a number
    @@ -775,17 +776,19 @@ from contentstore import utils
  • + This policy key, $KEYNAME, already exists. + Delete
  • - You cannot leave the key value for this pair blank.
    + Keys are case sensitive and cannot contain spaces or start with a number
    @@ -795,18 +798,20 @@ from contentstore import utils
    + You cannot leave the key value for this pair blank. + Delete
  • - The JSON value for $KEYNAME is invalid.
    -
    + Keys are case sensitive and cannot contain spaces or start with a number +
    @@ -815,25 +820,8 @@ from contentstore import utils
    - Delete -
  • + The JSON value for $KEYNAME is invalid. - -
  • -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    Delete
  • From 649136364784708993b6b6dde00f7813aedf188d Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Thu, 31 Jan 2013 12:11:11 -0500 Subject: [PATCH 0413/1392] Remove format field as it's the one for grading type. --- cms/templates/edit_subsection.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cms/templates/edit_subsection.html b/cms/templates/edit_subsection.html index c3aed8a94f..de5e14e0a9 100644 --- a/cms/templates/edit_subsection.html +++ b/cms/templates/edit_subsection.html @@ -23,10 +23,6 @@ -
    - - -
    ${units.enum_units(subsection, subsection_units=subsection_units)} From e431378f46a812afc5a562cedd87babe7beb5bec Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Thu, 31 Jan 2013 12:14:01 -0500 Subject: [PATCH 0414/1392] Add first pass at a randomize module --- common/lib/xmodule/setup.py | 1 + .../lib/xmodule/xmodule/randomize_module.py | 122 ++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 common/lib/xmodule/xmodule/randomize_module.py diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py index 29227c3188..446078ffcf 100644 --- a/common/lib/xmodule/setup.py +++ b/common/lib/xmodule/setup.py @@ -28,6 +28,7 @@ setup( "error = xmodule.error_module:ErrorDescriptor", "problem = xmodule.capa_module:CapaDescriptor", "problemset = xmodule.seq_module:SequenceDescriptor", + "randomize = xmodule.randomize_module:RandomizeDescriptor", "section = xmodule.backcompat_module:SemanticSectionDescriptor", "sequential = xmodule.seq_module:SequenceDescriptor", "slides = xmodule.backcompat_module:TranslateCustomTagDescriptor", diff --git a/common/lib/xmodule/xmodule/randomize_module.py b/common/lib/xmodule/xmodule/randomize_module.py new file mode 100644 index 0000000000..0bc26c21bf --- /dev/null +++ b/common/lib/xmodule/xmodule/randomize_module.py @@ -0,0 +1,122 @@ +import json +import logging +import random + +from xmodule.mako_module import MakoModuleDescriptor +from xmodule.x_module import XModule +from xmodule.xml_module import XmlDescriptor +from xmodule.modulestore import Location +from xmodule.seq_module import SequenceDescriptor + +from pkg_resources import resource_string + +log = logging.getLogger('mitx.' + __name__) + +class RandomizeModule(XModule): + """ + Chooses a random child module. Chooses the same one every time for each student. + + Example: + + + + + + + User notes: + + - If you're randomizing amongst graded modules, each of them MUST be worth the same + number of points. Otherwise, the earth will be overrun by monsters from the + deeps. You have been warned. + + Technical notes: + - There is more dark magic in this code than I'd like. The whole varying-children + + grading interaction is a tangle between super and subclasses of descriptors and + modules. +""" + + def __init__(self, system, location, definition, descriptor, + instance_state=None, shared_state=None, **kwargs): + XModule.__init__(self, system, location, definition, descriptor, + instance_state, shared_state, **kwargs) + + # NOTE: calling self.get_children() creates a circular reference-- + # it calls get_child_descriptors() internally, but that doesn't work until + # we've picked a choice + num_choices = len(self.descriptor.get_children()) + + self.choice = None + if instance_state is not None: + state = json.loads(instance_state) + self.choice = state.get('choice', None) + if self.choice > num_choices: + # Oops. Children changed. Reset. + self.choice = None + + if self.choice is None: + # choose one based on the system seed, or randomly if that's not available + if num_choices > 0: + if system.seed is not None: + self.choice = system.seed % num_choices + else: + self.choice = random.randrange(0, num_choices) + + log.debug("********* self.choice = %s", self.choice) + if self.choice is not None: + self.child_descriptor = self.descriptor.get_children()[self.choice] + # Now get_children() should return a list with one element + log.debug("children of randomize module (should be only 1): %s", + self.get_children()) + self.child = self.get_children()[0] + else: + self.child_descriptor = None + self.child = None + + + def get_instance_state(self): + return json.dumps({'choice': self.choice}) + + + def get_child_descriptors(self): + """ + For grading--return just the chosen child. + """ + if self.child_descriptor is None: + return [] + + return [self.child_descriptor] + + + def get_html(self): + if self.child is None: + # raise error instead? In fact, could complain on descriptor load... + return "
    Nothing to randomize between
    " + + return self.child.get_html() + + def get_icon_class(self): + return self.child.get_icon_class() if self.child else 'other' + + +class RandomizeDescriptor(SequenceDescriptor): + # the editing interface can be the same as for sequences -- just a container + module_class = RandomizeModule + + filename_extension = "xml" + + stores_state = True + + def definition_to_xml(self, resource_fs): + xml_object = etree.Element('randomize') + for child in self.get_children(): + xml_object.append( + etree.fromstring(child.export_to_xml(resource_fs))) + return xml_object + + def has_dynamic_children(self): + """ + Grading needs to know that only one of the children is actually "real". This + makes it use module.get_child_descriptors(). + """ + return True + From e0fb906c0692da41253ac1fe9411c6703f981f44 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Thu, 31 Jan 2013 12:14:20 -0500 Subject: [PATCH 0415/1392] add note about potential bug in verticals. No time to investigate at the moment... --- common/lib/xmodule/xmodule/vertical_module.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/lib/xmodule/xmodule/vertical_module.py b/common/lib/xmodule/xmodule/vertical_module.py index 397bd3e136..14105b41d0 100644 --- a/common/lib/xmodule/xmodule/vertical_module.py +++ b/common/lib/xmodule/xmodule/vertical_module.py @@ -48,3 +48,5 @@ class VerticalDescriptor(SequenceDescriptor): js = {'coffee': [resource_string(__name__, 'js/src/vertical/edit.coffee')]} js_module_name = "VerticalDescriptor" + # TODO (victor): Does this need its own definition_to_xml method? Otherwise it looks + # like verticals will get exported as sequentials... From 63d4ac8c442615c45435b2186dfbaa590891037f Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 31 Jan 2013 12:17:21 -0500 Subject: [PATCH 0416/1392] Working on some flagging coffeescript --- .../coffee/src/open_ended/open_ended.coffee | 22 +++++++++++++------ .../open_ended_flagged_problems.html | 3 +++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lms/static/coffee/src/open_ended/open_ended.coffee b/lms/static/coffee/src/open_ended/open_ended.coffee index 45de3a4fcc..558d712c46 100644 --- a/lms/static/coffee/src/open_ended/open_ended.coffee +++ b/lms/static/coffee/src/open_ended/open_ended.coffee @@ -23,26 +23,34 @@ class OpenEnded parent_tr = $(event.target).parent().parent() tr_children = parent_tr.children() action_type = "unflag" - submission_id = tr_children[4].innerText - student_id = tr_children[5].innerText - @post('take_action_on_flags', {'submission_id' : submission_id, 'student_id' : student_id, 'action_type' : action_type}, @handle_after_action) + submission_id = tr_children[5].innerText + student_id = tr_children[6].innerText + callback_func = @after_action_wrapper($(event.target), action_type) + @post('take_action_on_flags', {'submission_id' : submission_id, 'student_id' : student_id, 'action_type' : action_type}, callback_func) ban: (event) => event.preventDefault() parent_tr = $(event.target).parent().parent() tr_children = parent_tr.children() action_type = "ban" - submission_id = tr_children[4].innerText - student_id = tr_children[5].innerText - @post('take_action_on_flags', {'submission_id' : submission_id, 'student_id' : student_id, 'action_type' : action_type}, @handle_after_action) + submission_id = tr_children[5].innerText + student_id = tr_children[6].innerText + callback_func = @after_action_wrapper($(event.target), action_type) + @post('take_action_on_flags', {'submission_id' : submission_id, 'student_id' : student_id, 'action_type' : action_type}, callback_func) post: (cmd, data, callback) -> # if this post request fails, the error callback will catch it $.post(@ajax_url + cmd, data, callback) .error => callback({success: false, error: "Error occured while performing this operation"}) + after_action_wrapper: (target, action_type) -> + return @handle_after_action + handle_after_action: (data) -> - @gentle_alert data.data + tr_parent = target.parent().parent() + tr_children = tr_parent.children() + action_taken = tr_children[4].children()[0] + action_taken.replaceWith('
    #{action_type} done for student.
    ') gentle_alert: (msg) => if $('.message-container').length diff --git a/lms/templates/open_ended_problems/open_ended_flagged_problems.html b/lms/templates/open_ended_problems/open_ended_flagged_problems.html index 9265ad4663..ec892da43c 100644 --- a/lms/templates/open_ended_problems/open_ended_flagged_problems.html +++ b/lms/templates/open_ended_problems/open_ended_flagged_problems.html @@ -47,6 +47,9 @@
    Ban +
    +
    ${problem['submission_id']}
    + + + % for i in range(max_score + 1): + + % endfor + % for i in range(len(categories)): <% category = categories[i] %> @@ -23,7 +31,6 @@
    % endif ${option['text']} -
    [${option['points']} points]
    % else: From b613bdc3366bdef89511355142e2829c515a51de Mon Sep 17 00:00:00 2001 From: cahrens Date: Thu, 31 Jan 2013 13:37:45 -0500 Subject: [PATCH 0427/1392] Fixes date bug (#149). --- .../js/views/settings/main_settings_view.js | 96 ++++++++++--------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/cms/static/js/views/settings/main_settings_view.js b/cms/static/js/views/settings/main_settings_view.js index e2b5326aaf..826b385dff 100644 --- a/cms/static/js/views/settings/main_settings_view.js +++ b/cms/static/js/views/settings/main_settings_view.js @@ -211,15 +211,15 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({ 'intro_video' : 'course-introduction-video', 'effort' : "course-effort" }, - - setupDatePicker : function(fieldName) { - var cacheModel = this.model; - var div = this.$el.find('#' + this.fieldToSelectorMap[fieldName]); - var datefield = $(div).find(".date"); - var timefield = $(div).find(".time"); - var cachethis = this; - var savefield = function() { - cachethis.clearValidationErrors(); + + setupDatePicker: function (fieldName) { + var cacheModel = this.model; + var div = this.$el.find('#' + this.fieldToSelectorMap[fieldName]); + var datefield = $(div).find(".date"); + var timefield = $(div).find(".time"); + var cachethis = this; + var savefield = function () { + cachethis.clearValidationErrors(); var date = datefield.datepicker('getDate'); if (date) { var time = timefield.timepicker("getSecondsFromMidnight"); @@ -227,21 +227,24 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({ time = 0; } var newVal = new Date(date.getTime() + time * 1000); - if (cacheModel.get(fieldName) != newVal) cacheModel.save(fieldName, newVal, - { error : CMS.ServerError}); + if (cacheModel.get(fieldName).getTime() !== newVal.getTime()) { + cacheModel.save(fieldName, newVal, { error: CMS.ServerError}); + } } - }; - - // instrument as date and time pickers - timefield.timepicker(); - - // FIXME being called 2x on each change. Was trapping datepicker onSelect b4 but change to datepair broke that - datefield.datepicker({ onSelect : savefield }); - timefield.on('changeTime', savefield); - - datefield.datepicker('setDate', this.model.get(fieldName)); - if (this.model.has(fieldName)) timefield.timepicker('setTime', this.model.get(fieldName)); - }, + }; + + // instrument as date and time pickers + timefield.timepicker(); + datefield.datepicker(); + + // Using the change event causes savefield to be triggered twice, but it is necessary + // to pick up when the date is typed directly in the field. + datefield.change(savefield); + timefield.on('changeTime', savefield); + + datefield.datepicker('setDate', this.model.get(fieldName)); + if (this.model.has(fieldName)) timefield.timepicker('setTime', this.model.get(fieldName)); + }, updateModel: function(event) { switch (event.currentTarget.id) { @@ -294,29 +297,30 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({ } }, codeMirrors : {}, - codeMirrorize : function(e, forcedTarget) { - if (forcedTarget) { - thisTarget = forcedTarget; - thisTarget.id = $(thisTarget).attr('id'); - } else { - thisTarget = e.currentTarget; - } + codeMirrorize: function (e, forcedTarget) { + var thisTarget; + if (forcedTarget) { + thisTarget = forcedTarget; + thisTarget.id = $(thisTarget).attr('id'); + } else { + thisTarget = e.currentTarget; + } - if (!this.codeMirrors[thisTarget.id]) { - var cachethis = this; - var field = this.selectorToField[thisTarget.id]; - this.codeMirrors[thisTarget.id] = CodeMirror.fromTextArea(thisTarget, { - mode: "text/html", lineNumbers: true, lineWrapping: true, - onBlur : function(mirror) { - mirror.save(); - cachethis.clearValidationErrors(); - var newVal = mirror.getValue(); - if (cachethis.model.get(field) != newVal) cachethis.model.save(field, newVal, - { error : CMS.ServerError}); - } - }); - } - } + if (!this.codeMirrors[thisTarget.id]) { + var cachethis = this; + var field = this.selectorToField[thisTarget.id]; + this.codeMirrors[thisTarget.id] = CodeMirror.fromTextArea(thisTarget, { + mode: "text/html", lineNumbers: true, lineWrapping: true, + onBlur: function (mirror) { + mirror.save(); + cachethis.clearValidationErrors(); + var newVal = mirror.getValue(); + if (cachethis.model.get(field) != newVal) cachethis.model.save(field, newVal, + { error: CMS.ServerError}); + } + }); + } + } }); @@ -668,7 +672,7 @@ CMS.Views.Settings.GraderView = CMS.Views.ValidatingView.extend({ $(event.currentTarget).parent().append( this.errorTemplate({message : 'For grading to work, you must change all "' + oldName + '" subsections to "' + this.model.get('type') + '".'})); - }; + } break; default: this.saveIfChanged(event); From c590c24e25729caefc8f4135d923fed4d1bcee0b Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Thu, 31 Jan 2013 13:48:38 -0500 Subject: [PATCH 0428/1392] Add vendor files to files.json for the cms jasmine tests to work. --- cms/static/coffee/files.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cms/static/coffee/files.json b/cms/static/coffee/files.json index 9e84c39f03..2249813b04 100644 --- a/cms/static/coffee/files.json +++ b/cms/static/coffee/files.json @@ -2,9 +2,9 @@ "js_files": [ "/static/js/vendor/RequireJS.js", "/static/js/vendor/jquery.min.js", - "js/vendor/jquery-ui.min.js", - "js/vendor/jquery.ui.draggable.js", - "js/vendor/jquery.cookie.js", + "/static/js/vendor/jquery-ui.min.js", + "/static/js/vendor/jquery.ui.draggable.js", + "/static/js/vendor/jquery.cookie.js", "/static/js/vendor/json2.js", "/static/js/vendor/underscore-min.js", "/static/js/vendor/backbone-min.js" From 2e0f90081eb12c822b603861cbf86e8e34601866 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Thu, 31 Jan 2013 14:23:17 -0500 Subject: [PATCH 0429/1392] Make rubric cleaner and visually simpler --- lms/static/sass/course/_rubric.scss | 17 ++++++++--------- lms/templates/open_ended_rubric.html | 6 +++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lms/static/sass/course/_rubric.scss b/lms/static/sass/course/_rubric.scss index c82d929fac..9aa0ca2f2a 100644 --- a/lms/static/sass/course/_rubric.scss +++ b/lms/static/sass/course/_rubric.scss @@ -1,5 +1,5 @@ .rubric { - padding: 40px 0px; + margin: 40px 0px; tr { margin:10px 0px; height: 100%; @@ -8,6 +8,7 @@ padding: 20px 0px 25px 0px; height: 100%; border: 1px black solid; + text-align: center; } th { padding: 5px; @@ -17,13 +18,11 @@ .points-header th { padding: 0px; } - label, - .view-only { - margin:2px; + .rubric-label + { position: relative; - padding: 15px 15px 25px 15px; + padding: 15px 15px 25px; width: 130px; - height:100%; min-height: 50px; min-width: 50px; font-size: .9em; @@ -40,9 +39,9 @@ background: #666; color: white; } - input[type=radio]:checked + label { - background: #666; - color: white; } + input[type=radio]:checked + .rubric-label { + background: white; + color: $base-font-color; } input[class='score-selection'] { position: relative; margin-left: 10px; diff --git a/lms/templates/open_ended_rubric.html b/lms/templates/open_ended_rubric.html index b92ad04bde..a2d8d6945c 100644 --- a/lms/templates/open_ended_rubric.html +++ b/lms/templates/open_ended_rubric.html @@ -26,15 +26,15 @@ % if view_only: ## if this is the selected rubric block, show it highlighted % if option['selected']: -
    +
    % else: -
    +
    % endif ${option['text']}
    % else: - + % endif % endfor From abc3e5b09d705d728522b6ffb79da85a5489fe1a Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Thu, 31 Jan 2013 14:47:59 -0500 Subject: [PATCH 0430/1392] more tests in test_views.py --- .../contentstore/tests/test_views.py | 119 ++++++++++++++++-- 1 file changed, 111 insertions(+), 8 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index 2cb00eac36..9fa16ad4b2 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -23,6 +23,7 @@ from contentstore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore import Location from xmodule.x_module import ModuleSystem from xmodule.error_module import ErrorModule +from contentstore.utils import get_course_for_item class Stub(): pass @@ -49,6 +50,7 @@ TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) class ViewsTestCase(TestCase): def setUp(self): + #modulestore().collection.drop() self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] self.location_3 = ['i4x', 'MITx', '999', 'course', 'Robot_Super_Course'] @@ -56,8 +58,6 @@ class ViewsTestCase(TestCase): self._MODULESTORES = {} self.course_id = 'edX/toy/2012_Fall' self.course_id_2 = 'edx/full/6.002_Spring_2012' - #self.toy_course = modulestore().get_course(self.course_id) - # Problem: Classes persist, need to delete stuff from modulestore # is a CourseDescriptor object? self.course = CourseFactory.create() # is a sequence descriptor @@ -66,7 +66,7 @@ class ViewsTestCase(TestCase): def tearDown(self): _MODULESTORES = {} modulestore().collection.drop() - assert False + #assert False def test_has_access(self): user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) @@ -196,18 +196,121 @@ class ViewsTestCase(TestCase): print self.course.xmodule_constructor(system) print self.course.xmodule_constructor(system).func print self.course.xmodule_constructor(system).keywords + print dir(self.course.xmodule_constructor(system).func) def test__xmodule_recurse(self): - raise SkipTest -## mock_item = MagicMock() -## mock_item.get_children.return_value = [] + #There shouldn't be a difference, but the code works with defined + # function f but not with lambda functions + mock_item = MagicMock() + mock_item.get_children.return_value = [] s = Stub() s.children.append(Stub()) - views._xmodule_recurse(s, lambda x: return) - #views._xmodule_recurse(s, lambda x: x.n += 1) + views._xmodule_recurse(s, f) self.assertEquals(s.n, 1) self.assertEquals(s.children[0].n, 1) + + def test_get_module_previews(self): + # needs a working render_to_string + raise SkipTest + self.request = RequestFactory().get('foo') + self.request.user = UserFactory() + self.request.session = {} + print views.get_module_previews(self.request, self.course) + + def test_delete_item(self): + # If user doesn't have permission, redirect + self.no_permit_user = MagicMock(is_staff = False, is_active = False) + self.no_permit_user.is_authenticated.return_value = True + self.request = RequestFactory().post('i4x://MITx/999/course/Robot_Super_Course') + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':'i4x://MITx/999/course/Robot_Super_Course'}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.delete_item, self.request) + # Should return an HttpResponse + self.permit_user =MagicMock(is_staff = True, is_active = True) + self.permit_user.is_authenticated.return_value = True + self.request_2 = RequestFactory().post(self.item.location.url()) + self.request_2.POST = self.request_2.POST.copy() + self.request_2.POST.update({'id':self.item.location.url()}) + self.request_2.user = self.permit_user + response = views.delete_item(self.request_2) + self.assertIsInstance(response, HttpResponse) + self.assertEquals(modulestore().get_items(self.item.location.url()), []) + # Set delete_children to True to delete all children + # Create children + self.item_2 = ItemFactory.create() + child_item = ItemFactory.create() +## print type(self.item_2) +## print self.item_2.__dict__ + # Is there better way of adding children? What format are children in? + self.item_2.definition['children'] = [child_item.location.url()] + self.request_3 = RequestFactory().post(self.item_2.location.url()) + self.request_3.POST = self.request_3.POST.copy() + self.request_3.POST.update({'id':self.item_2.location.url(), + 'delete_children':True, + 'delete_all_versions':True}) + self.request_3.user = self.permit_user + print self.item_2.get_children() + self.assertIsInstance(views.delete_item(self.request_3), HttpResponse) + self.assertEquals(modulestore().get_items(self.item_2.location.url()), []) + # Problem: Function doesn't delete child item? + # child_item can be manually deleted, but can't delete it using function + # Not sure if problem with _xmodule_recurse and lambda functions + #store = views.get_modulestore(child_item.location.url()) + #store.delete_item(child_item.location) + self.assertEquals(modulestore().get_items(child_item.location.url()), []) + # Check delete_item on 'vertical' + self.item_3 = ItemFactory.create(template = 'i4x://edx/templates/vertical/Empty') + self.request_4 = RequestFactory().post(self.item_3.location.url()) + self.request_4.POST = self.request_4.POST.copy() + self.request_4.POST.update({'id':self.item_3.location.url(), + 'delete_children':True, + 'delete_all_versions':True}) + self.request_4.user = self.permit_user + self.assertIsInstance(views.delete_item(self.request_4), HttpResponse) + self.assertEquals(modulestore().get_items(self.item_3.location.url()), []) + + def test_save_item(self): + # Test that user with no permissions gets redirected + self.no_permit_user = MagicMock(is_staff = False, is_active = False) + self.no_permit_user.is_authenticated.return_value = True + self.request = RequestFactory().post(self.item.location.url()) + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':self.item.location.url()}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.save_item, self.request) + # Test user with permissions but nothing in request.POST + self.item_2 = ItemFactory.create() + self.permit_user =MagicMock(is_staff = True, is_active = True) + self.permit_user.is_authenticated.return_value = True + self.request_2 = RequestFactory().post(self.item_2.location.url()) + self.request_2.POST = self.request.POST.copy() + self.request_2.POST.update({'id':self.item_2.location.url()}) + self.request_2.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_2), HttpResponse) + # Test updating data + self.request_3 = RequestFactory().post(self.item_2.location.url()) + self.request_3.POST = self.request.POST.copy() + self.request_3.POST.update({'id':self.item_2.location.url(), + 'data':{'foo':'bar'}}) + self.request_3.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_3), HttpResponse) + self.assertEquals(modulestore().get_item(self.item_2.location.dict()).definition['data'], + {u'foo': u'bar'}) + # Test metadata, which is a dictionary? + self.request_4 = RequestFactory().post(self.item_2.location.url()) + self.request_4.POST = self.request.POST.copy() + self.request_4.POST.update({'id':self.item_2.location.url(), + 'metadata':{'foo':'bar'}}) + self.request_4.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_4), HttpResponse) + self.assertEquals(modulestore().get_item(self.item_2.location.dict()).metadata['foo'], + 'bar') + +def f(x): + x.n += 1 + class Stub(): def __init__(self): self.n = 0 From c956555da4d0badb5ab0dc335ce8ae9a7720c499 Mon Sep 17 00:00:00 2001 From: cahrens Date: Thu, 31 Jan 2013 14:50:21 -0500 Subject: [PATCH 0431/1392] Note the codemirror version. --- common/static/js/vendor/CodeMirror/codemirror.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/static/js/vendor/CodeMirror/codemirror.js b/common/static/js/vendor/CodeMirror/codemirror.js index ff127f80f6..d345d64a26 100644 --- a/common/static/js/vendor/CodeMirror/codemirror.js +++ b/common/static/js/vendor/CodeMirror/codemirror.js @@ -1,3 +1,5 @@ +// CodeMirror version 2.23 (with edits) +// // All functions that need access to the editor's state live inside // the CodeMirror function. Below that, at the bottom of the file, // some utilities are defined. From d52be034466aa2c583458964de024fa2b05b90ad Mon Sep 17 00:00:00 2001 From: cahrens Date: Thu, 31 Jan 2013 14:52:06 -0500 Subject: [PATCH 0432/1392] Add ACE Editor (contents of src-min-noconflict). last commit: 75ba742f4f00cefadfef1ae451cfb2a4280ad367 package 01.27.2013 --- common/static/js/vendor/ace/ace.js | 11 +++++++++++ common/static/js/vendor/ace/ext-searchbox.js | 1 + common/static/js/vendor/ace/ext-spellcheck.js | 1 + common/static/js/vendor/ace/ext-static_highlight.js | 1 + common/static/js/vendor/ace/ext-textarea.js | 1 + common/static/js/vendor/ace/keybinding-emacs.js | 1 + common/static/js/vendor/ace/keybinding-vim.js | 1 + common/static/js/vendor/ace/mode-abap.js | 1 + common/static/js/vendor/ace/mode-asciidoc.js | 1 + common/static/js/vendor/ace/mode-c9search.js | 1 + common/static/js/vendor/ace/mode-c_cpp.js | 1 + common/static/js/vendor/ace/mode-clojure.js | 1 + common/static/js/vendor/ace/mode-coffee.js | 1 + common/static/js/vendor/ace/mode-coldfusion.js | 1 + common/static/js/vendor/ace/mode-csharp.js | 1 + common/static/js/vendor/ace/mode-css.js | 1 + common/static/js/vendor/ace/mode-curly.js | 1 + common/static/js/vendor/ace/mode-dart.js | 1 + common/static/js/vendor/ace/mode-diff.js | 1 + common/static/js/vendor/ace/mode-dot.js | 1 + common/static/js/vendor/ace/mode-glsl.js | 1 + common/static/js/vendor/ace/mode-golang.js | 1 + common/static/js/vendor/ace/mode-groovy.js | 1 + common/static/js/vendor/ace/mode-haml.js | 1 + common/static/js/vendor/ace/mode-haxe.js | 1 + common/static/js/vendor/ace/mode-html.js | 1 + common/static/js/vendor/ace/mode-jade.js | 1 + common/static/js/vendor/ace/mode-java.js | 1 + common/static/js/vendor/ace/mode-javascript.js | 1 + common/static/js/vendor/ace/mode-json.js | 1 + common/static/js/vendor/ace/mode-jsp.js | 1 + common/static/js/vendor/ace/mode-jsx.js | 1 + common/static/js/vendor/ace/mode-latex.js | 1 + common/static/js/vendor/ace/mode-less.js | 1 + common/static/js/vendor/ace/mode-liquid.js | 1 + common/static/js/vendor/ace/mode-lisp.js | 1 + common/static/js/vendor/ace/mode-lua.js | 1 + common/static/js/vendor/ace/mode-luapage.js | 1 + common/static/js/vendor/ace/mode-lucene.js | 1 + common/static/js/vendor/ace/mode-makefile.js | 1 + common/static/js/vendor/ace/mode-markdown.js | 1 + common/static/js/vendor/ace/mode-objectivec.js | 1 + common/static/js/vendor/ace/mode-ocaml.js | 1 + common/static/js/vendor/ace/mode-perl.js | 1 + common/static/js/vendor/ace/mode-pgsql.js | 1 + common/static/js/vendor/ace/mode-php.js | 1 + common/static/js/vendor/ace/mode-powershell.js | 1 + common/static/js/vendor/ace/mode-python.js | 1 + common/static/js/vendor/ace/mode-r.js | 1 + common/static/js/vendor/ace/mode-rdoc.js | 1 + common/static/js/vendor/ace/mode-rhtml.js | 1 + common/static/js/vendor/ace/mode-ruby.js | 1 + common/static/js/vendor/ace/mode-scad.js | 1 + common/static/js/vendor/ace/mode-scala.js | 1 + common/static/js/vendor/ace/mode-scss.js | 1 + common/static/js/vendor/ace/mode-sh.js | 1 + common/static/js/vendor/ace/mode-sql.js | 1 + common/static/js/vendor/ace/mode-stylus.js | 1 + common/static/js/vendor/ace/mode-svg.js | 1 + common/static/js/vendor/ace/mode-tcl.js | 1 + common/static/js/vendor/ace/mode-tex.js | 1 + common/static/js/vendor/ace/mode-text.js | 0 common/static/js/vendor/ace/mode-textile.js | 1 + common/static/js/vendor/ace/mode-typescript.js | 1 + common/static/js/vendor/ace/mode-vbscript.js | 1 + common/static/js/vendor/ace/mode-xml.js | 1 + common/static/js/vendor/ace/mode-xquery.js | 1 + common/static/js/vendor/ace/mode-yaml.js | 1 + common/static/js/vendor/ace/theme-ambiance.js | 1 + common/static/js/vendor/ace/theme-chaos.js | 1 + common/static/js/vendor/ace/theme-chrome.js | 1 + common/static/js/vendor/ace/theme-clouds.js | 1 + common/static/js/vendor/ace/theme-clouds_midnight.js | 1 + common/static/js/vendor/ace/theme-cobalt.js | 1 + common/static/js/vendor/ace/theme-crimson_editor.js | 1 + common/static/js/vendor/ace/theme-dawn.js | 1 + common/static/js/vendor/ace/theme-dreamweaver.js | 1 + common/static/js/vendor/ace/theme-eclipse.js | 1 + common/static/js/vendor/ace/theme-github.js | 1 + common/static/js/vendor/ace/theme-idle_fingers.js | 1 + common/static/js/vendor/ace/theme-kr.js | 1 + common/static/js/vendor/ace/theme-merbivore.js | 1 + common/static/js/vendor/ace/theme-merbivore_soft.js | 1 + common/static/js/vendor/ace/theme-mono_industrial.js | 1 + common/static/js/vendor/ace/theme-monokai.js | 1 + common/static/js/vendor/ace/theme-pastel_on_dark.js | 1 + common/static/js/vendor/ace/theme-solarized_dark.js | 1 + common/static/js/vendor/ace/theme-solarized_light.js | 1 + common/static/js/vendor/ace/theme-textmate.js | 1 + common/static/js/vendor/ace/theme-tomorrow.js | 1 + common/static/js/vendor/ace/theme-tomorrow_night.js | 1 + .../static/js/vendor/ace/theme-tomorrow_night_blue.js | 1 + .../js/vendor/ace/theme-tomorrow_night_bright.js | 1 + .../js/vendor/ace/theme-tomorrow_night_eighties.js | 1 + common/static/js/vendor/ace/theme-twilight.js | 1 + common/static/js/vendor/ace/theme-vibrant_ink.js | 1 + common/static/js/vendor/ace/theme-xcode.js | 1 + common/static/js/vendor/ace/worker-coffee.js | 1 + common/static/js/vendor/ace/worker-css.js | 1 + common/static/js/vendor/ace/worker-javascript.js | 1 + common/static/js/vendor/ace/worker-json.js | 1 + common/static/js/vendor/ace/worker-php.js | 1 + common/static/js/vendor/ace/worker-xquery.js | 1 + 103 files changed, 112 insertions(+) create mode 100644 common/static/js/vendor/ace/ace.js create mode 100644 common/static/js/vendor/ace/ext-searchbox.js create mode 100644 common/static/js/vendor/ace/ext-spellcheck.js create mode 100644 common/static/js/vendor/ace/ext-static_highlight.js create mode 100644 common/static/js/vendor/ace/ext-textarea.js create mode 100644 common/static/js/vendor/ace/keybinding-emacs.js create mode 100644 common/static/js/vendor/ace/keybinding-vim.js create mode 100644 common/static/js/vendor/ace/mode-abap.js create mode 100644 common/static/js/vendor/ace/mode-asciidoc.js create mode 100644 common/static/js/vendor/ace/mode-c9search.js create mode 100644 common/static/js/vendor/ace/mode-c_cpp.js create mode 100644 common/static/js/vendor/ace/mode-clojure.js create mode 100644 common/static/js/vendor/ace/mode-coffee.js create mode 100644 common/static/js/vendor/ace/mode-coldfusion.js create mode 100644 common/static/js/vendor/ace/mode-csharp.js create mode 100644 common/static/js/vendor/ace/mode-css.js create mode 100644 common/static/js/vendor/ace/mode-curly.js create mode 100644 common/static/js/vendor/ace/mode-dart.js create mode 100644 common/static/js/vendor/ace/mode-diff.js create mode 100644 common/static/js/vendor/ace/mode-dot.js create mode 100644 common/static/js/vendor/ace/mode-glsl.js create mode 100644 common/static/js/vendor/ace/mode-golang.js create mode 100644 common/static/js/vendor/ace/mode-groovy.js create mode 100644 common/static/js/vendor/ace/mode-haml.js create mode 100644 common/static/js/vendor/ace/mode-haxe.js create mode 100644 common/static/js/vendor/ace/mode-html.js create mode 100644 common/static/js/vendor/ace/mode-jade.js create mode 100644 common/static/js/vendor/ace/mode-java.js create mode 100644 common/static/js/vendor/ace/mode-javascript.js create mode 100644 common/static/js/vendor/ace/mode-json.js create mode 100644 common/static/js/vendor/ace/mode-jsp.js create mode 100644 common/static/js/vendor/ace/mode-jsx.js create mode 100644 common/static/js/vendor/ace/mode-latex.js create mode 100644 common/static/js/vendor/ace/mode-less.js create mode 100644 common/static/js/vendor/ace/mode-liquid.js create mode 100644 common/static/js/vendor/ace/mode-lisp.js create mode 100644 common/static/js/vendor/ace/mode-lua.js create mode 100644 common/static/js/vendor/ace/mode-luapage.js create mode 100644 common/static/js/vendor/ace/mode-lucene.js create mode 100644 common/static/js/vendor/ace/mode-makefile.js create mode 100644 common/static/js/vendor/ace/mode-markdown.js create mode 100644 common/static/js/vendor/ace/mode-objectivec.js create mode 100644 common/static/js/vendor/ace/mode-ocaml.js create mode 100644 common/static/js/vendor/ace/mode-perl.js create mode 100644 common/static/js/vendor/ace/mode-pgsql.js create mode 100644 common/static/js/vendor/ace/mode-php.js create mode 100644 common/static/js/vendor/ace/mode-powershell.js create mode 100644 common/static/js/vendor/ace/mode-python.js create mode 100644 common/static/js/vendor/ace/mode-r.js create mode 100644 common/static/js/vendor/ace/mode-rdoc.js create mode 100644 common/static/js/vendor/ace/mode-rhtml.js create mode 100644 common/static/js/vendor/ace/mode-ruby.js create mode 100644 common/static/js/vendor/ace/mode-scad.js create mode 100644 common/static/js/vendor/ace/mode-scala.js create mode 100644 common/static/js/vendor/ace/mode-scss.js create mode 100644 common/static/js/vendor/ace/mode-sh.js create mode 100644 common/static/js/vendor/ace/mode-sql.js create mode 100644 common/static/js/vendor/ace/mode-stylus.js create mode 100644 common/static/js/vendor/ace/mode-svg.js create mode 100644 common/static/js/vendor/ace/mode-tcl.js create mode 100644 common/static/js/vendor/ace/mode-tex.js create mode 100644 common/static/js/vendor/ace/mode-text.js create mode 100644 common/static/js/vendor/ace/mode-textile.js create mode 100644 common/static/js/vendor/ace/mode-typescript.js create mode 100644 common/static/js/vendor/ace/mode-vbscript.js create mode 100644 common/static/js/vendor/ace/mode-xml.js create mode 100644 common/static/js/vendor/ace/mode-xquery.js create mode 100644 common/static/js/vendor/ace/mode-yaml.js create mode 100644 common/static/js/vendor/ace/theme-ambiance.js create mode 100644 common/static/js/vendor/ace/theme-chaos.js create mode 100644 common/static/js/vendor/ace/theme-chrome.js create mode 100644 common/static/js/vendor/ace/theme-clouds.js create mode 100644 common/static/js/vendor/ace/theme-clouds_midnight.js create mode 100644 common/static/js/vendor/ace/theme-cobalt.js create mode 100644 common/static/js/vendor/ace/theme-crimson_editor.js create mode 100644 common/static/js/vendor/ace/theme-dawn.js create mode 100644 common/static/js/vendor/ace/theme-dreamweaver.js create mode 100644 common/static/js/vendor/ace/theme-eclipse.js create mode 100644 common/static/js/vendor/ace/theme-github.js create mode 100644 common/static/js/vendor/ace/theme-idle_fingers.js create mode 100644 common/static/js/vendor/ace/theme-kr.js create mode 100644 common/static/js/vendor/ace/theme-merbivore.js create mode 100644 common/static/js/vendor/ace/theme-merbivore_soft.js create mode 100644 common/static/js/vendor/ace/theme-mono_industrial.js create mode 100644 common/static/js/vendor/ace/theme-monokai.js create mode 100644 common/static/js/vendor/ace/theme-pastel_on_dark.js create mode 100644 common/static/js/vendor/ace/theme-solarized_dark.js create mode 100644 common/static/js/vendor/ace/theme-solarized_light.js create mode 100644 common/static/js/vendor/ace/theme-textmate.js create mode 100644 common/static/js/vendor/ace/theme-tomorrow.js create mode 100644 common/static/js/vendor/ace/theme-tomorrow_night.js create mode 100644 common/static/js/vendor/ace/theme-tomorrow_night_blue.js create mode 100644 common/static/js/vendor/ace/theme-tomorrow_night_bright.js create mode 100644 common/static/js/vendor/ace/theme-tomorrow_night_eighties.js create mode 100644 common/static/js/vendor/ace/theme-twilight.js create mode 100644 common/static/js/vendor/ace/theme-vibrant_ink.js create mode 100644 common/static/js/vendor/ace/theme-xcode.js create mode 100644 common/static/js/vendor/ace/worker-coffee.js create mode 100644 common/static/js/vendor/ace/worker-css.js create mode 100644 common/static/js/vendor/ace/worker-javascript.js create mode 100644 common/static/js/vendor/ace/worker-json.js create mode 100644 common/static/js/vendor/ace/worker-php.js create mode 100644 common/static/js/vendor/ace/worker-xquery.js diff --git a/common/static/js/vendor/ace/ace.js b/common/static/js/vendor/ace/ace.js new file mode 100644 index 0000000000..740a1e4899 --- /dev/null +++ b/common/static/js/vendor/ace/ace.js @@ -0,0 +1,11 @@ +(function(){function o(e){var i=function(e,t){return r("",e,t)},s=t;e&&(t[e]||(t[e]={}),s=t[e]);if(!s.define||!s.define.packaged)n.original=s.define,s.define=n,s.define.packaged=!0;if(!s.require||!s.require.packaged)r.original=s.require,s.require=i,s.require.packaged=!0}var e="ace",t=function(){return this}();if(!e&&typeof requirejs!="undefined")return;var n=function(e,t,r){if(typeof e!="string"){n.original?n.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(r=t),n.modules||(n.modules={}),n.modules[e]=r},r=function(e,t,n){if(Object.prototype.toString.call(t)==="[object Array]"){var i=[];for(var o=0,u=t.length;o1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function m(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError;var r=o.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e,u=n.apply(s,r.concat(o.call(arguments)));return u!==null&&Object(u)===u?u:s}return n.apply(t,r.concat(o.call(arguments)))};return i});var r=Function.prototype.call,i=Array.prototype,s=Object.prototype,o=i.slice,u=r.bind(s.toString),a=r.bind(s.hasOwnProperty),f,l,c,h,p;if(p=a(s,"__defineGetter__"))f=r.bind(s.__defineGetter__),l=r.bind(s.__defineSetter__),c=r.bind(s.__lookupGetter__),h=r.bind(s.__lookupSetter__);Array.isArray||(Array.isArray=function(t){return u(t)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=D(this),r=arguments[1],i=0,s=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;while(i>>0,i=Array(r),s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o>>0,i=[],s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i=0,s;if(arguments.length>=2)s=arguments[1];else do{if(i in n){s=n[i++];break}if(++i>=r)throw new TypeError}while(!0);for(;i>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i,s=r-1;if(arguments.length>=2)i=arguments[1];else do{if(s in n){i=n[s--];break}if(--s<0)throw new TypeError}while(!0);do s in this&&(i=t.call(void 0,i,n[s],s,n));while(s--);return i}),Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var n=D(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=M(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,M(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:s)});if(!Object.getOwnPropertyDescriptor){var d="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(d+t);if(!a(t,n))return;var r,i,o;r={enumerable:!0,configurable:!0};if(p){var u=t.__proto__;t.__proto__=s;var i=c(t,n),o=h(t,n);t.__proto__=u;if(i||o)return i&&(r.get=i),o&&(r.set=o),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var v;Object.prototype.__proto__===null?v=function(){return{__proto__:null}}:v=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=v();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var g=m({}),y=typeof document=="undefined"||m(document.createElement("div"));if(!g||!y)var b=Object.defineProperty}if(!Object.defineProperty||b){var w="Property description must be an object: ",E="Object.defineProperty called on non-object: ",S="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(E+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(w+r);if(b)try{return b.call(Object,t,n,r)}catch(i){}if(a(r,"value"))if(p&&(c(t,n)||h(t,n))){var o=t.__proto__;t.__proto__=s,delete t[n],t[n]=r.value,t.__proto__=o}else t[n]=r.value;else{if(!p)throw new TypeError(S);a(r,"get")&&f(t,n,r.get),a(r,"set")&&l(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)a(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(x){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(a(t,n))n+="?";t[n]=!0;var r=a(t,n);return delete t[n],r});if(!Object.keys){var T=!0,N=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],C=N.length;for(var k in{toString:null})T=!1;Object.keys=function P(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var P=[];for(var t in e)a(e,t)&&P.push(t);if(T)for(var n=0,r=C;n9999?"+":"")+("00000"+Math.abs(i)).slice(0<=i&&i<=9999?-4:-6),n=t.length;while(n--)r=t[n],r<10&&(t[n]="0"+r);return i+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(t){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(e){var t=function i(t,n,r,s,o,u,a){var f=arguments.length;if(this instanceof e){var l=f==1&&String(t)===t?new e(i.parse(t)):f>=7?new e(t,n,r,s,o,u,a):f>=6?new e(t,n,r,s,o,u):f>=5?new e(t,n,r,s,o):f>=4?new e(t,n,r,s):f>=3?new e(t,n,r):f>=2?new e(t,n):f>=1?new e(t):new e;return l.constructor=i,l}return e.apply(this,arguments)},n=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var r in e)t[r]=e[r];return t.now=e.now,t.UTC=e.UTC,t.prototype=e.prototype,t.prototype.constructor=t,t.parse=function(r){var i=n.exec(r);if(i){i.shift();for(var s=1;s<7;s++)i[s]=+(i[s]||(s<3?1:0)),s==1&&i[s]--;var o=+i.pop(),u=+i.pop(),a=i.pop(),f=0;if(a){if(u>23||o>59)return NaN;f=(u*60+o)*6e4*(a=="+"?-1:1)}var l=+i[0];return 0<=l&&l<=99?(i[0]=l+400,e.UTC.apply(this,i)+f-126227808e5):e.UTC.apply(this,i)+f}return e.parse.apply(this,arguments)},t}(Date));var L=" \n \f\r   ᠎ â€â€‚         âŸã€€\u2028\u2029";if(!String.prototype.trim||L.trim()){L="["+L+"]";var A=new RegExp("^"+L+L+"*"),O=new RegExp(L+L+"*$");String.prototype.trim=function(){return String(this).replace(A,"").replace(O,"")}}var M=function(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e},_="a"[0]!="a",D=function(e){if(e==null)throw new TypeError;return _&&typeof e=="string"&&e?e.split(""):Object(e)}}),ace.define("ace/lib/dom",["require","exports","module"],function(e,t,n){var r="http://www.w3.org/1999/xhtml";t.createElement=function(e,t){return document.createElementNS?document.createElementNS(t||r,e):document.createElement(e)},t.setText=function(e,t){e.innerText!==undefined&&(e.innerText=t),e.textContent!==undefined&&(e.textContent=t)},t.hasCssClass=function(e,t){var n=e.className.split(/\s+/g);return n.indexOf(t)!==-1},t.addCssClass=function(e,n){t.hasCssClass(e,n)||(e.className+=" "+n)},t.removeCssClass=function(e,t){var n=e.className.split(/\s+/g);for(;;){var r=n.indexOf(t);if(r==-1)break;n.splice(r,1)}e.className=n.join(" ")},t.toggleCssClass=function(e,t){var n=e.className.split(/\s+/g),r=!0;for(;;){var i=n.indexOf(t);if(i==-1)break;r=!1,n.splice(i,1)}return r&&n.push(t),e.className=n.join(" "),r},t.setCssClass=function(e,n,r){r?t.addCssClass(e,n):t.removeCssClass(e,n)},t.hasCssString=function(e,t){var n=0,r;t=t||document;if(t.createStyleSheet&&(r=t.styleSheets)){while(n5||Math.abs(e.clientY-a)>5;if(!f||i)o=0;o+=1,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600)}o==1&&(u=e.clientX,a=e.clientY),r[s]("mousedown",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}),i.isOldIE&&t.addListener(e,"dblclick",function(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s]("mousedown",e),r[s](l[o],e)})},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!("KeyboardEvent"in window)){var s=null;r(e,"keydown",function(e){s=e.keyCode}),r(e,"keypress",function(e){return o(n,e,s)})}else{var u=null;r(e,"keydown",function(e){return u=e.keyIdentifier||e.keyCode,o(n,e,e.keyCode)})}};if(window.postMessage&&!i.isOldIE){var u=1;t.nextTick=function(e,n){n=n||window;var r="zero-timeout-message-"+u;t.addListener(n,"message",function i(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,"message",i),e())}),n.postMessage(r,"*")}}t.nextFrame=window.requestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame,t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),ace.define("ace/lib/keys",["require","exports","module","ace/lib/oop"],function(e,t,n){var r=e("./oop"),i=function(){var e={MODIFIER_KEYS:{16:"Shift",17:"Ctrl",18:"Alt",224:"Meta"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,meta:8,command:8},FUNCTION_KEYS:{8:"Backspace",9:"Tab",13:"Return",19:"Pause",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"Print",45:"Insert",46:"Delete",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Numlock",145:"Scrolllock"},PRINTABLE_KEYS:{32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",107:"+",109:"-",110:".",188:",",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"}};for(var t in e.FUNCTION_KEYS){var n=e.FUNCTION_KEYS[t].toLowerCase();e[n]=parseInt(t,10)}return r.mixin(e,e.MODIFIER_KEYS),r.mixin(e,e.PRINTABLE_KEYS),r.mixin(e,e.FUNCTION_KEYS),e.enter=e["return"],e.escape=e.esc,e.del=e["delete"],e[173]="-",e}();r.mixin(t,i),t.keyCodeToString=function(e){return(i[e]||String.fromCharCode(e)).toLowerCase()}}),ace.define("ace/lib/oop",["require","exports","module"],function(e,t,n){t.inherits=function(){var e=function(){};return function(t,n){e.prototype=n.prototype,t.super_=n.prototype,t.prototype=new e,t.prototype.constructor=t}}(),t.mixin=function(e,t){for(var n in t)e[n]=t[n]},t.implement=function(e,n){t.mixin(e,n)}}),ace.define("ace/lib/useragent",["require","exports","module"],function(e,t,n){t.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},t.getOS=function(){return t.isMac?t.OS.MAC:t.isLinux?t.OS.LINUX:t.OS.WINDOWS};if(typeof navigator!="object")return;var r=(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase(),i=navigator.userAgent;t.isWin=r=="win",t.isMac=r=="mac",t.isLinux=r=="linux",t.isIE=(navigator.appName=="Microsoft Internet Explorer"||navigator.appName.indexOf("MSAppHost")>=0)&&parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=window.controllers&&window.navigator.product==="Gecko",t.isOldGecko=t.isGecko&&parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",t.isWebKit=parseFloat(i.split("WebKit/")[1])||undefined,t.isChrome=parseFloat(i.split(" Chrome/")[1])||undefined,t.isAIR=i.indexOf("AdobeAIR")>=0,t.isIPad=i.indexOf("iPad")>=0,t.isTouchPad=i.indexOf("TouchPad")>=0}),ace.define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands","ace/config"],function(e,t,n){e("./lib/fixoldbrowsers");var r=e("./lib/oop"),i=e("./lib/lang"),s=e("./lib/useragent"),o=e("./keyboard/textinput").TextInput,u=e("./mouse/mouse_handler").MouseHandler,a=e("./mouse/fold_handler").FoldHandler,f=e("./keyboard/keybinding").KeyBinding,l=e("./edit_session").EditSession,c=e("./search").Search,h=e("./range").Range,p=e("./lib/event_emitter").EventEmitter,d=e("./commands/command_manager").CommandManager,v=e("./commands/default_commands").commands,m=e("./config"),g=function(e,t){var n=e.getContainerElement();this.container=n,this.renderer=e,this.commands=new d(s.isMac?"mac":"win",v),this.textInput=new o(e.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.keyBinding=new f(this),this.$mouseHandler=new u(this),new a(this),this.$blockScrolling=0,this.$search=(new c).set({wrap:!0}),this.setSession(t||new l(""))};(function(){r.implement(this,p),this.setKeyboardHandler=function(e){if(typeof e=="string"&&e){this.$keybindingId=e;var t=this;m.loadModule(["keybinding",e],function(n){t.$keybindingId==e&&t.keyBinding.setKeyboardHandler(n&&n.handler)})}else delete this.$keybindingId,this.keyBinding.setKeyboardHandler(e)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;if(this.session){var t=this.session;this.session.removeEventListener("change",this.$onDocumentChange),this.session.removeEventListener("changeMode",this.$onChangeMode),this.session.removeEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.session.removeEventListener("changeTabSize",this.$onChangeTabSize),this.session.removeEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.session.removeEventListener("changeWrapMode",this.$onChangeWrapMode),this.session.removeEventListener("onChangeFold",this.$onChangeFold),this.session.removeEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.session.removeEventListener("changeBackMarker",this.$onChangeBackMarker),this.session.removeEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.session.removeEventListener("changeAnnotation",this.$onChangeAnnotation),this.session.removeEventListener("changeOverwrite",this.$onCursorChange),this.session.removeEventListener("changeScrollTop",this.$onScrollTopChange),this.session.removeEventListener("changeLeftTop",this.$onScrollLeftChange);var n=this.session.getSelection();n.removeEventListener("changeCursor",this.$onCursorChange),n.removeEventListener("changeSelection",this.$onSelectionChange)}this.session=e,this.$onDocumentChange=this.onDocumentChange.bind(this),e.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.addEventListener("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.addEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.addEventListener("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.addEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.addEventListener("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.addEventListener("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.addEventListener("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.addEventListener("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.addEventListener("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull(),this._emit("changeSession",{session:e,oldSession:t})},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e){this.renderer.setTheme(e)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.setFontSize=function(e){this.container.style.fontSize=e,this.renderer.updateFontSize()},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session.findMatchingBracket(e.getCursorPosition());if(t){var n=new h(t.row,t.column,t.row,t.column+1);e.session.$bracketHighlight=e.session.addMarker(n,"ace_bracket","text")}},50)},this.focus=function(){var e=this;setTimeout(function(){e.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){if(this.$isFocused)return;this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus")},this.onBlur=function(){if(!this.$isFocused)return;this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur")},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(e){var t=e.data,n=t.range,r;n.start.row==n.end.row&&t.action!="insertLines"&&t.action!="removeLines"?r=n.end.row:r=Infinity,this.renderer.updateLines(n.start.row,r),this._emit("change",e),this.$cursorChange()},this.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.$highlightBrackets(),this.$updateHighlightActiveLine(),this._emit("changeSelection")},this.$updateHighlightActiveLine=function(){var e=this.getSession(),t;this.$highlightActiveLine&&(this.$selectionStyle!="line"||!this.selection.isMultiLine())&&(t=this.getCursorPosition()),e.$highlightLineMarker&&!t?(e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null):!e.$highlightLineMarker&&t?e.$highlightLineMarker=e.highlightLines(t.row,t.row,"ace_active-line"):t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e._emit("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,"ace_selection",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._emit("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column-1,r=t.end.column+1,i=e.getLine(t.start.row),s=i.length,o=i.substring(Math.max(n,0),Math.min(r,s));if(n>=0&&/^[\w\d]/.test(o)||r<=s&&/[\w\d]$/.test(o))return;o=i.substring(t.start.column,t.end.column);if(!/^[\w\d]+$/.test(o))return;var u=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:o});return u},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(){this.renderer.updateText()},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){var e="";return this.selection.isEmpty()||(e=this.session.getTextRange(this.getSelectionRange())),this._emit("copy",e),e},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(e){if(this.$readOnly)return;this._emit("paste",e),this.insert(e)},this.execCommand=function(e,t){this.commands.exec(e,this,t)},this.insert=function(e){var t=this.session,n=t.getMode(),r=this.getCursorPosition();if(this.getBehavioursEnabled()){var i=n.transformAction(t.getState(r.row),"insertion",this,t,e);i&&(e=i.text)}e=e.replace(" ",this.session.getTabString());if(!this.selection.isEmpty())r=this.session.remove(this.getSelectionRange()),this.clearSelection();else if(this.session.getOverwrite()){var s=new h.fromPoints(r,r);s.end.column+=e.length,this.session.remove(s)}this.clearSelection();var o=r.column,u=t.getState(r.row),a=t.getLine(r.row),f=n.checkOutdent(u,a,e),l=t.insert(r,e);i&&i.selection&&(i.selection.length==2?this.selection.setSelectionRange(new h(r.row,o+i.selection[0],r.row,o+i.selection[1])):this.selection.setSelectionRange(new h(r.row+i.selection[0],i.selection[1],r.row+i.selection[2],i.selection[3])));if(t.getDocument().isNewLine(e)){var c=n.getNextLineIndent(u,a.slice(0,r.column),t.getTabString());this.moveCursorTo(r.row+1,0);var p=t.getTabSize(),d=Number.MAX_VALUE;for(var v=r.row+1;v<=l.row;++v){var m=0;a=t.getLine(v);for(var g=0;g0;++g)a.charAt(g)==" "?y-=p:a.charAt(g)==" "&&(y-=1);t.remove(new h(v,0,v,g))}t.indentRows(r.row+1,l.row,c)}f&&n.autoOutdent(u,t,r.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.$mouseHandler.setScrollSpeed(e)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.setDragDelay=function(e){this.$mouseHandler.setDragDelay(e)},this.getDragDelay=function(){return this.$mouseHandler.getDragDelay()},this.$selectionStyle="line",this.setSelectionStyle=function(e){if(this.$selectionStyle==e)return;this.$selectionStyle=e,this.onSelectionChange(),this._emit("changeSelectionStyle",{data:e})},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(e){if(this.$highlightActiveLine==e)return;this.$highlightActiveLine=e,this.$updateHighlightActiveLine()},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightGutterLine=!0,this.setHighlightGutterLine=function(e){if(this.$highlightGutterLine==e)return;this.renderer.setHighlightGutterLine(e),this.$highlightGutterLine=e},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(e){if(this.$highlightSelectedWord==e)return;this.$highlightSelectedWord=e,this.$onSelectionChange()},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(e){this.$readOnly=e,this.textInput.setReadOnly(e),this.renderer.$cursorLayer.setBlinking(!e)},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(e){this.$modeBehaviours=e},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.$modeWrapBehaviours=!0,this.setWrapBehavioursEnabled=function(e){this.$modeWrapBehaviours=e},this.getWrapBehavioursEnabled=function(){return this.$modeWrapBehaviours},this.setShowFoldWidgets=function(e){var t=this.renderer.$gutterLayer;if(t.getShowFoldWidgets()==e)return;this.renderer.$gutterLayer.setShowFoldWidgets(e),this.$showFoldWidgets=e,this.renderer.updateFull()},this.getShowFoldWidgets=function(){return this.renderer.$gutterLayer.getShowFoldWidgets()},this.setFadeFoldWidgets=function(e){this.renderer.setFadeFoldWidgets(e)},this.getFadeFoldWidgets=function(){return this.renderer.getFadeFoldWidgets()},this.remove=function(e){this.selection.isEmpty()&&(e=="left"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,"deletion",this,n,t);i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;tt.toLowerCase()?1:0});var r=new h(0,0,0,0);for(var i=e.first;i<=e.last;i++){var s=t.getLine(i);r.start.row=i,r.end.row=i,r.end.column=s.length,t.replace(r,n[i-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.getNumberAt=function(e,t){var n=/[\-]?[0-9]+(?:\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new h(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(".")>=0?s.start+s.value.indexOf(".")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&n=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,t==1?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t==0&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e){var t=this.getCursorPosition(),n=this.session.getBracketRange(t);if(!n){n=this.find({needle:/[{}()\[\]]/g,preventScroll:!0,start:{row:t.row,column:t.column-1}});if(!n)return;var r=n.start;r.row==t.row&&Math.abs(r.column-t.column)<2&&(n=this.session.getBracketRange(r))}r=n&&n.cursor||r,r&&(e?n&&n.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(r.row,r.column):(this.clearSelection(),this.moveCursorTo(r.row,r.column)))},this.gotoLine=function(e,t,n){this.selection.clearSelection(),this.session.unfold({row:e-1,column:t||0}),this.$blockScrolling+=1,this.moveCursorTo(e-1,t||0),this.$blockScrolling-=1,this.isRowFullyVisible(e-1)||this.scrollToLine(e-1,!0,n)},this.navigateTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.navigateUp=function(e){this.selection.clearSelection(),e=e||1,this.selection.moveCursorBy(-e,0)},this.navigateDown=function(e){this.selection.clearSelection(),e=e||1,this.selection.moveCursorBy(e,0)},this.navigateLeft=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().start;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().end;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){var e=this.renderer.scrollTop;this.selection.moveCursorFileEnd(),this.clearSelection(),this.renderer.animateScrolling(e)},this.navigateFileStart=function(){var e=this.renderer.scrollTop;this.selection.moveCursorFileStart(),this.clearSelection(),this.renderer.animateScrolling(e)},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(e,t){t&&this.$search.set(t);var n=this.$search.find(this.session),r=0;return n?(this.$tryReplace(n,e)&&(r=1),n!==null&&(this.selection.setSelectionRange(n),this.renderer.scrollSelectionIntoView(n.start,n.end)),r):r},this.replaceAll=function(e,t){t&&this.$search.set(t);var n=this.$search.findAll(this.session),r=0;if(!n.length)return r;this.$blockScrolling+=1;var i=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0);for(var s=n.length-1;s>=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),this.$blockScrolling-=1,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e=="string"||e instanceof RegExp?t.needle=e:typeof e=="object"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!=0&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy()}}).call(g.prototype),t.Editor=g}),ace.define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=a(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.renderer.scrollCursorIntoView()},this.startDrag=function(){var e=this.editor;this.setState("drag"),this.dragRange=e.getSelectionRange();var t=e.getSelectionStyle();this.dragSelectionMarker=e.session.addMarker(this.dragRange,"ace_selection",t),e.clearSelection(),r.addCssClass(e.container,"ace_dragging"),this.$dragKeybinding||(this.$dragKeybinding={handleKeyboard:function(e,t,n,r){if(n=="esc")return{command:this.command}},command:{exec:function(e){var t=e.$mouseHandler;t.dragCursor=null,t.dragEnd(),t.startSelect()}}}),e.keyBinding.addKeyboardHandler(this.$dragKeybinding)},this.focusWait=function(){var e=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=(new Date).getTime();(e>s||t-this.mousedownEvent.time>this.$focusWaitTimout)&&this.startSelect()},this.dragWait=function(e){var t=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),n=(new Date).getTime(),r=this.editor;t>s?this.startSelect(this.mousedownEvent.getDocumentPosition()):n-this.mousedownEvent.time>r.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(e){this.mousedownEvent.domEvent=e,this.startSelect()},this.drag=function(){var e=this.editor;this.dragCursor=e.renderer.screenToTextCoordinates(this.x,this.y),e.moveCursorToPosition(this.dragCursor),e.renderer.scrollCursorIntoView()},this.dragEnd=function(e){var t=this.editor,n=this.dragCursor,i=this.dragRange;r.removeCssClass(t.container,"ace_dragging"),t.session.removeMarker(this.dragSelectionMarker),t.keyBinding.removeKeyboardHandler(this.$dragKeybinding);if(!n)return;t.clearSelection();if(e&&(e.ctrlKey||e.altKey)){var s=t.session,o=i;o.end=s.insert(n,s.getTextRange(i)),o.start=n}else{if(i.contains(n.row,n.column))return;var o=t.moveText(i,n)}if(!o)return;t.selection.setSelectionRange(o)},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);if(i){i.isEmpty()&&(i.start.column--,i.end.column++),this.$clickSelection=i,this.setState("select");return}this.$clickSelection=n.selection.getWordRange(t.row,t.column),this.setState("selectByWords")},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState("selectByLines"),this.$clickSelection=n.selection.getLineRange(t.row)},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("null")},this.onMouseWheel=function(e){if(e.getShiftKey()||e.getAccelKey())return;var t=this.editor,n=t.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);if(n)this.$passScrollEvent=!1;else{if(this.$passScrollEvent)return;if(!this.$scrollStopTimeout){var r=this;this.$scrollStopTimeout=setTimeout(function(){r.$passScrollEvent=!0,r.$scrollStopTimeout=null},200)}}return t.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.preventDefault()}}).call(o.prototype),t.DefaultHandlers=o}),ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/event"],function(e,t,n){function s(e){function f(){u=r.createElement("div"),u.className="ace_gutter-tooltip",u.style.display="none",t.container.appendChild(u)}function l(){u||f();var e=o.getDocumentPosition().row,r=n.$annotations[e];if(!r)return c();var i=t.session.getLength();if(e==i){var s=t.renderer.pixelToScreenCoordinates(0,o.y).row,l=o.$pos;if(s>t.session.documentToScreenRow(l.row,l.column))return c()}if(a==r)return;a=r.text.join("
    "),u.style.display="block",u.innerHTML=a,t.on("mousewheel",c),h(o)}function c(){s&&(s=clearTimeout(s)),a&&(u.style.display="none",a=null,t.removeEventListener("mousewheel",c))}function h(e){var n=t.renderer.$gutter.getBoundingClientRect();u.style.left=e.x+15+"px",e.y+3*t.renderer.lineHeight+150)return;return clearInterval(o),t.session.removeMarker(n),n=null,t.selection.setSelectionRange(u,a),r.preventDefault(e)}),r.addListener(c,"drop",function(e){if(t.getReadOnly())return;return l=0,clearInterval(o),t.session.removeMarker(n),n=null,u.end=t.session.insert(f,e.dataTransfer.getData("Text")),u.start=f,t.focus(),t.selection.setSelectionRange(u),r.preventDefault(e)})};t.DragdropHandler=i}),ace.define("ace/mouse/fold_handler",["require","exports","module"],function(e,t,n){function r(e){e.on("click",function(t){var n=t.getDocumentPosition(),r=e.session,i=r.getFoldAt(n.row,n.column,1);i&&(t.getAccelKey()?r.removeFold(i):r.expandFold(i),t.stop())}),e.on("guttermousedown",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),t.stop()}}),e.on("gutterdblclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session,s=i.foldWidgets;if(!s||s[r])return;var o=r-1,u;while(o>=0){var a=s[o];a==null&&(a=s[o]=i.getFoldWidget());if(a=="start"){var f=i.getFoldWidgetRange(o);u||(u=f);if(f&&f.end.row>=r)break}o--}o==-1&&(f=u);if(f){var r=f.start.row,l=i.getFoldAt(r,i.getLine(r).length,1);l?i.removeFold(l):(i.addFold("...",f),e.renderer.scrollCursorIntoView({row:f.start.row,column:0}))}t.stop()}})}t.FoldHandler=r}),ace.define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,n){var r=e("../lib/keys"),i=e("../lib/event"),s=function(e){this.$editor=e,this.$data={},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0),this.$data={editor:this.$editor}},this.setKeyboardHandler=function(e){if(this.$handlers[this.$handlers.length-1]==e)return;while(this.$handlers[1])this.removeKeyboardHandler(this.$handlers[1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command=="null"?o=s.passEvent!=1:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&i.stopEvent(r);if(o)break}return o},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){var t=this.$callKeyboardHandlers(-1,e);t||this.$editor.commands.exec("insertstring",this.$editor,e)}}).call(s.prototype),t.KeyBinding=s}),ace.define("ace/edit_session",["require","exports","module","ace/config","ace/lib/oop","ace/lib/lang","ace/lib/net","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"],function(e,t,n){var r=e("./config"),i=e("./lib/oop"),s=e("./lib/lang"),o=e("./lib/net"),u=e("./lib/event_emitter").EventEmitter,a=e("./selection").Selection,f=e("./mode/text").Mode,l=e("./range").Range,c=e("./document").Document,h=e("./background_tokenizer").BackgroundTokenizer,p=e("./search_highlight").SearchHighlight,d=function(e,t){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.$foldData.toString=function(){var e="";return this.forEach(function(t){e+="\n"+t.toString()}),e},this.on("changeFold",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this);if(typeof e!="object"||!e.getLine)e=new c(e);this.setDocument(e),this.selection=new a(this),this.setMode(t)};(function(){function g(e){return e<4352?!1:e>=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}i.implement(this,u),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$getRowCacheIndex(this.$docRowCache,e)+1,n=this.$docRowCache.length;this.$docRowCache.splice(t,n),this.$screenRowCache.splice(t,n)},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:"fold",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:"doc",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:"aceupdate",args:[t.$deltas,t]}),t.$deltas=[]},this.$informUndoManager=s.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?s.stringRepeat(" ",this.getTabSize()):" "},this.$useSoftTabs=!0,this.setUseSoftTabs=function(e){if(this.$useSoftTabs===e)return;this.$useSoftTabs=e},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._emit("changeTabSize")},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(e){if(this.$overwrite==e)return;this.$overwrite=e,this._emit("changeOverwrite")},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._emit("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._emit("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\s+$/.test(n.slice(t-1,t+1)))var i=/\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(oo){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=e.length-1;r!=-1;r--){var i=e[r];i.group=="doc"?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=0;r=this.doc.getLength()-1)return 0;var n=this.doc.removeLines(e,t);return this.doc.insertLines(e+1,n),1},this.duplicateLines=function(e,t){var e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t),n=this.getLines(e,t);this.doc.insertLines(e,n);var r=t-e+1;return r},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=[];for(var n=0;n0?(this.$wrapLimit=t,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._emit("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e){var t=this.$wrapLimitRange.min;t&&(e=Math.max(t,e));var n=this.$wrapLimitRange.max;return n&&(e=Math.min(n,e)),Math.max(1,e)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n,r=e.data.action,i=e.data.range.start.row,s=e.data.range.end.row,o=e.data.range.start,u=e.data.range.end,a=null;r.indexOf("Lines")!=-1?(r=="insertLines"?s=i+e.data.lines.length:s=i,n=e.data.lines?e.data.lines.length:s-i):n=s-i;if(n!=0)if(r.indexOf("remove")!=-1){this[t?"$wrapData":"$rowLengthCache"].splice(i,n);var f=this.$foldData;a=this.getFoldsInRange(e.data.range),this.removeFolds(a);var l=this.getFoldLine(u.row),c=0;if(l){l.addRemoveChars(u.row,u.column,o.column-u.column),l.shiftRow(-n);var h=this.getFoldLine(i);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c=u.row&&l.shiftRow(-n)}s=i}else{var p;if(t){p=[i,0];for(var d=0;d=i&&l.shiftRow(n)}}else{n=Math.abs(e.data.range.start.column-e.data.range.end.column),r.indexOf("remove")!=-1&&(a=this.getFoldsInRange(e.data.range),this.removeFolds(a),n=-n);var l=this.getFoldLine(i);l&&l.addRemoveChars(i,o.column,n)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),t?this.$updateWrapData(i,s):this.$updateRowLengthCache(i,s),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var n=this.doc.getAllLines(),r=this.getTabSize(),i=this.$wrapData,u=this.$wrapLimit,f,l,c=e;t=Math.min(t,n.length-1);while(c<=t){l=this.getFoldLine(c,l);if(!l)f=this.$getDisplayTokens(s.stringTrimRight(n[c])),i[c]=this.$computeWrapSplits(f,u,r),c++;else{f=[],l.walk(function(e,t,r,i){var s;if(e!=null){s=this.$getDisplayTokens(e,f.length),s[0]=o;for(var u=1;u=d)f.pop();i[l.start.row]=this.$computeWrapSplits(f,u,r),c=l.end.row+1}}};var t=1,n=2,o=3,a=4,c=9,d=10,v=11,m=12;this.$computeWrapSplits=function(e,t){function u(t){var r=e.slice(i,t),o=r.length;r.join("").replace(/12/g,function(){o-=1}).replace(/2/g,function(){o-=1}),s+=o,n.push(s),i=t}if(e.length==0)return[];var n=[],r=e.length,i=0,s=0;while(r-i>t){var f=i+t;if(e[f]>=d){while(e[f]>=d)f++;u(f);continue}if(e[f]==o||e[f]==a){for(f;f!=i-1;f--)if(e[f]==o)break;if(f>i){u(f);continue}f=i+t;for(f;fl&&e[f]l&&e[f]==c)f--;if(f>l){u(++f);continue}f=i+t,u(f)}return n},this.$getDisplayTokens=function(e,r){var i=[],s;r=r||0;for(var o=0;o39&&u<48||u>57&&u<64?i.push(c):u>=4352&&g(u)?i.push(t,n):i.push(t)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i=4352&&g(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.getRowLength=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getScreenLastRowColumn=function(e){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE);return this.documentToScreenColumn(t.row,t.column)},this.getDocumentLastRowColumn=function(e,t){var n=this.documentToScreenRow(e,t);return this.getScreenLastRowColumn(n)},this.getDocumentLastRowColumnPosition=function(e,t){var n=this.documentToScreenRow(e,t);return this.screenToDocumentPosition(n,Number.MAX_VALUE/10)},this.getRowSplitData=function(e){return this.$useWrapMode?this.$wrapData[e]:undefined},this.getScreenTabSize=function(e){return this.$tabSize-e%this.$tabSize},this.screenToDocumentRow=function(e,t){return this.screenToDocumentPosition(e,t).row},this.screenToDocumentColumn=function(e,t){return this.screenToDocumentPosition(e,t).column},this.screenToDocumentPosition=function(e,t){if(e<0)return{row:0,column:0};var n,r=0,i=0,s,o=0,u=0,a=this.$screenRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var o=a[f],r=this.$docRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getLength()-1,p=this.getNextFoldLine(r),d=p?p.start.row:Infinity;while(o<=e){u=this.getRowLength(r);if(o+u-1>=e||r>=h)break;o+=u,r++,r>d&&(r=p.end.row+1,p=this.getNextFoldLine(r,p),d=p?p.start.row:Infinity),c&&(this.$docRowCache.push(r),this.$screenRowCache.push(o))}if(p&&p.start.row<=r)n=this.getFoldDisplayLine(p),r=p.start.row;else{if(o+u<=e||r>h)return{row:h,column:this.getLine(h).length};n=this.getLine(r),p=null}if(this.$useWrapMode){var v=this.$wrapData[r];v&&(s=v[e-o],e>o&&v.length&&(i=v[e-o-1]||v[v.length-1],n=n.substring(i)))}return i+=this.$getStringScreenWidth(n,t)[1],this.$useWrapMode&&i>=s&&(i=s-1),p?p.idxToPosition(i):{row:r,column:i}},this.documentToScreenPosition=function(e,t){if(typeof t=="undefined")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d="";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);if(this.$useWrapMode){var v=this.$wrapData[i],m=0;while(d.length>=v[m])r++,m++;d=d.substring(v[m-1]||0,d.length)}return{row:r,column:this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;ro&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}return e}}).call(d.prototype),e("./edit_session/folding").Folding.call(d.prototype),e("./edit_session/bracket_match").BracketMatch.call(d.prototype),t.EditSession=d}),ace.define("ace/config",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/lib/net","ace/lib/event_emitter"],function(e,t,n){"no use strict";function f(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./lib/net"),o=e("./lib/event_emitter").EventEmitter,u=function(){return this}(),a={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:"",suffix:".js",$moduleUrls:{}};t.get=function(e){if(!a.hasOwnProperty(e))throw new Error("Unknown config key: "+e);return a[e]},t.set=function(e,t){if(!a.hasOwnProperty(e))throw new Error("Unknown config key: "+e);a[e]=t},t.all=function(){return r.copyObject(a)},i.implement(t,o),t.moduleUrl=function(e,t){if(a.$moduleUrls[e])return a.$moduleUrls[e];var n=e.split("/");t=t||n[n.length-2]||"";var r=n[n.length-1].replace(t,"").replace(/(^[\-_])|([\-_]$)/,"");!r&&n.length>1&&(r=n[n.length-2]);var i=a[t+"Path"];return i==null&&(i=a.basePath),i&&i.slice(-1)!="/"&&(i+="/"),i+t+"-"+r+this.get("suffix")},t.setModuleUrl=function(e,t){return a.$moduleUrls[e]=t},t.loadModule=function(n,r){var i,o;Array.isArray(n)&&(o=n[0],n=n[1]);try{i=e(n)}catch(u){}if(i)return r(i);var a=function(){e([n],function(e){t._emit("load.module",{name:n,module:e}),r(e)})};if(!t.get("packaged"))return a();s.loadScript(t.moduleUrl(n,o),a)},t.init=function(){a.packaged=e.packaged||n.packaged||u.define&&define.packaged;if(!u.document)return"";var r={},i="",s=document.getElementsByTagName("script");for(var o=0;ot.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t=="undefined"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e=="number"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column==0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(e.column-n,e.column).split(" ").length-1==n?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var s=this.session.getFoldAt(e,t,1);if(s){this.moveCursorTo(s.end.row,s.end.column);return}if(i=this.session.nonTokenRe.exec(r))t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t);if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e0&&this.moveCursorWordLeft();return}if(o=this.session.tokenRe.exec(s))t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t,n=0,r,i=/\s/,s=this.session.tokenRe;s.lastIndex=0;if(t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{while((r=e[n])&&i.test(r))n++;if(n<=1){s.lastIndex=0;while((r=e[n])&&!s.test(r)){s.lastIndex=0,n++;if(i.test(r)){if(n>2){n--;break}while((r=e[n])&&i.test(r))n++;if(n>2)break}}}}return s.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e0&&/^\s*$/.test(r));t=r.length,/\s+$/.test(r)||(r="")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column);t===0&&(this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var r=this.session.screenToDocumentPosition(n.row+e,n.column);this.moveCursorTo(r.row,r.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e}}).call(u.prototype),t.Selection=u}),ace.define("ace/range",["require","exports","module"],function(e,t,n){var r=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row==e.start.row&&this.end.row==e.end.row&&this.start.column==e.start.column&&this.end.column==e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};if(this.start.row>t)var i={row:t+1,column:0};if(this.start.row1&&i[a].token.length!==f-1)throw new Error("For "+i[a].regex+" the matching groups ("+(f-1)+") and length of the token array ("+i[a].token.length+") don't match (rule #"+a+" of state "+n+")");u[o]={rule:a,len:f},o+=f,s.push(l)}this.regExps[n]=new RegExp("(?:("+s.join(")|(")+")|(.))",t)}};(function(){this.getLineTokens=function(e,t){var n=t||"start",r=this.rules[n],i=this.matchMappings[n],s=this.regExps[n];s.lastIndex=0;var o,u=[],a=0,f={type:null,value:""};while(o=s.exec(e)){var l="text",c=null,h=[o[0]];for(var p=0;p1&&(h=o.slice(p+2,p+1+i[p].len)),typeof c.token=="function"?l=c.token.apply(this,h):l=c.token;if(c.next){n=c.next,r=this.rules[n],i=this.matchMappings[n],a=s.lastIndex,s=this.regExps[n];if(s===undefined)throw new Error("You indicated a state of "+c.next+" to go to, but it doesn't exist!");s.lastIndex=a}break}if(h[0]){typeof l=="string"&&(h=[h.join("")],l=[l]);for(var p=0;p=t&&(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this.insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this.insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this.removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this.insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;ithis.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column;t.action==="insertText"?n.start.row===r&&n.start.column<=i?n.start.row===n.end.row?i+=n.end.column-n.start.column:(i-=n.start.column,r+=n.end.row-n.start.row):n.start.row!==n.end.row&&n.start.row=i?i=n.start.column:i=Math.max(0,i-(n.end.column-n.start.column)):n.start.row!==n.end.row&&n.start.row=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=5e3,o=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var n=this;this.$worker=function(){if(!n.running)return;var e=new Date,t=n.currentLine,r=n.doc,i=0,s=r.getLength();while(n.currentLine20){n.fireUpdateEvent(t,n.currentLine-1),n.running=setTimeout(n.$worker,20);return}}n.running=!1,n.fireUpdateEvent(t,s-1)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._emit("update",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.$updateOnChange=function(e){var t=e.range,n=t.start.row,r=t.end.row-n;if(r===0)this.lines[n]=null;else if(e.action=="removeText"||e.action=="removeLines")this.lines.splice(n,r+1,null),this.states.splice(n,r+1,null);else{var i=Array(r+1);i.unshift(n,1),this.lines.splice.apply(this.lines,i),this.states.splice.apply(this.states,i)}this.currentLine=Math.min(n,this.currentLine,this.doc.getLength()),this.stop(),this.running=setTimeout(this.$worker,700)},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1];if(t.length>s){var r={value:t.substr(s),type:"text"};t=t.slice(0,s)}var i=this.tokenizer.getLineTokens(t,n);return r&&(i.tokens.push(r),i.state="start"),this.states[e]!==i.state?(this.states[e]=i.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=i.tokens}}).call(o.prototype),t.BackgroundTokenizer=o}),ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+""==e+"")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:"");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i,null,this.type)}}}).call(o.prototype),t.SearchHighlight=o}),ace.define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"],function(e,t,n){function u(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if(!r)return null;var i=r.folds;for(var s=0;s=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i=t){u=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:o=new s(t,e),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u==f&&l-a<2)throw"The range has to be at least 2 characters width";var c=this.getFoldAt(u,a,1),h=this.getFoldAt(f,l,-1);if(c&&h==c)return c.addSubFold(o);if(c&&!c.range.isStart(u,a)||h&&!h.range.isEnd(f,l))throw"A fold can't intersect already existing fold"+o.range+c.range;var p=this.getFoldsInRange(o.range);p.length>0&&(this.removeFolds(p),o.subFolds=p);for(var d=0;dthis.endRow)throw"Can't add a fold to this FoldLine as it has no connection";this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw"Trying to add fold to FoldRow that doesn't have a matching row";this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f=this.$rowTokens.length){this.$row+=1;if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n}}).call(r.prototype),t.TokenIterator=r}),ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,n){function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n=="")return null;var r=n.match(/([\(\[\{])|([\)\]\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\(\[\{])|([\)\]\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\(\[\{])|([\)\]\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("rparen",".paren")+")+"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("lparen",".paren")+")+"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(aw&&o[c].end.row==n.end.row)c--;return o.slice(m,c+1)}return o},this.replace=function(e,t){var n=this.$options,r=this.$assembleRegExp(n);if(n.$isMultiLine)return t;if(!r)return;var i=r.exec(e);if(!i||i[0].length!=e.length)return null;t=e.replace(r,t);if(n.preserveCase){t=t.split("");for(var s=Math.min(e.length,e.length);s--;){var o=e[s];o&&o.toLowerCase()!=o?t[s]=t[s].toUpperCase():t[s]=t[s].toLowerCase()}t=t.join("")}return t},this.$matchIterator=function(e,t){var n=this.$assembleRegExp(t);if(!n)return!1;var i=this,o,u=t.backwards;if(t.$isMultiLine)var a=n.length,f=function(t,r,i){var u=t.search(n[0]);if(u==-1)return;for(var f=1;f=0;u--)if(o(s[u],t,i))return!0};else var f=function(e,t,i){var s=r.getMatchOffsets(e,n);for(var u=0;u=o;r--)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=u,o=s.row;r>=o;r--)if(n(e.getLine(r),r))return}:function(n){var r=s.row,i=e.getLine(r).substr(s.column);if(n(i,r,s.column))return;for(r+=1;r<=u;r++)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=o,u=s.row;r<=u;r++)if(n(e.getLine(r),r))return};return{forEach:a}}}).call(o.prototype),t.Search=o}),ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../keyboard/hash_handler").HashHandler,s=e("../lib/event_emitter").EventEmitter,o=function(e,t){this.platform=e,this.commands=this.byName={},this.commmandKeyBinding={},this.addCommands(t),this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){typeof e=="string"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;var r=this._emit("exec",{editor:t,command:e,args:n});return r===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t=="string"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!="string"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys"],function(e,t,n){function i(e,t){this.platform=t,this.commands={},this.commmandKeyBinding={},this.addCommands(e)}var r=e("../lib/keys");(function(){this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e){var t=typeof e=="string"?e:e.name;e=this.commands[t],delete this.commands[t];var n=this.commmandKeyBinding;for(var r in n)for(var i in n[r])n[r][i]==e&&delete n[r][i]},this.bindKey=function(e,t){if(!e)return;if(typeof t=="function"){this.addCommand({exec:t,bindKey:e,name:e});return}var n=this.commmandKeyBinding;e.split("|").forEach(function(e){var r=this.parseKeys(e,t),i=r.hashId;(n[i]||(n[i]={}))[r.key]=t},this)},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(typeof n=="string")return this.bindKey(n,t);typeof n=="function"&&(n={exec:n}),n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){var t=e.bindKey;if(!t)return;var n=typeof t=="string"?t:t[this.platform];this.bindKey(n,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]=="shift")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)throw"invalid modifier "+t[o]+" in "+e;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=this.commmandKeyBinding;return r[t]&&r[t][n]},this.handleKeyboard=function(e,t,n,r){return{command:this.findKeyCommand(t,n)}}}).call(i.prototype),t.HashHandler=i}),ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config"],function(e,t,n){function s(e,t){return{win:e,mac:t}}var r=e("../lib/lang"),i=e("../config");t.commands=[{name:"selectall",bindKey:s("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:s(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:s("Ctrl-L","Command-L"),exec:function(e){var t=parseInt(prompt("Enter line number:"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:s("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},readOnly:!0},{name:"unfold",bindKey:s("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},readOnly:!0},{name:"foldall",bindKey:s("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll()},readOnly:!0},{name:"unfoldall",bindKey:s("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},readOnly:!0},{name:"findnext",bindKey:s("Ctrl-K","Command-G"),exec:function(e){e.findNext()},readOnly:!0},{name:"findprevious",bindKey:s("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},readOnly:!0},{name:"find",bindKey:s("Ctrl-F","Command-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e)})},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:s("Ctrl-Shift-Home","Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0},{name:"gotostart",bindKey:s("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectup",bindKey:s("Shift-Up","Shift-Up"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",readOnly:!0},{name:"golineup",bindKey:s("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selecttoend",bindKey:s("Ctrl-Shift-End","Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoend",bindKey:s("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectdown",bindKey:s("Shift-Down","Shift-Down"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",readOnly:!0},{name:"golinedown",bindKey:s("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordleft",bindKey:s("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordleft",bindKey:s("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolinestart",bindKey:s("Alt-Shift-Left","Command-Shift-Left"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolinestart",bindKey:s("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectleft",bindKey:s("Shift-Left","Shift-Left"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoleft",bindKey:s("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordright",bindKey:s("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordright",bindKey:s("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolineend",bindKey:s("Alt-Shift-Right","Command-Shift-Right"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolineend",bindKey:s("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectright",bindKey:s("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoright",bindKey:s("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:s(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:s("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:s(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:s("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:s("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"togglerecording",bindKey:s("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:s("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:s("Ctrl-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttomatching",bindKey:s("Ctrl-Shift-P",null),exec:function(e){e.jumpToMatching(!0)},readOnly:!0},{name:"cut",exec:function(e){var t=e.getSelectionRange();e._emit("cut",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},multiSelectAction:"forEach"},{name:"removeline",bindKey:s("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},multiSelectAction:"forEach"},{name:"duplicateSelection",bindKey:s("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},multiSelectAction:"forEach"},{name:"sortlines",bindKey:s("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},multiSelectAction:"forEach"},{name:"togglecomment",bindKey:s("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEach"},{name:"modifyNumberUp",bindKey:s("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:s("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},multiSelectAction:"forEach"},{name:"replace",bindKey:s("Ctrl-H","Command-Option-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e,!0)})}},{name:"undo",bindKey:s("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:s("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:s("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()}},{name:"movelinesup",bindKey:s("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()}},{name:"copylinesdown",bindKey:s("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()}},{name:"movelinesdown",bindKey:s("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()}},{name:"del",bindKey:s("Delete","Delete|Ctrl-D"),exec:function(e){e.remove("right")},multiSelectAction:"forEach"},{name:"backspace",bindKey:s("Command-Backspace|Option-Backspace|Shift-Backspace|Backspace","Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach"},{name:"removetolinestart",bindKey:s("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach"},{name:"removetolineend",bindKey:s("Alt-Delete","Ctrl-K"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach"},{name:"removewordleft",bindKey:s("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach"},{name:"removewordright",bindKey:s("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach"},{name:"outdent",bindKey:s("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach"},{name:"indent",bindKey:s("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach"},{name:"blockoutdent",bindKey:s("Ctrl-[","Ctrl-["),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach"},{name:"blockindent",bindKey:s("Ctrl-]","Ctrl-]"),exec:function(e){e.blockIndent()},multiSelectAction:"forEach"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach"},{name:"splitline",bindKey:s(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach"},{name:"transposeletters",bindKey:s("Ctrl-T","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)}},{name:"touppercase",bindKey:s("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach"},{name:"tolowercase",bindKey:s("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach"}]}),ace.define("ace/undomanager",["require","exports","module"],function(e,t,n){var r=function(){this.reset()};(function(){this.execute=function(e){var t=e.args[0];this.$doc=e.args[1],this.$undoStack.push(t),this.$redoStack=[]},this.undo=function(e){var t=this.$undoStack.pop(),n=null;return t&&(n=this.$doc.undoChanges(t,e),this.$redoStack.push(t)),n},this.redo=function(e){var t=this.$redoStack.pop(),n=null;return t&&(n=this.$doc.redoChanges(t,e),this.$undoStack.push(t)),n},this.reset=function(){this.$undoStack=[],this.$redoStack=[]},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0}}).call(r.prototype),t.UndoManager=r}),ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/useragent","ace/config","ace/lib/net","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/renderloop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/useragent"),u=e("./config"),a=e("./lib/net"),f=e("./layer/gutter").Gutter,l=e("./layer/marker").Marker,c=e("./layer/text").Text,h=e("./layer/cursor").Cursor,p=e("./scrollbar").ScrollBar,d=e("./renderloop").RenderLoop,v=e("./lib/event_emitter").EventEmitter,m=".ace_editor {position: relative;overflow: hidden;font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;}.ace_content {position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: text;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTQ4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTU4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBMjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBMzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkgXxbAAAAJbSURBVHjapFNNaBNBFH4zs5vdZLP5sQmNpT82QY209heh1ioWisaDRcSKF0WKJ0GQnrzrxasHsR6EnlrwD0TagxJabaVEpFYxLWlLSS822tr87m66ccfd2GKyVhA6MMybgfe97/vmPUQphd0sZjto9XIn9OOsvlu2nkqRzVU+6vvlzPf8W6bk8dxQ0NPbxAALgCgg2JkaQuhzQau/El0zbmUA7U0Es8v2CiYmKQJHGO1QICCLoqilMhkmurDAyapKgqItezi/USRdJqEYY4D5jCy03ht2yMkkvL91jTTX10qzyyu2hruPRN7jgbH+EOsXcMLgYiThEgAMhABW85oqy1DXdRIdvP1AHJ2acQXvDIrVHcdQNrEKNYSVMSZGMjEzIIAwDXIo+6G/FxcGnzkC3T2oMhLjre49sBB+RRcHLqdafK6sYdE/GGBwU1VpFNj0aN8pJbe+BkZyevUrvLl6Xmm0W9IuTc0DxrDNAJd5oEvI/KRsNC3bQyNjPO9yQ1YHcfj2QvfQc/5TUhJTBc2iM0U7AWDQtc1nJHvD/cfO2s7jaGkiTEfa/Ep8coLu7zmNmh8+dc5lZDuUeFAGUNA/OY6JVaypQ0vjr7XYjUvJM37vt+j1vuTK5DgVfVUoTjVe+y3/LxMxY2GgU+CSLy4cpfsYorRXuXIOi0Vt40h67uZFTdIo6nLaZcwUJWAzwNS0tBnqqKzQDnjdG/iPyZxo46HaKUpbvYkj8qYRTZsBhge+JHhZyh0x9b95JqjVJkT084kZIPwu/mPWqPgfQ5jXh2+92Ay7HedfAgwA6KDWafb4w3cAAAAASUVORK5CYII=\");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTg4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTk4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBNjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBNzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pgd7PfIAAAGmSURBVHjaYvr//z8DJZiJgUIANoCRkREb9gLiSVAaQx4OQM7AAkwd7XU2/v++/rOttdYGEB9dASEvOMydGKfH8Gv/p4XTkvRBfLxeQAP+1cUhXopyvzhP7P/IoSj7g7Mw09cNKO6J1QQ0L4gICPIv/veg/8W+JdFvQNLHVsW9/nmn9zk7B+cCkDwhL7gt6knSZnx9/LuCEOcvkIAMP+cvto9nfqyZmmUAksfnBUtbM60gX/3/kgyv3/xSFOL5DZT+L8vP+Yfh5cvfPvp/xUHyQHXGyAYwgpwBjZYFT3Y1OEl/OfCH4ffv3wzc4iwMvNIsDJ+f/mH4+vIPAxsb631WW0Yln6ZpQLXdMK/DXGDflh+sIv37EivD5x//Gb7+YWT4y86sl7BCCkSD+Z++/1dkvsFRl+HnD1Rvje4F8whjMXmGj58YGf5zsDMwcnAwfPvKcml62DsQDeaDxN+/Y0qwlpEHqrdB94IRNIDUgfgfKJChGK4OikEW3gTiXUB950ASLFAF54AC94A0G9QAfOnmF9DCDzABFqS08IHYDIScdijOjQABBgC+/9awBH96jwAAAABJRU5ErkJggg==\");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRTk5MTVGREIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRTk5MTVGRUIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZFOTkxNUZCQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFOTkxNUZDQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SIDkjAAAAJ1JREFUeNpi/P//PwMlgImBQkB7A6qrq/+DMC55FkIGKCoq4pVnpFkgTp069f/+/fv/r1u37r+tre1/kg0A+ptn9uzZYLaRkRHpLvjw4cNXWVlZhufPnzOcO3eOdAO0tbVPAjHDmzdvGA4fPsxIsgGSkpJmv379Ynj37h2DjIyMCMkG3LhxQ/T27dsMampqDHZ2dq/pH41DxwCAAAMAFdc68dUsFZgAAAAASUVORK5CYII=\");}.ace_scrollbar {position: absolute;overflow-x: hidden;overflow-y: scroll;right: 0;top: 0;bottom: 0;}.ace_scrollbar-inner {position: absolute;width: 1px;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;}.ace_text-input.ace_composition {background: #f8f8f8;color: #111;z-index: 1000;opacity: 1;border: solid lightgray 1px;margin: -1px;padding: 0 1px;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;white-space: nowrap;height: 100%;width: 100%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;/* setting pointer-events: auto; on node under the mouse, which changesduring scroll, will break mouse wheel scrolling in Safari */pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;}.ace_text-layer {color: black;font: inherit !important;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {-moz-transition: opacity 0.18s;-webkit-transition: opacity 0.18s;-o-transition: opacity 0.18s;-ms-transition: opacity 0.18s;transition: opacity 0.18s;}.ace_cursor[style*=\"opacity: 0\"]{-ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\";}.ace_editor.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_line {white-space: nowrap;}.ace_marker-layer .ace_step {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_line .ace_fold {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;-moz-border-radius: 2px;-webkit-border-radius: 2px;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;}.ace_editor.ace_dragging .ace_content {cursor: move;}.ace_gutter-tooltip {background-color: #FFF;background-image: -webkit-linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;display: inline-block;max-width: 500px;padding: 4px;position: fixed;z-index: 300;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: default;white-space: pre-line;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: inline-block;width: 11px;vertical-align: top;background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;}.ace_fold-widget.ace_end {background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");}.ace_fold-widget.ace_closed {background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}/*** Dark version for fold widgets*/.ace_dark .ace_fold-widget {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");}.ace_dark .ace_fold-widget.ace_end {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget.ace_closed {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-moz-transition: opacity 0.4s ease 0.05s;-webkit-transition: opacity 0.4s ease 0.05s;-o-transition: opacity 0.4s ease 0.05s;-ms-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-moz-transition: opacity 0.05s ease 0.05s;-webkit-transition: opacity 0.05s ease 0.05s;-o-transition: opacity 0.05s ease 0.05s;-ms-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}";i.importCssString(m,"ace_editor");var g=function(e,t){var n=this;this.container=e||i.createElement("div"),this.$keepTextAreaAtCursor=!o.isIE,i.addCssClass(this.container,"ace_editor"),this.setTheme(t),this.$gutter=i.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=i.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=i.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.setHighlightGutterLine(!0),this.$gutterLayer=new f(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new l(this.content);var r=this.$textLayer=new c(this.content);this.canvas=r.element,this.$markerFront=new l(this.content),this.$cursorLayer=new h(this.content),this.$horizScroll=!1,this.$horizScrollAlwaysVisible=!1,this.$animatedScroll=!1,this.scrollBar=new p(this.container),this.scrollBar.addEventListener("scroll",function(e){n.$inScrollAnimation||n.session.setScrollTop(e.data)}),this.scrollTop=0,this.scrollLeft=0,s.addListener(this.scroller,"scroll",function(){var e=n.scroller.scrollLeft;n.scrollLeft=e,n.session.setScrollLeft(e)}),this.cursorPos={row:0,column:0},this.$textLayer.addEventListener("changeCharacterSize",function(){n.updateCharacterSize(),n.onResize(!0)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:1,characterWidth:1,minHeight:1,maxHeight:1,offset:0,height:1},this.$loop=new d(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4)};(function(){this.showGutter=!0,this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.characterWidth=this.$textLayer.getCharacterWidth(),this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session=e,this.scroller.className="ace_scroller",this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e),this.$loop.schedule(this.CHANGE_FULL)},this.updateLines=function(e,t){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow||this.$changedLines.lastRow2)return;this.resizing>1?this.resizing++:this.resizing=e?1:0,r||(r=i.getInnerHeight(this.container)),r&&(e||o.height!=r)&&(o.height=r,o.scrollerHeight=this.scroller.clientHeight,this.scrollBar.setHeight(o.scrollerHeight),this.session&&(this.session.setScrollTop(this.getScrollTop()),s|=this.CHANGE_FULL)),n||(n=i.getInnerWidth(this.container));if(n&&(e||this.resizing>1||o.width!=n)){o.width=n;var t=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=t+"px",o.scrollerWidth=Math.max(0,n-t-this.scrollBar.getWidth()),this.scroller.style.right=this.scrollBar.getWidth()+"px";if(this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)s|=this.CHANGE_FULL}e?this.$renderChanges(s,!0):this.$loop.schedule(s),e&&delete this.resizing},this.onGutterResize=function(){var e=this.$size.width,t=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=t+"px",this.$size.scrollerWidth=Math.max(0,e-t-this.scrollBar.getWidth()),this.session.getUseWrapMode()&&this.adjustWrapLimit()&&this.$loop.schedule(this.CHANGE_FULL)},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t)},this.setAnimatedScroll=function(e){this.$animatedScroll=e},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},this.getShowInvisibles=function(){return this.$textLayer.showInvisibles},this.getDisplayIndentGuides=function(){return this.$textLayer.displayIndentGuides},this.setDisplayIndentGuides=function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},this.$showPrintMargin=!0,this.setShowPrintMargin=function(e){this.$showPrintMargin=e,this.$updatePrintMargin()},this.getShowPrintMargin=function(){return this.$showPrintMargin},this.$printMarginColumn=80,this.setPrintMarginColumn=function(e){this.$printMarginColumn=e,this.$updatePrintMargin()},this.getPrintMarginColumn=function(){return this.$printMarginColumn},this.getShowGutter=function(){return this.showGutter},this.setShowGutter=function(e){if(this.showGutter===e)return;this.$gutter.style.display=e?"block":"none",this.showGutter=e,this.onResize(!0)},this.getFadeFoldWidgets=function(){return i.hasCssClass(this.$gutter,"ace_fade-fold-widgets")},this.setFadeFoldWidgets=function(e){e?i.addCssClass(this.$gutter,"ace_fade-fold-widgets"):i.removeCssClass(this.$gutter,"ace_fade-fold-widgets")},this.$highlightGutterLine=!1,this.setHighlightGutterLine=function(e){if(this.$highlightGutterLine==e)return;this.$highlightGutterLine=e;if(!this.$gutterLineHighlight){this.$gutterLineHighlight=i.createElement("div"),this.$gutterLineHighlight.className="ace_gutter-active-line",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=e?"":"none",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$updateGutterLineHighlight=function(){this.$gutterLineHighlight.style.top=this.$cursorLayer.$pixelPos.top-this.layerConfig.offset+"px",this.$gutterLineHighlight.style.height=this.layerConfig.lineHeight+"px"},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=i.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",t.visibility=this.$showPrintMargin?"visible":"hidden"},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.content},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,n=this.$cursorLayer.$pixelPos.left;t-=e.offset;if(t<0||t>e.height-this.lineHeight)return;var r=this.characterWidth;if(this.$composition){var i=this.textarea.value.replace(/^\x01+/,"");r*=this.session.$getStringScreenWidth(i)[0]}n-=this.scrollLeft,n>this.$size.scrollerWidth-r&&(n=this.$size.scrollerWidth-r),n-=this.scrollBar.width,this.textarea.style.height=this.lineHeight+"px",this.textarea.style.width=r+"px",this.textarea.style.right=this.$size.scrollerWidth-n-r+"px",this.textarea.style.bottom=this.$size.height-t-this.lineHeight+"px"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+e},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.getHScrollBarAlwaysVisible=function(){return this.$horizScrollAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.$horizScrollAlwaysVisible!=e&&(this.$horizScrollAlwaysVisible=e,(!this.$horizScrollAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL))},this.$updateScrollBar=function(){this.scrollBar.setInnerHeight(this.layerConfig.maxHeight),this.scrollBar.setScrollTop(this.scrollTop)},this.$renderChanges=function(e,t){if(!t&&(!e||!this.session||!this.container.offsetWidth))return;(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL)&&this.$computeLayerConfig();if(e&this.CHANGE_H_SCROLL){this.scroller.scrollLeft=this.scrollLeft;var n=this.scroller.scrollLeft;this.scrollLeft=n,this.session.setScrollLeft(n),this.scroller.className=this.scrollLeft==0?"ace_scroller":"ace_scroller ace_scroll-left"}if(e&this.CHANGE_FULL){this.$textLayer.checkForSizeChanges(),this.$updateScrollBar(),this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}if(e&this.CHANGE_SCROLL){this.$updateScrollBar(),e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(this.layerConfig):this.$textLayer.scrollLines(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}e&this.CHANGE_TEXT?(this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.showGutter)&&this.$gutterLayer.update(this.layerConfig):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.showGutter&&this.$gutterLayer.update(this.layerConfig),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(this.layerConfig),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(this.layerConfig),e&this.CHANGE_SIZE&&this.$updateScrollBar()},this.$computeLayerConfig=function(){var e=this.session,t=this.scrollTop%this.lineHeight,n=this.$size.scrollerHeight+this.lineHeight,r=this.$getLongestLine(),i=this.$horizScrollAlwaysVisible||this.$size.scrollerWidth-r<0,s=this.$horizScroll!==i;this.$horizScroll=i,s&&(this.scroller.style.overflowX=i?"scroll":"hidden",i||this.session.setScrollLeft(0));var o=this.session.getScreenLength()*this.lineHeight;this.session.setScrollTop(Math.max(0,Math.min(this.scrollTop,o-this.$size.scrollerHeight)));var u=Math.ceil(n/this.lineHeight)-1,a=Math.max(0,Math.round((this.scrollTop-t)/this.lineHeight)),f=a+u,l,c,h=this.lineHeight;a=e.screenToDocumentRow(a,0);var p=e.getFoldLine(a);p&&(a=p.start.row),l=e.documentToScreenRow(a,0),c=e.getRowLength(a)*h,f=Math.min(e.screenToDocumentRow(f,0),e.getLength()-1),n=this.$size.scrollerHeight+e.getRowLength(f)*h+c,t=this.scrollTop-l*h,this.layerConfig={width:r,padding:this.$padding,firstRow:a,firstRowScreen:l,lastRow:f,lineHeight:h,characterWidth:this.characterWidth,minHeight:n,maxHeight:o,offset:t,height:this.$size.scrollerHeight},this.$gutterLayer.element.style.marginTop=-t+"px",this.content.style.marginTop=-t+"px",this.content.style.width=r+2*this.$padding+"px",this.content.style.height=n+"px",s&&this.onResize(!0)},this.$updateLines=function(){var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(ti?(t&&(i-=t*this.$size.scrollerHeight),this.session.setScrollTop(i)):this.scrollTop+this.$size.scrollerHeightr?(r0)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight0?1:-1}},this.screenToTextCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=Math.round((e+this.scrollLeft-n.left-this.$padding)/this.characterWidth),i=Math.floor((t+this.scrollTop-n.top)/this.lineHeight);return this.session.screenToDocumentPosition(i,Math.max(r,0))},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+Math.round(r.column*this.characterWidth),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){i.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;i.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this._loadTheme=function(e,t){},this.setTheme=function(e){function r(e){i.importCssString(e.cssText,e.cssClass,t.container.ownerDocument),t.theme&&i.removeCssClass(t.container,t.theme.cssClass),t.$theme=e.cssClass,t.theme=e,i.addCssClass(t.container,e.cssClass),i.setCssClass(t.container,"ace_dark",e.isDark);var n=e.padding||4;t.$padding&&n!=t.$padding&&t.setPadding(n),t.$size&&(t.$size.width=0,t.onResize()),t._dispatchEvent("themeLoaded",{theme:e})}var t=this;this.$themeValue=e,t._dispatchEvent("themeChange",{theme:e});if(!e||typeof e=="string"){var n=e||"ace/theme/textmate";u.loadModule(["theme",n],r)}else r(e)},this.getTheme=function(){return this.$themeValue},this.setStyle=function(t,n){i.setCssClass(this.container,t,n!=0)},this.unsetStyle=function(t){i.removeCssClass(this.container,t)},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(g.prototype),t.VirtualRenderer=g}),ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/lang"),o=e("../lib/event_emitter").EventEmitter,u=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_gutter-layer",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this)};(function(){i.implement(this,o),this.setSession=function(e){this.session&&this.session.removeEventListener("change",this.$updateAnnotations),this.session=e,e.on("change",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.addGutterDecoration"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.removeGutterDecoration"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];var t,n;for(var r=0;ru&&(i=o.end.row+1,o=this.session.getNextFoldLine(i,o),u=o?o.start.row:Infinity);if(i>s)break;var h=this.$annotations[i]||t;n.push("
    ",c=i+1);if(a){var p=a[i];p==null&&(p=a[i]=this.session.getFoldWidget(i)),p&&n.push("")}n.push("
    "),i++}this.element=r.setInnerHtml(this.element,n.join("")),this.element.style.height=e.minHeight+"px",this.session.$useWrapMode&&(c=this.session.getLength());var d=(""+c).length*e.characterWidth,v=this.$padding||this.$computePadding();d+=v.left+v.right,d!==this.gutterWidth&&(this.gutterWidth=d,this.element.style.width=Math.ceil(this.gutterWidth)+"px",this._emit("changeGutterWidth",d))},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(e){e?r.addCssClass(this.element,"ace_folding-enabled"):r.removeCssClass(this.element,"ace_folding-enabled"),this.$showFoldWidgets=e,this.$padding=null},this.getShowFoldWidgets=function(){return this.$showFoldWidgets},this.$computePadding=function(){if(!this.element.firstChild)return{left:0,right:0};var e=r.computedStyle(this.element.firstChild);return this.$padding={},this.$padding.left=parseInt(e.paddingLeft)+1,this.$padding.right=parseInt(e.paddingRight),this.$padding},this.getRegion=function(e){var t=this.$padding||this.$computePadding(),n=this.element.getBoundingClientRect();if(e.xn.right-t.right)return"foldWidgets"}}).call(u.prototype),t.Gutter=u}),ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,n){var r=e("../range").Range,i=e("../lib/dom"),s=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){var e=e||this.config;if(!e)return;this.config=e;var t=[];for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var s=r.range.clipRows(e.firstRow,e.lastRow);if(s.isEmpty())continue;s=s.toScreenRange(this.session);if(r.renderer){var o=this.$getTop(s.start.row,e),u=this.$padding+s.start.column*e.characterWidth;r.renderer(t,s,u,o,e)}else r.type=="fullLine"?this.drawFullLineMarker(t,s,r.clazz,e):s.isMultiLine()?r.type=="text"?this.drawTextMarker(t,s,r.clazz,e):this.drawMultiLineMarker(t,s,r.clazz,e):this.drawSingleLineMarker(t,s,r.clazz+" ace_start",e)}this.element=i.setInnerHtml(this.element,t.join(""))},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(e,t,n,i){var s=t.start.row,o=new r(s,t.start.column,s,this.session.getScreenLastRowColumn(s));this.drawSingleLineMarker(e,o,n+" ace_start",i,1,"text"),s=t.end.row,o=new r(s,0,s,t.end.column),this.drawSingleLineMarker(e,o,n,i,0,"text");for(s=t.start.row+1;s
    "),u=this.$getTop(t.end.row,r);var f=t.end.column*r.characterWidth;e.push("
    "),o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<0)return;u=this.$getTop(t.start.row+1,r),e.push("
    ")},this.drawSingleLineMarker=function(e,t,n,r,i){var s=r.lineHeight,o=(t.end.column+(i||0)-t.start.column)*r.characterWidth,u=this.$getTop(t.start.row,r),a=this.$padding+t.start.column*r.characterWidth;e.push("
    ")},this.drawFullLineMarker=function(e,t,n,r){var i=this.$getTop(t.start.row,r),s=r.lineHeight;t.start.row!=t.end.row&&(s+=this.$getTop(t.end.row,r)-i),e.push("
    ")}}).call(s.prototype),t.Marker=s}),ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/useragent"),u=e("../lib/event_emitter").EventEmitter,a=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$characterSize={width:0,height:0},this.checkForSizeChanges(),this.$pollSizeChanges()};(function(){r.implement(this,u),this.EOF_CHAR="¶",this.EOL_CHAR="¬",this.TAB_CHAR="→",this.SPACE_CHAR="·",this.$padding=0,this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$characterSize.height||1},this.getCharacterWidth=function(){return this.$characterSize.width||1},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$pollSizeChanges=function(){var e=this;this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.$fontStyles={fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},this.$measureSizes=o.isIE||o.isOldGecko?function(){var e=1e3;if(!this.$measureNode){var t=this.$measureNode=i.createElement("div"),n=t.style;n.width=n.height="auto",n.left=n.top=-e*40+"px",n.visibility="hidden",n.position="fixed",n.overflow="visible",n.whiteSpace="nowrap",t.innerHTML=s.stringRepeat("Xy",e);if(this.element.ownerDocument.body)this.element.ownerDocument.body.appendChild(t);else{var r=this.element.parentNode;while(!i.hasCssClass(r,"ace_editor"))r=r.parentNode;r.appendChild(t)}}if(!this.element.offsetWidth)return null;var n=this.$measureNode.style,o=i.computedStyle(this.element);for(var u in this.$fontStyles)n[u]=o[u];var a={height:this.$measureNode.offsetHeight,width:this.$measureNode.offsetWidth/(e*2)};return a.width==0||a.height==0?null:a}:function(){if(!this.$measureNode){var e=this.$measureNode=i.createElement("div"),t=e.style;t.width=t.height="auto",t.left=t.top="-100px",t.visibility="hidden",t.position="fixed",t.overflow="visible",t.whiteSpace="nowrap",e.innerHTML="X";var n=this.element.parentNode;while(n&&!i.hasCssClass(n,"ace_editor"))n=n.parentNode;if(!n)return this.$measureNode=null;n.appendChild(e)}var r=this.$measureNode.getBoundingClientRect(),s={height:r.height,width:r.width};return s.width==0||s.height==0?null:s},this.setSession=function(e){this.session=e,this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n"+this.TAB_CHAR+s.stringRepeat(" ",n-1)+""):t.push(s.stringRepeat(" ",n));if(this.displayIndentGuides){this.$indentGuideRe=/\s\S| \t|\t |\s$/;var r="ace_indent-guide";if(this.showInvisibles){r+=" ace_invisible";var i=s.stringRepeat(this.SPACE_CHAR,this.tabSize),o=this.TAB_CHAR+s.stringRepeat(" ",this.tabSize-1)}else var i=s.stringRepeat(" ",this.tabSize),o=i;this.$tabStrings[" "]=""+i+"",this.$tabStrings[" "]=""+o+""}},this.updateLines=function(e,t,n){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;var r=Math.max(t,e.firstRow),s=Math.min(n,e.lastRow),o=this.element.childNodes,u=0;for(var a=e.firstRow;al&&(a=f.end.row+1,f=this.session.getNextFoldLine(a,f),l=f?f.start.row:Infinity);if(a>s)break;var c=o[u++];if(c){var h=[];this.$renderLine(h,a,!this.$useLineGroups(),a==l?f:!1),i.setInnerHtml(c,h.join(""))}a++}},this.scrollLines=function(e){var t=this.config;this.config=e;if(!t||t.lastRow0;r--)n.removeChild(n.firstChild);if(t.lastRow>e.lastRow)for(var r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);r>0;r--)n.removeChild(n.lastChild);if(e.firstRowt.lastRow){var i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);n.appendChild(i)}},this.$renderLinesFragment=function(e,t,n){var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=i.createElement("div"),f=[];this.$renderLine(f,s,!1,s==u?o:!1),a.innerHTML=f.join("");if(this.$useLineGroups())a.className="ace_line_group",r.appendChild(a);else{var l=a.childNodes;while(l.length)r.appendChild(l[0])}s++}return r},this.update=function(e){this.config=e;var t=[],n=e.firstRow,r=e.lastRow,s=n,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>r)break;this.$useLineGroups()&&t.push("
    "),this.$renderLine(t,s,!1,s==u?o:!1),this.$useLineGroups()&&t.push("
    "),s++}this.element=i.setInnerHtml(this.element,t.join(""))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var i=this,o=/\t|&|<|( +)|([\x00-\x1f\x80-\xa0\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g,u=function(e,n,r,o,u){if(n)return i.showInvisibles?""+s.stringRepeat(i.SPACE_CHAR,e.length)+"":s.stringRepeat(" ",e.length);if(e=="&")return"&";if(e=="<")return"<";if(e==" "){var a=i.session.getScreenTabSize(t+o);return t+=a-1,i.$tabStrings[a]}if(e==" "){var f=i.showInvisibles?"ace_cjk ace_invisible":"ace_cjk",l=i.showInvisibles?i.SPACE_CHAR:"";return t+=1,""+l+""}return r?""+i.SPACE_CHAR+"":(t+=1,""+e+"")},a=r.replace(o,u);if(!this.$textToken[n.type]){var f="ace_"+n.type.replace(/\./g," ace_"),l="";n.type=="fold"&&(l=" style='width:"+n.value.length*this.config.characterWidth+"px;' "),e.push("",a,"")}else e.push(a);return t+r.length},this.renderIndentGuide=function(e,t){var n=t.search(this.$indentGuideRe);return n<=0?t:t[0]==" "?(n-=n%this.tabSize,e.push(s.stringRepeat(this.$tabStrings[" "],n/this.tabSize)),t.substr(n)):t[0]==" "?(e.push(s.stringRepeat(this.$tabStrings[" "],n)),t.substr(n)):t},this.$renderWrappedLine=function(e,t,n,r){var i=0,s=0,o=n[0],u=0;for(var a=0;a=o)u=this.$renderToken(e,u,f,l.substring(0,o-i)),l=l.substring(o-i),i=o,r||e.push("
    ","
    "),s++,u=0,o=n[s]||Number.MAX_VALUE;l.length!=0&&(i+=l.length,u=this.$renderToken(e,u,f,l))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;s");if(i.length){var s=this.session.getRowSplitData(t);s&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)}this.showInvisibles&&(r&&(t=r.end.row),e.push("",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"")),n||e.push("
    ")},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.lengthn-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(sn?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:"fold",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,n){var r=e("../lib/dom"),i=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors")};(function(){this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&(this.smoothBlinking=e,e?r.addCssClass(this.element,"ace_smooth-blinking"):r.removeCssClass(this.element,"ace_smooth-blinking"),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking");for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity="";if(!this.isBlinking||!this.blinkInterval||!this.isVisible)return;this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity=0}.bind(this),.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity="";t()}.bind(this),this.blinkInterval),t()},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+n.column*this.config.characterWidth,i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,r=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=t.length;n--;){var i=this.getPixelPosition(t[n].cursor,!0);if((i.top>e.height+e.offset||i.top<-e.offset)&&n>1)continue;var s=(this.cursors[r++]||this.addCursor()).style;s.left=i.left+"px",s.top=i.top+"px",s.width=e.characterWidth+"px",s.height=e.lineHeight+"px"}while(this.cursors.length>r)this.removeCursor();var o=this.session.getOverwrite();this.$setOverwrite(o),this.$pixelPos=i,this.restartTimer()},this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(i.prototype),t.Cursor=i}),ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/event_emitter").EventEmitter,u=function(e){this.element=i.createElement("div"),this.element.className="ace_scrollbar",this.inner=i.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.width=i.scrollbarWidth(e.ownerDocument),this.element.style.width=(this.width||15)+5+"px",s.addListener(this.element,"scroll",this.onScroll.bind(this))};(function(){r.implement(this,o),this.onScroll=function(){this.skipEvent||(this.scrollTop=this.element.scrollTop,this._emit("scroll",{data:this.scrollTop})),this.skipEvent=!1},this.getWidth=function(){return this.width},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=function(e){this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=this.element.scrollTop=e)}}).call(u.prototype),t.ScrollBar=u}),ace.define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,n){var r=e("./lib/event"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){this.changes=this.changes|e;if(!this.pending){this.pending=!0;var t=this;r.nextFrame(function(){t.pending=!1;var e;while(e=t.changes)t.changes=0,t.onRender(e)},this.window)}}}).call(i.prototype),t.RenderLoop=i}),ace.define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor"],function(e,t,n){function h(e,t,n){return c.$options.wrap=!0,c.$options.needle=t,c.$options.backwards=n==-1,c.find(e)}function v(e,t){return e.row==t.row&&e.column==t.column}function m(e){e.$onAddRange=e.$onAddRange.bind(e),e.$onRemoveRange=e.$onRemoveRange.bind(e),e.$onMultiSelect=e.$onMultiSelect.bind(e),e.$onSingleSelect=e.$onSingleSelect.bind(e),t.onSessionChange.call(e,e),e.on("changeSession",t.onSessionChange.bind(e)),e.on("mousedown",o),e.commands.addCommands(f.defaultCommands),g(e)}function g(e){function i(){n&&(r.style.cursor="",n=!1)}var t=e.textInput.getElement(),n=!1,r=e.renderer.content;u.addListener(t,"keydown",function(e){e.keyCode==18&&!(e.ctrlKey||e.shiftKey||e.metaKey)?n||(r.style.cursor="crosshair",n=!0):n&&(r.style.cursor="")}),u.addListener(t,"keyup",i),u.addListener(t,"blur",i)}var r=e("./range_list").RangeList,i=e("./range").Range,s=e("./selection").Selection,o=e("./mouse/multi_select_handler").onMouseDown,u=e("./lib/event"),a=e("./lib/lang"),f=e("./commands/multi_select_commands");t.commands=f.defaultCommands.concat(f.multiSelectCommands);var l=e("./search").Search,c=new l,p=e("./edit_session").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(p.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(e,t){if(!e)return;if(!this.inMultiSelectMode&&this.rangeCount==0){var n=this.toOrientedRange();if(e.intersects(n))return t||this.fromOrientedRange(e);this.rangeList.add(n),this.$onAddRange(n)}e.cursor||(e.cursor=e.end);var r=this.rangeList.add(e);return this.$onAddRange(e),r.length&&this.$onRemoveRange(r),this.rangeCount>1&&!this.inMultiSelectMode&&(this._emit("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._emit("addRange",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._emit("removeRange",{ranges:e}),this.rangeCount==0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._emit("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeList.ranges.concat()},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.selectionLead),s=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column0)d--;if(d>0){var m=0;while(r[m].isEmpty())m++}for(var g=d;g>=m;g--)r[g].isEmpty()&&r.splice(g,1)}return r}}.call(s.prototype);var d=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.on("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeEventListener("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;t.multiSelectAction?t.multiSelectAction=="forEach"?n.forEachSelection(t,e.args):t.multiSelectAction=="single"?(n.exitMultiSelectMode(),t.exec(n,e.args||{})):t.multiSelectAction(n,e.args||{}):(t.exec(n,e.args||{}),n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()),e.preventDefault()},this.forEachSelection=function(e,t){if(this.inVirtualSelectionMode)return;var n=this.session,r=this.selection,i=r.rangeList,o=r._eventRegistry;r._eventRegistry={};var u=new s(n);this.inVirtualSelectionMode=!0;for(var a=i.ranges.length;a--;)u.fromOrientedRange(i.ranges[a]),this.selection=n.selection=u,e.exec(this,t||{}),u.toOrientedRange(i.ranges[a]);u.detach(),this.selection=n.selection=r,this.inVirtualSelectionMode=!1,r._eventRegistry=o,r.mergeOverlappingRanges(),this.onCursorChange(),this.onSelectionChange()},this.exitMultiSelectMode=function(){if(this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getCopyText=function(){var e="";if(this.inMultiSelectMode){var t=this.multiSelect.rangeList.ranges;e=[];for(var n=0;nn.length||t.length<=2||!t[1])return this.commands.exec("insertstring",this,e);for(var r=n.length;r--;){var i=n[r];i.isEmpty()||this.session.remove(i),this.session.insert(i.start,t[r])}},this.findAll=function(e,t,n){t=t||{},t.needle=e||t.needle,this.$search.set(t);var r=this.$search.findAll(this.session);if(!r.length)return 0;this.$blockScrolling+=1;var i=this.multiSelect;n||i.toSingleRange(r[0]);for(var s=r.length;s--;)i.addRange(r[s],!0);return this.$blockScrolling-=1,r.length},this.selectMoreLines=function(e,t){var n=this.selection.toOrientedRange(),r=n.cursor==n.end,s=this.session.documentToScreenPosition(n.cursor);this.selection.$desiredColumn&&(s.column=this.selection.$desiredColumn);var o=this.session.screenToDocumentPosition(s.row+e,s.column);if(!n.isEmpty())var u=this.session.documentToScreenPosition(r?n.end:n.start),a=this.session.screenToDocumentPosition(u.row+e,u.column);else var a=o;if(r){var f=i.fromPoints(o,a);f.cursor=f.start}else{var f=i.fromPoints(a,o);f.cursor=f.end}f.desiredColumn=s.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(n);else if(t)var l=n.cursor;this.selection.addRange(f),l&&this.selection.substractPoint(l)},this.transposeSelections=function(e){var t=this.session,n=t.multiSelect,r=n.ranges;for(var i=r.length;i--;){var s=r[i];if(s.isEmpty()){var o=t.getWordRange(s.start.row,s.start.column);s.start.row=o.start.row,s.start.column=o.start.column,s.end.row=o.end.row,s.end.column=o.end.column}}n.mergeOverlappingRanges();var u=[];for(var i=r.length;i--;){var s=r[i];u.unshift(t.getTextRange(s))}e<0?u.unshift(u.pop()):u.push(u.shift());for(var i=r.length;i--;){var s=r[i],o=s.clone();t.replace(s,u[i]),s.start.row=o.start.row,s.start.column=o.start.column}},this.selectMore=function(e,t){var n=this.session,r=n.multiSelect,i=r.toOrientedRange();if(i.isEmpty()){var i=n.getWordRange(i.start.row,i.start.column);i.cursor=i.end,this.multiSelect.addRange(i)}var s=n.getTextRange(i),o=h(n,s,e);o&&(o.cursor=e==-1?o.start:o.end,this.multiSelect.addRange(o)),t&&this.multiSelect.substractPoint(i.cursor)},this.alignCursors=function(){var e=this.session,t=e.multiSelect,n=t.ranges;if(!n.length){var r=this.selection.getRange(),s=r.start.row,o=r.end.row,u=this.session.doc.removeLines(s,o);u=this.$reAlignText(u),this.session.doc.insertLines(s,u),r.start.column=0,r.end.column=u[u.length-1].length,this.selection.setRange(r)}else{var f=-1,l=n.filter(function(e){if(e.cursor.row==f)return!0;f=e.cursor.row});t.$onRemoveRange(l);var c=0,h=Infinity,p=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\S/g);return i==-1&&(i=0),n.column>c&&(c=n.column),io?e.insert(r,a.stringRepeat(" ",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=c,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e){function o(e){return a.stringRepeat(" ",e)}function u(e){return e[2]?o(r)+e[2]+o(i-e[2].length+s)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function f(e){return e[2]?o(r+i-e[2].length)+e[2]+o(s," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function l(e){return e[2]?o(r)+e[2]+o(s)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var t=!0,n=!0,r,i,s;return e.map(function(e){var o=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return o?r==null?(r=o[1].length,i=o[2].length,s=o[3].length,o):(r+i+s!=o[1].length+o[2].length+o[3].length&&(n=!1),r!=o[1].length&&(t=!1),r>o[1].length&&(r=o[1].length),io[3].length&&(s=o[3].length),o):[e]}).map(t?n?f:u:l)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t.multiSelect||(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t.multiSelect;var n=e.oldSession;n&&(n.multiSelect&&n.multiSelect.editor==this&&(n.multiSelect.editor=null),t.multiSelect.removeEventListener("addRange",this.$onAddRange),t.multiSelect.removeEventListener("removeRange",this.$onRemoveRange),t.multiSelect.removeEventListener("multiSelect",this.$onMultiSelect),t.multiSelect.removeEventListener("singleSelect",this.$onSingleSelect)),t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m}),ace.define("ace/range_list",["require","exports","module"],function(e,t,n){var r=function(){this.ranges=[]};(function(){this.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},this.pointIndex=function(e,t){var n=this.ranges;for(var r=t||0;r0)continue;return s==0?r:(s=this.comparePoints(e,i.start),s>=0?r:-r-1)}return-r-1},this.add=function(e){var t=this.pointIndex(e.start);t<0&&(t=-t-1);var n=this.pointIndex(e.end,t);return n<0?n=-n-1:n++,this.ranges.splice(t,n-t,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.call(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges,n=t[0],r;for(var i=1;i=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.rowi)break;c.start.row==i&&c.start.column>=n.column&&(c.start.column+=u,c.start.row+=o),c.end.row==i&&c.end.column>=n.column&&(c.end.column+=u,c.end.row+=o)}if(o!=0&&f=0?i=e.nameToUrl("ace/worker/worker_sourcemint"):(e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl),i=o(e.toUrl("ace/worker/worker",null,"_")));var u={};t.forEach(function(t){u[t]=o(e.toUrl(t,null,"_").replace(/.js(\?.*)?$/,""))})}this.$worker=new Worker(i),this.$worker.postMessage({init:!0,tlns:u,module:n,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onerror=this.onError,this.$worker.onmessage=this.onMessage};(function(){r.implement(this,i),this.onError=function(e){throw window.console&&console.log&&console.log(e),e},this.onMessage=function(e){var t=e.data;switch(t.type){case"log":window.console&&console.log&&console.log.apply(console,t.data);break;case"event":this._emit(t.name,{data:t.data});break;case"call":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id])}},this.$normalizePath=function(e){return location.host?(e=e.replace(/^[a-z]+:\/\/[^\/]+/,""),e=location.protocol+"//"+location.host+(e.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+e.replace(/^[\/]+/,""),e):e},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call("setValue",[e.getValue()]),e.on("change",this.changeListener)},this.changeListener=function(e){e.range={start:e.data.range.start,end:e.data.range.end},this.emit("change",e)}}).call(o.prototype);var u=function(t,n,r){this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var s=null,o=Object.create(i),u=this;this.$worker={},this.$worker.postMessage=function(e){u.messageBuffer.push(e),s&&setTimeout(a)};var a=function(){var e=u.messageBuffer.shift();e.command?s[e.command].apply(s,e.args):e.event&&o._emit(e.event,e.data)};o.postMessage=function(e){u.onMessage({data:e})},o.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},o.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},e([n],function(e){s=new e[r](o);while(u.messageBuffer.length)a()})};u.prototype=o.prototype,t.UIWorkerClient=u,t.WorkerClient=o}),ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,n){var r=e("./range").Range,i=e("./lib/event_emitter").EventEmitter,s=e("./lib/oop"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session,i=this.$pos;this.pos=t.createAnchor(i.row,i.column),this.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.pos.on("change",function(t){n.removeMarker(e.markerId),e.markerId=n.addMarker(new r(t.value.row,t.value.column,t.value.row,t.value.column+e.length),e.mainClass,null,!1)}),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1),n.on("change",function(i){e.removeMarker(n.markerId),n.markerId=e.addMarker(new r(i.value.row,i.value.column,i.value.row,i.value.column+t.length),t.othersClass,null,!1)})})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e=this.pos.column&&n.start.column<=this.pos.column+this.length+1){var s=n.start.column-this.pos.column;this.length+=i;if(!this.session.$fromUndo){if(t.action==="insertText")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};u.row===n.start.row&&n.start.column=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};u.row===n.start.row&&n.start.column=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))},this.detach=function(){this.session.removeMarker(this.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.pos.detach();for(var e=0;ef){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=this.getFoldWidget(e,u.row)),a=="start"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}); + (function() { + ace.require(["ace/ace"], function(a) { + a && a.config.init(); + if (!window.ace) + window.ace = {}; + for (var key in a) if (a.hasOwnProperty(key)) + ace[key] = a[key]; + }); + })(); + \ No newline at end of file diff --git a/common/static/js/vendor/ace/ext-searchbox.js b/common/static/js/vendor/ace/ext-searchbox.js new file mode 100644 index 0000000000..06fecea5bb --- /dev/null +++ b/common/static/js/vendor/ace/ext-searchbox.js @@ -0,0 +1 @@ +ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"],function(e,t,n){var r=e("../lib/dom"),i=e("../lib/lang"),s=e("../lib/event"),o="/* ------------------------------------------------------------------------------------------* Editor Search Form* --------------------------------------------------------------------------------------- */.ace_search {background-color: #ddd;border: 1px solid #cbcbcb;border-top: 0 none;max-width: 297px;overflow: hidden;margin: 0;padding: 4px;padding-right: 6px;padding-bottom: 0;position: absolute;top: 0px;z-index: 99;}.ace_search.left {border-left: 0 none;border-radius: 0px 0px 5px 0px;left: 0;}.ace_search.right {border-radius: 0px 0px 0px 5px;border-right: 0 none;right: 0;}.ace_search_form, .ace_replace_form {border-radius: 3px;border: 1px solid #cbcbcb;float: left;margin-bottom: 4px;overflow: hidden;}.ace_search_field {background-color: white;border-right: 1px solid #cbcbcb;border: 0 none;-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;display: block;float: left;height: 22px;outline: 0;padding: 0 7px;width: 214px;margin: 0;}.ace_searchbtn,.ace_replacebtn {background: #fff;border: 0 none;border-left: 1px solid #dcdcdc;cursor: pointer;display: block;float: left;height: 22px;margin: 0;padding: 0;position: relative;}.ace_searchbtn:last-child,.ace_replacebtn:last-child {border-top-right-radius: 3px;border-bottom-right-radius: 3px;}.ace_searchbtn:disabled {background: none;cursor: default;}.ace_searchbtn {background-position: 50% 50%;background-repeat: no-repeat;width: 27px;}.ace_searchbtn.prev {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); }.ace_searchbtn.next {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); }.ace_searchbtn_close {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;border-radius: 50%;border: 0 none;color: #656565;cursor: pointer;display: block;float: right;font-family: Arial;font-size: 16px;height: 14px;line-height: 16px;margin: 5px 1px 9px 5px;padding: 0;text-align: center;width: 14px;}.ace_searchbtn_close:hover {background-color: #656565;background-position: 50% 100%;color: white;}.ace_replacebtn.prev {width: 54px}.ace_replacebtn.next {width: 27px}",u=e("../keyboard/hash_handler").HashHandler,a=e("../lib/keys");r.importCssString(o,"ace_searchbox");var f=''.replace(/>\s+/g,">"),l=function(e,t,n){var i=r.createElement("div");i.innerHTML=f,this.element=i.firstChild,this.$init(),this.setEditor(e)};(function(){this.setEditor=function(e){e.searchBox=this,e.container.appendChild(this.element),this.editor=e},this.$init=function(){var e=this.element;this.searchBox=e.querySelector(".ace_search_form"),this.replaceBox=e.querySelector(".ace_replace_form"),this.searchInput=this.searchBox.querySelector(".ace_search_field"),this.replaceInput=this.replaceBox.querySelector(".ace_search_field");var t=this;s.addListener(e,"mousedown",function(e){setTimeout(function(){t.activeInput.focus()},0),s.stopPropagation(e)}),s.addListener(e,"click",function(e){var n=e.target,r=n.getAttribute("action");r&&t[r]&&t[r](),s.stopPropagation(e)}),s.addCommandKeyListener(e,function(e,n,r){var i=a.keyCodeToString(r),o=t.$searchBarKb.findKeyCommand(n,i);o&&o.exec&&(o.exec(t),s.stopEvent(e))}),this.$onChange=i.delayedCall(function(){t.find(!1,!1)}),s.addListener(this.searchInput,"input",function(){t.$onChange.schedule(20)}),s.addListener(this.searchInput,"focus",function(){t.activeInput=t.searchInput}),s.addListener(this.replaceInput,"focus",function(){t.activeInput=t.replaceInput})},this.$closeSearchBarKb=new u([{bindKey:"Esc",name:"closeSearchBar",exec:function(e){e.searchBox.hide()}}]),this.$searchBarKb=new u,this.$searchBarKb.bindKeys({"Ctrl-f|Command-f|Ctrl-H|Command-Option-F":function(e){var t=e.isReplace=!e.isReplace;e.replaceBox.style.display=t?"":"none",e[t?"replaceInput":"searchInput"].focus()},esc:function(e){setTimeout(function(){e.hide()})},Return:function(e){e.activeInput==e.replaceInput&&e.replace(),e.findNext()},"Shift-Return":function(e){e.activeInput==e.replaceInput&&e.replace(),e.findPrev()},Tab:function(e){(e.activeInput==e.replaceInput?e.searchInput:e.replaceInput).focus()}}),this.find=function(e,t){this.editor.find(this.searchInput.value,{skipCurrent:e,backwards:t,wrap:!0}),this.editor.session.highlight(this.editor.$search.$options.re)},this.findNext=function(){this.find(!0,!1)},this.findPrev=function(){this.find(!0,!0)},this.replace=function(){this.editor.replace(this.replaceInput.value),this.findNext()},this.replaceAll=function(){this.editor.replaceAll(this.replaceInput.value)},this.hide=function(){this.element.style.display="none",this.editor.keyBinding.removeKeyboardHandler(this.$searchKeybingin),this.editor.focus()},this.show=function(e,t){this.element.style.display="",this.replaceBox.style.display=t?"":"none",this.isReplace=t,e&&(this.searchInput.value=e),this.searchInput.focus(),this.searchInput.select(),this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb)}}).call(l.prototype),t.SearchBox=l,t.Search=function(e,t){var n=e.searchBox||new l(e);n.show(e.session.getTextRange(),t)},t.ISearch=function(e,t){this.$changeListener=this.$changeListener.bind(this),this.startRange=e.selection.toOrientedRange(),this.options=t||{}},function(){this.setSession=function(e){this.session&&this.session.removeListener(this.$changeListener),this.session=e,this.session.addListener(this.$changeListener)},this.setSearchString=function(){},this.getValue=function(){return this.value==null&&(this.value=this.session.getValue()),this.value},this.$changeListener=function(){this.value=null},this.find=function(){},this.$edgeBefore=function(){this.cursor=this.startRange[this.options.backwards?"start":"end"]},this.$edgeAfter=function(){},this.next=function(e){}}.call(t.ISearch.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/ext-spellcheck.js b/common/static/js/vendor/ace/ext-spellcheck.js new file mode 100644 index 0000000000..7df4ef7f38 --- /dev/null +++ b/common/static/js/vendor/ace/ext-spellcheck.js @@ -0,0 +1 @@ +ace.define("ace/ext/spellcheck",["require","exports","module"],function(e,t,n){text.spellcheck=!0,host.on("nativecontextmenu",function(e){if(!host.selection.isEmpty())return;var t=host.getCursorPosition(),n=host.session.getWordRange(t.row,t.column),r=host.session.getTextRange(n);host.session.tokenRe.lastIndex=0;if(!host.session.tokenRe.test(r))return;var e=r+" "+PLACEHOLDER;text.value=e,text.setSelectionRange(r.length+1,r.length+1),text.setSelectionRange(0,0),inputHandler=function(t){if(t==e)return"";if(t.lastIndexOf(e)==t.length-e.length)return t.slice(0,-e.length);if(t.indexOf(e)==0)return t.slice(e.length);if(t.slice(-2)==PLACEHOLDER){var r=t.slice(0,-2);if(r.slice(-1)==" ")return r=r.slice(0,-1),host.session.replace(n,r),r}return t}})}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/ext-static_highlight.js b/common/static/js/vendor/ace/ext-static_highlight.js new file mode 100644 index 0000000000..b154ef23bc --- /dev/null +++ b/common/static/js/vendor/ace/ext-static_highlight.js @@ -0,0 +1 @@ +ace.define("ace/ext/static_highlight",["require","exports","module","ace/edit_session","ace/layer/text"],function(e,t,n){var r=e("../edit_session").EditSession,i=e("../layer/text").Text,s=".ace_editor {font-family: 'Monaco', 'Menlo', 'Droid Sans Mono', 'Courier New', monospace;font-size: 12px;}.ace_editor .ace_gutter { width: 25px !important;display: block;float: left;text-align: right; padding: 0 3px 0 0; margin-right: 3px;}.ace_line { clear: both; }*.ace_gutter-cell {-moz-user-select: -moz-none;-khtml-user-select: none;-webkit-user-select: none;user-select: none;}";t.render=function(e,t,n,o,u){o=parseInt(o||1,10);var a=new r("");a.setMode(t),a.setUseWorker(!1);var f=new i(document.createElement("div"));f.setSession(a),f.config={characterWidth:10,lineHeight:20},a.setValue(e);var l=[],c=a.getLength();for(var h=0;h"),u||l.push(""+(h+o)+""),f.$renderLine(l,h,!0,!1),l.push("
    ");var p="
    :code
    ".replace(/:cssClass/,n.cssClass).replace(/:code/,l.join(""));return f.destroy(),{css:s+n.cssText,html:p}}}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/ext-textarea.js b/common/static/js/vendor/ace/ext-textarea.js new file mode 100644 index 0000000000..84ade590ad --- /dev/null +++ b/common/static/js/vendor/ace/ext-textarea.js @@ -0,0 +1 @@ +ace.define("ace/ext/textarea",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/net","ace/ace","ace/theme/textmate","ace/mode/text"],function(e,t,n){function a(e,t){for(var n in t)e.style[n]=t[n]}function f(e,t){if(e.type!="textarea")throw"Textarea required!";var n=e.parentNode,i=document.createElement("div"),s=function(){var t="position:relative;";["margin-top","margin-left","margin-right","margin-bottom"].forEach(function(n){t+=n+":"+u(e,i,n)+";"});var n=u(e,i,"width")||e.clientWidth+"px",r=u(e,i,"height")||e.clientHeight+"px";t+="height:"+r+";width:"+n+";",t+="display:inline-block;",i.setAttribute("style",t)};r.addListener(window,"resize",s),s(),e.nextSibling?n.insertBefore(i,e.nextSibling):n.appendChild(i);while(n!==document){if(n.tagName.toUpperCase()==="FORM"){var o=n.onsubmit;n.onsubmit=function(n){e.innerHTML=t(),e.value=t(),o&&o.call(this,n)};break}n=n.parentNode}return i}function l(t,n,r){s.loadScript(t,function(){e([n],r)})}function c(n,r,i,s,o,u){function c(e){return e=="true"}var a=n.getSession(),f=n.renderer;u=u||l,n.setDisplaySettings=function(e){e==null&&(e=i.style.display=="none"),i.style.display=e?"block":"none"},n.setOption=function(t,i){if(o[t]==i)return;switch(t){case"gutter":f.setShowGutter(c(i));break;case"mode":i!="text"?u("mode-"+i+".js","ace/mode/"+i,function(){var t=e("../mode/"+i).Mode;a.setMode(new t)}):a.setMode(new(e("../mode/text").Mode));break;case"theme":i!="textmate"?u("theme-"+i+".js","ace/theme/"+i,function(){n.setTheme("ace/theme/"+i)}):n.setTheme("ace/theme/textmate");break;case"fontSize":r.style.fontSize=i;break;case"keybindings":switch(i){case"vim":n.setKeyboardHandler("ace/keyboard/vim");break;case"emacs":n.setKeyboardHandler("ace/keyboard/emacs");break;default:n.setKeyboardHandler(null)}break;case"softWrap":switch(i){case"off":a.setUseWrapMode(!1),f.setPrintMarginColumn(80);break;case"40":a.setUseWrapMode(!0),a.setWrapLimitRange(40,40),f.setPrintMarginColumn(40);break;case"80":a.setUseWrapMode(!0),a.setWrapLimitRange(80,80),f.setPrintMarginColumn(80);break;case"free":a.setUseWrapMode(!0),a.setWrapLimitRange(null,null),f.setPrintMarginColumn(80)}break;case"useSoftTabs":a.setUseSoftTabs(c(i));break;case"showPrintMargin":f.setShowPrintMargin(c(i));break;case"showInvisibles":n.setShowInvisibles(c(i))}o[t]=i},n.getOption=function(e){return o[e]},n.getOptions=function(){return o};for(var h in t.options)n.setOption(h,t.options[h]);return n}function h(e,t,n,i){function f(e,t,n,r){e.push("")}var s={"true":!0,"false":!1},o={mode:"Mode:",gutter:"Display Gutter:",theme:"Theme:",fontSize:"Font Size:",softWrap:"Soft Wrap:",keybindings:"Keyboard",showPrintMargin:"Show Print Margin:",useSoftTabs:"Use Soft Tabs:",showInvisibles:"Show Invisibles"},u={mode:{text:"Plain",javascript:"JavaScript",xml:"XML",html:"HTML",css:"CSS",scss:"SCSS",python:"Python",php:"PHP",java:"Java",ruby:"Ruby",c_cpp:"C/C++",coffee:"CoffeeScript",json:"json",perl:"Perl",clojure:"Clojure",ocaml:"OCaml",csharp:"C#",haxe:"haXe",svg:"SVG",textile:"Textile",groovy:"Groovy",liquid:"Liquid",Scala:"Scala"},theme:{clouds:"Clouds",clouds_midnight:"Clouds Midnight",cobalt:"Cobalt",crimson_editor:"Crimson Editor",dawn:"Dawn",eclipse:"Eclipse",idle_fingers:"Idle Fingers",kr_theme:"Kr Theme",merbivore:"Merbivore",merbivore_soft:"Merbivore Soft",mono_industrial:"Mono Industrial",monokai:"Monokai",pastel_on_dark:"Pastel On Dark",solarized_dark:"Solarized Dark",solarized_light:"Solarized Light",textmate:"Textmate",twilight:"Twilight",vibrant_ink:"Vibrant Ink"},gutter:s,fontSize:{"10px":"10px","11px":"11px","12px":"12px","14px":"14px","16px":"16px"},softWrap:{off:"Off",40:"40",80:"80",free:"Free"},keybindings:{ace:"ace",vim:"vim",emacs:"emacs"},showPrintMargin:s,useSoftTabs:s,showInvisibles:s},a=[];a.push("
    + ${i} points +
    ");for(var l in i)a.push(""),a.push("");a.push("
    SettingValue
    ",o[l],""),f(a,l,u[l],i[l]),a.push("
    "),e.innerHTML=a.join("");var c=e.getElementsByTagName("select");for(var h=0;h30&&this.$data.shift()},get:function(){return this.$data[this.$data.length-1]||""},pop:function(){return this.$data.length>1&&this.$data.pop(),this.get()},rotate:function(){return this.$data.unshift(this.$data.pop()),this.get()}}}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/keybinding-vim.js b/common/static/js/vendor/ace/keybinding-vim.js new file mode 100644 index 0000000000..5a8eabff7c --- /dev/null +++ b/common/static/js/vendor/ace/keybinding-vim.js @@ -0,0 +1 @@ +ace.define("ace/keyboard/vim",["require","exports","module","ace/keyboard/vim/commands","ace/keyboard/vim/maps/util","ace/lib/useragent"],function(e,t,n){var r=e("./vim/commands"),i=r.coreCommands,s=e("./vim/maps/util"),o=e("../lib/useragent"),u={i:{command:i.start},I:{command:i.startBeginning},a:{command:i.append},A:{command:i.appendEnd},"ctrl-f":{command:"gotopagedown"},"ctrl-b":{command:"gotopageup"}};t.handler={handleMacRepeat:function(e,t,n){if(t==-1)e.inputChar=n,e.lastEvent="input";else if(e.inputChar&&e.$lastHash==t&&e.$lastKey==n){if(e.lastEvent=="input")e.lastEvent="input1";else if(e.lastEvent=="input1")return!0}else e.$lastHash=t,e.$lastKey=n,e.lastEvent="keypress"},handleKeyboard:function(e,t,n,s,a){if(t!=0&&(n==""||n=="\0"))return null;t==1&&(n="ctrl-"+n);if(n=="esc"&&t==0||n=="ctrl-[")return{command:i.stop};if(e.state=="start"){o.isMac&&this.handleMacRepeat(e,t,n)&&(t=-1,n=e.inputChar);if(t==-1||t==1||t==0&&n.length>1)return r.inputBuffer.idle&&u[n]?u[n]:{command:{exec:function(e){return r.inputBuffer.push(e,n)}}};if(n.length==1&&(t==0||t==4))return{command:"null",passEvent:!0};if(n=="esc"&&t==0)return{command:i.stop}}else if(n=="ctrl-w")return{command:"removewordleft"}},attach:function(e){e.on("click",t.onCursorMove),s.currentMode!=="insert"&&r.coreCommands.stop.exec(e),e.$vimModeHandler=this},detach:function(e){e.removeListener("click",t.onCursorMove),s.noMode(e),s.currentMode="normal"},actions:r.actions,getStatusText:function(){return s.currentMode=="insert"?"INSERT":s.onVisualMode?(s.onVisualLineMode?"VISUAL LINE ":"VISUAL ")+r.inputBuffer.status:r.inputBuffer.status}},t.onCursorMove=function(e){r.onCursorMove(e.editor,e),t.onCursorMove.scheduled=!1}}),ace.define("ace/keyboard/vim/commands",["require","exports","module","ace/keyboard/vim/maps/util","ace/keyboard/vim/maps/motions","ace/keyboard/vim/maps/operators","ace/keyboard/vim/maps/aliases","ace/keyboard/vim/registers"],function(e,t,n){"never use strict";function g(e){m.previous={action:{action:{fn:e}}}}var r=e("./maps/util"),i=e("./maps/motions"),s=e("./maps/operators"),o=e("./maps/aliases"),u=e("./registers"),a=1,f=2,l=3,c=4,h=8,p=function(t,n,r){while(0t.$size.scrollerHeight&&(i=t.$size.scrollerHeight/2),t.scrollTop>r-i&&t.session.setScrollTop(r-i),t.scrollTop+t.$size.scrollerHeight0&&e.navigateLeft()),e.setOverwrite(!0),e.keyBinding.$data.buffer="",e.keyBinding.$data.state="start",this.onVisualMode=!1,this.onVisualLineMode=!1,e._emit("changeStatus"),e.commands.recording?(e.commands.toggleRecording(e),e.commands.macro):[]},visualMode:function(e,t){if(this.onVisualLineMode&&t||this.onVisualMode&&!t){this.normalMode(e);return}e.setStyle("insert-mode"),e.unsetStyle("normal-mode"),e._emit("changeStatus"),t?this.onVisualLineMode=!0:(this.onVisualMode=!0,this.onVisualLineMode=!1)},getRightNthChar:function(e,t,n,r){var i=e.getSession().getLine(t.row),s=i.substr(t.column+1).split(n);return r~!@#$%^&*|+=\[\]{}`~?]/,u=/[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/,a=/\s/,f=function(e,t){var n=e.selection;this.range=n.getRange(),t=t||n.selectionLead,this.row=t.row,this.col=t.column;var r=e.session.getLine(this.row),i=e.session.getLength();this.ch=r[this.col]||"\n",this.skippedLines=0,this.next=function(){return this.ch=r[++this.col]||this.handleNewLine(1),this.ch},this.prev=function(){return this.ch=r[--this.col]||this.handleNewLine(-1),this.ch},this.peek=function(t){var n=r[this.col+t];return n?n:t==-1?"\n":this.col==r.length-1?"\n":e.session.getLine(this.row+1)[0]||"\n"},this.handleNewLine=function(t){if(t==1)return this.col==r.length?"\n":this.row==i-1?"":(this.col=0,this.row++,r=e.session.getLine(this.row),this.skippedLines++,r[0]||"\n");if(t==-1)return this.row===0?"":(this.row--,r=e.session.getLine(this.row),this.col=r.length,this.skippedLines--,"\n")},this.debug=function(){console.log(r.substring(0,this.col)+"|"+this.ch+"'"+this.col+"'"+r.substr(this.col+1))}},l=e("../../../search").Search,c=new l,p=e("../../../range").Range;n.exports={w:new s(function(e){var t=new f(e);if(t.ch&&u.test(t.ch))while(t.ch&&u.test(t.ch))t.next();else while(t.ch&&!o.test(t.ch))t.next();while(t.ch&&a.test(t.ch)&&t.skippedLines<2)t.next();return t.skippedLines==2&&t.prev(),{column:t.col,row:t.row}}),W:new s(function(e){var t=new f(e);while(t.ch&&(!a.test(t.ch)||!!a.test(t.peek(1)))&&t.skippedLines<2)t.next();return t.skippedLines==2?t.prev():t.next(),{column:t.col,row:t.row}}),b:new s(function(e){var t=new f(e);t.prev();while(t.ch&&a.test(t.ch)&&t.skippedLines>-2)t.prev();if(t.ch&&u.test(t.ch))while(t.ch&&u.test(t.ch))t.prev();else while(t.ch&&!o.test(t.ch))t.prev();return t.ch&&t.next(),{column:t.col,row:t.row}}),B:new s(function(e){var t=new f(e);t.prev();while(t.ch&&(!!a.test(t.ch)||!a.test(t.peek(-1)))&&t.skippedLines>-2)t.prev();return t.skippedLines==-2&&t.next(),{column:t.col,row:t.row}}),e:new s(function(e){var t=new f(e);t.next();while(t.ch&&a.test(t.ch))t.next();if(t.ch&&u.test(t.ch))while(t.ch&&u.test(t.ch))t.next();else while(t.ch&&!o.test(t.ch))t.next();return t.ch&&t.prev(),{column:t.col,row:t.row}}),E:new s(function(e){var t=new f(e);t.next();while(t.ch&&(!!a.test(t.ch)||!a.test(t.peek(1))))t.next();return{column:t.col,row:t.row}}),l:{nav:function(e){var t=e.getCursorPosition(),n=t.column,r=e.session.getLine(t.row).length;r&&n!==r&&e.navigateRight()},sel:function(e){var t=e.getCursorPosition(),n=t.column,r=e.session.getLine(t.row).length;r&&n!==r&&e.selection.selectRight()}},h:{nav:function(e){var t=e.getCursorPosition();t.column>0&&e.navigateLeft()},sel:function(e){var t=e.getCursorPosition();t.column>0&&e.selection.selectLeft()}},H:{nav:function(e){var t=e.renderer.getScrollTopRow();e.moveCursorTo(t)},sel:function(e){var t=e.renderer.getScrollTopRow();e.selection.selectTo(t)}},M:{nav:function(e){var t=e.renderer.getScrollTopRow(),n=e.renderer.getScrollBottomRow(),r=t+(n-t)/2;e.moveCursorTo(r)},sel:function(e){var t=e.renderer.getScrollTopRow(),n=e.renderer.getScrollBottomRow(),r=t+(n-t)/2;e.selection.selectTo(r)}},L:{nav:function(e){var t=e.renderer.getScrollBottomRow();e.moveCursorTo(t)},sel:function(e){var t=e.renderer.getScrollBottomRow();e.selection.selectTo(t)}},k:{nav:function(e){e.navigateUp()},sel:function(e){e.selection.selectUp()}},j:{nav:function(e){e.navigateDown()},sel:function(e){e.selection.selectDown()}},i:{param:!0,sel:function(e,t,n,r){switch(r){case"w":e.selection.selectWord();break;case"W":e.selection.selectAWord();break;case"(":case"{":case"[":var i=e.getCursorPosition(),s=e.session.$findClosingBracket(r,i,/paren/);if(!s)return;var o=e.session.$findOpeningBracket(e.session.$brackets[r],i,/paren/);if(!o)return;o.column++,e.selection.setSelectionRange(p.fromPoints(o,s));break;case"'":case'"':case"/":var s=h(e,r,1);if(!s)return;var o=h(e,r,-1);if(!o)return;e.selection.setSelectionRange(p.fromPoints(o.end,s.start))}}},a:{param:!0,sel:function(e,t,n,r){switch(r){case"w":e.selection.selectAWord();break;case"W":e.selection.selectAWord();break;case"(":case"{":case"[":var i=e.getCursorPosition(),s=e.session.$findClosingBracket(r,i,/paren/);if(!s)return;var o=e.session.$findOpeningBracket(e.session.$brackets[r],i,/paren/);if(!o)return;s.column++,e.selection.setSelectionRange(p.fromPoints(o,s));break;case"'":case'"':case"/":var s=h(e,r,1);if(!s)return;var o=h(e,r,-1);if(!o)return;s.column++,e.selection.setSelectionRange(p.fromPoints(o.start,s.end))}}},f:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getRightNthChar(e,o,i,n||1);if(typeof u=="number")return o.column+=u+(s?2:1),o}}),F:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getLeftNthChar(e,o,i,n||1);if(typeof u=="number")return o.column-=u+1,o}}),t:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getRightNthChar(e,o,i,n||1);if(typeof u=="number")return o.column+=u+(s?1:0),o}}),T:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getLeftNthChar(e,o,i,n||1);if(typeof u=="number")return o.column-=u,o}}),"^":{nav:function(e){e.navigateLineStart()},sel:function(e){e.selection.selectLineStart()}},$:{nav:function(e){e.navigateLineEnd()},sel:function(e){e.selection.selectLineEnd()}},0:new s(function(e){return{row:e.selection.lead.row,column:0}}),G:{nav:function(e,t,n,r){!n&&n!==0&&(n=e.session.getLength()),e.gotoLine(n)},sel:function(e,t,n,r){!n&&n!==0&&(n=e.session.getLength()),e.selection.selectTo(n,0)}},g:{param:!0,nav:function(e,t,n,r){switch(r){case"m":console.log("Middle line");break;case"e":console.log("End of prev word");break;case"g":e.gotoLine(n||0);case"u":e.gotoLine(n||0);case"U":e.gotoLine(n||0)}},sel:function(e,t,n,r){switch(r){case"m":console.log("Middle line");break;case"e":console.log("End of prev word");break;case"g":e.selection.selectTo(n||0,0)}}},o:{nav:function(e,t,n,i){n=n||1;var s="";while(00?(e.navigateUp(),e.navigateLineEnd(),e.insert(o)):(e.session.insert({row:0,column:0},o),e.navigateUp()),r.insertMode(e))}},"%":new s(function(e){var t=/[\[\]{}()]/g,n=e.getCursorPosition(),r=e.session.getLine(n.row)[n.column];if(!t.test(r)){var i=h(e,t);if(!i)return;n=i.start}var s=e.session.findMatchingBracket({row:n.row,column:n.column+1});return s}),"{":new s(function(e){var t=e.session,n=t.selection.lead.row;while(n>0&&!/\S/.test(t.getLine(n)))n--;while(/\S/.test(t.getLine(n)))n--;return{column:0,row:n}}),"}":new s(function(e){var t=e.session,n=t.getLength(),r=t.selection.lead.row;while(r":{selFn:function(e,t,n,i){n=n||1;for(var s=0;s":var i=e.getCursorPosition();e.selection.selectLine();for(var s=0;s*]\W|\*\*|[~:,\.&$]|->*?|=>/},{token:"paren.lparen",regex:"[\\[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"constant.numeric",regex:"[+-]?\\d+\\b"},{token:"variable.parameter",regex:/sy|pa?\d\d\d\d\|t\d\d\d\.|innnn/},{token:"keyword",regex:t},{token:"variable.parameter",regex:/\w+-\w+(?:-\w+)*/},{token:e,regex:"\\w+\\b"}],qstring:[{token:"constant.language.escape",regex:"''"},{token:"string",regex:"'",next:"start"},{token:"string",regex:".|w+"}],string:[{token:"constant.language.escape",regex:"``"},{token:"string",regex:"`",next:"start"},{token:"string",regex:".|w+"}]}};r.inherits(s,i),t.AbapHighlightRules=s}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u{3,}$/,next:"start"},{token:"literal",regex:/^\.{4,}\s*$/,next:"listingBlock"},{token:"titleUnderline",regex:/^(?:={2,}|-{2,}|~{2,}|\^{2,}|\+{2,})\s*$/,next:"start"},{token:"singleLineTitle",regex:/^={1,5}\s+\S.*$/,next:"start"},{token:"otherBlock",regex:/^(?:\*{2,}|_{2,})\s*$/,next:"start"},{token:"optionalTitle",regex:/^\.[^.\s].+$/,next:"start"}],listStart:[{token:"keyword",regex:/^\s*(?:\d+\.|[a-zA-Z]\.|[ixvmIXVM]+\)|\*{1,5}|-|\.{1,5})\s/,next:"listText"},{token:"meta.tag",regex:/^.+(?::{2,4}|;;)(?: |$)/,next:"listText"},{token:"support.function.list.callout",regex:/^(?:<\d+>|\d+>|>) /,next:"text"},{token:"keyword",regex:/^\+\s*$/,next:"start"}],text:[{token:["link","variable.language"],regex:/((?:https?:\/\/|ftp:\/\/|file:\/\/|mailto:|callto:)[^\s\[]+)(\[.*?\])/},{token:"link",regex:/(?:https?:\/\/|ftp:\/\/|file:\/\/|mailto:|callto:)[^\s\[]+/},{token:"link",regex:/\b[\w\.\/\-]+@[\w\.\/\-]+\b/},{include:"macros"},{include:"paragraphEnd"},{token:"literal",regex:/\+{3,}/,next:"smallPassthrough"},{token:"escape",regex:/\((?:C|TM|R)\)|\.{3}|->|<-|=>|<=|&#(?:\d+|x[a-fA-F\d]+);|(?: |^)--(?=\s+\S)/},{token:"escape",regex:/\\[_*'`+#]|\\{2}[_*'`+#]{2}/},{token:"keyword",regex:/\s\+$/},{token:"text",regex:e},{token:["keyword","string","keyword"],regex:/(<<[\w\d\-$]+,)(.*?)(>>|$)/},{token:"keyword",regex:/<<[\w\d\-$]+,?|>>/},{token:"constant.character",regex:/\({2,3}.*?\){2,3}/},{token:"keyword",regex:/\[\[.+?\]\]/},{token:"support",regex:/^\[{3}[\w\d =\-]+\]{3}/},{include:"quotes"},{token:"empty",regex:/^\s*$/,next:"start"}],listText:[{include:"listStart"},{include:"text"}],indentedBlock:[{token:"literal",regex:/^[\s\w].+$/,next:"indentedBlock"},{token:"literal",regex:"",next:"start"}],listingBlock:[{token:"literal",regex:/^\.{4,}\s*$/,next:"dissallowDelimitedBlock"},{token:"constant.numeric",regex:"<\\d+>"},{token:"literal",regex:"[^<]+"},{token:"literal",regex:"<"}],literalBlock:[{token:"literal",regex:/^-{4,}\s*$/,next:"dissallowDelimitedBlock"},{token:"constant.numeric",regex:"<\\d+>"},{token:"literal",regex:"[^<]+"},{token:"literal",regex:"<"}],passthroughBlock:[{token:"literal",regex:/^\+{4,}\s*$/,next:"dissallowDelimitedBlock"},{token:"literal",regex:e+"|\\d+"},{include:"macros"},{token:"literal",regex:"."}],smallPassthrough:[{token:"literal",regex:/[+]{3,}/,next:"dissallowDelimitedBlock"},{token:"literal",regex:/^\s*$/,next:"dissallowDelimitedBlock"},{token:"literal",regex:e+"|\\d+"},{include:"macros"}],commentBlock:[{token:"doc.comment",regex:/^\/{4,}\s*$/,next:"dissallowDelimitedBlock"},{token:"doc.comment",regex:"^.*$"}],tableBlock:[{token:"tableBlock",regex:/^\s*\|={3,}\s*$/,next:"dissallowDelimitedBlock"},{token:"tableBlock",regex:/^\s*!={3,}\s*$/,next:"innerTableBlock"},{token:"tableBlock",regex:/\|/},{include:"text",noEscape:!0}],innerTableBlock:[{token:"tableBlock",regex:/^\s*!={3,}\s*$/,next:"tableBlock"},{token:"tableBlock",regex:/^\s*|={3,}\s*$/,next:"dissallowDelimitedBlock"},{token:"tableBlock",regex:/\!/}],macros:[{token:"macro",regex:/{[\w\-$]+}/},{token:["text","string","text","constant.character","text"],regex:/({)([\w\-$]+)(:)?(.+)?(})/},{token:["text","markup.list.macro","keyword","string"],regex:/(\w+)(footnote(?:ref)?::?)([^\s\[]+)?(\[.*?\])?/},{token:["markup.list.macro","keyword","string"],regex:/([a-zA-Z\-][\w\.\/\-]*::?)([^\s\[]+)(\[.*?\])?/},{token:["markup.list.macro","keyword"],regex:/([a-zA-Z\-][\w\.\/\-]+::?)(\[.*?\])/},{token:"keyword",regex:/^:.+?:(?= |$)/}],quotes:[{token:"string.italic",regex:/__[^_\s].*?__/},{token:"string.italic",regex:t("_")},{token:"keyword.bold",regex:/\*\*[^*\s].*?\*\*/},{token:"keyword.bold",regex:t("\\*")},{token:"literal",regex:t("\\+")},{token:"literal",regex:/\+\+[^+\s].*?\+\+/},{token:"literal",regex:/\$\$.+?\$\$/},{token:"literal",regex:t("`")},{token:"keyword",regex:t("^")},{token:"keyword",regex:t("~")},{token:"keyword",regex:/##?/},{token:"keyword",regex:/(?:\B|^)``|\b''/}]};var n={macro:"constant.character",tableBlock:"doc.comment",titleUnderline:"markup.heading",singleLineTitle:"markup.heading",pageBreak:"string",option:"string.regexp",otherBlock:"markup.list",literal:"support.function",optionalTitle:"constant.numeric",escape:"constant.language.escape",link:"markup.underline.list"};for(var r in this.$rules){var i=this.$rules[r];for(var s=i.length;s--;){var o=i[s];if(o.include||typeof o=="string"){var u=[s,1].concat(this.$rules[o.include||o]);o.noEscape&&(u=u.filter(function(e){return!e.next})),i.splice.apply(i,u)}else o.token in n&&(o.token=n[o.token])}}};r.inherits(s,i),t.AsciidocHighlightRules=s}),ace.define("ace/mode/folding/asciidoc",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.foldingStartMarker=/^(?:\|={10,}|[\.\/=\-~^+]{4,}\s*$|={1,5} )/,this.singleLineHeadingRe=/^={1,5}(?=\s+\S)/,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?r[0]=="="?this.singleLineHeadingRe.test(r)?"start":e.getLine(n-1).length!=e.getLine(n).length?"":"start":e.bgTokenizer.getState(n)=="dissallowDelimitedBlock"?"end":"start":""},this.getFoldWidgetRange=function(e,t,n){function l(t){return f=e.getTokens(t)[0],f&&f.type}function d(){var t=f.value.match(p);if(t)return t[0].length;var r=c.indexOf(f.value[0])+1;return r==1&&e.getLine(n-1).length!=e.getLine(n).length?Infinity:r}var r=e.getLine(n),i=r.length,o=e.getLength(),u=n,a=n;if(!r.match(this.foldingStartMarker))return;var f,c=["=","-","~","^","+"],h="markup.heading",p=this.singleLineHeadingRe;if(l(n)==h){var v=d();while(++nu)while(a>u&&(!l(a)||f.value[0]=="["))a--;if(a>u){var y=e.getLine(a).length;return new s(u,i,a,y)}}else{var b=e.bgTokenizer.getState(n);if(b=="dissallowDelimitedBlock"){while(n-->0)if(e.bgTokenizer.getState(n).lastIndexOf("Block")==-1)break;a=n+1;if(au){var y=e.getLine(n).length;return new s(u,5,a,y-5)}}}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-c9search.js b/common/static/js/vendor/ace/mode-c9search.js new file mode 100644 index 0000000000..cd0a3e34d0 --- /dev/null +++ b/common/static/js/vendor/ace/mode-c9search.js @@ -0,0 +1 @@ +ace.define("ace/mode/c9search",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/c9search_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/c9search"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./c9search_highlight_rules").C9SearchHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./folding/c9search").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/c9search_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:["c9searchresults.constant.numeric","c9searchresults.text","c9searchresults.text"],regex:"(^\\s+[0-9]+)(:\\s*)(.+)"},{token:["string","text"],regex:"(.+)(:$)"}]}};r.inherits(s,i),t.C9SearchHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/c9search",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/^(\S.*\:|Searching for.*)$/,this.foldingStopMarker=/^(\s+|Found.*)$/,this.getFoldWidgetRange=function(e,t,n){var r=e.doc.getAllLines(n),s=r[n],o=/^(Found.*|Searching for.*)$/,u=/^(\S.*\:|\s*)$/,a=o.test(s)?o:u;if(this.foldingStartMarker.test(s)){for(var f=n+1,l=e.getLength();f=0;f--){s=r[f];if(a.test(s))break}return new i(f,s.length,n,0)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-c_cpp.js b/common/static/js/vendor/ace/mode-c_cpp.js new file mode 100644 index 0000000000..51fcb4d1bf --- /dev/null +++ b/common/static/js/vendor/ace/mode-c_cpp.js @@ -0,0 +1 @@ +ace.define("ace/mode/c_cpp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/c_cpp_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./c_cpp_highlight_rules").c_cppHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var u=t.match(/^.*[\{\(\[]\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/c_cpp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=t.cFunctions="\\s*\\bhypot(?:f|l)?|s(?:scanf|ystem|nprintf|ca(?:nf|lb(?:n(?:f|l)?|ln(?:f|l)?))|i(?:n(?:h(?:f|l)?|f|l)?|gn(?:al|bit))|tr(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?)|error|pbrk|ftime|len|rchr|xfrm)|printf|et(?:jmp|vbuf|locale|buf)|qrt(?:f|l)?|w(?:scanf|printf)|rand)|n(?:e(?:arbyint(?:f|l)?|xt(?:toward(?:f|l)?|after(?:f|l)?))|an(?:f|l)?)|c(?:s(?:in(?:h(?:f|l)?|f|l)?|qrt(?:f|l)?)|cos(?:h(?:f)?|f|l)?|imag(?:f|l)?|t(?:ime|an(?:h(?:f|l)?|f|l)?)|o(?:s(?:h(?:f|l)?|f|l)?|nj(?:f|l)?|pysign(?:f|l)?)|p(?:ow(?:f|l)?|roj(?:f|l)?)|e(?:il(?:f|l)?|xp(?:f|l)?)|l(?:o(?:ck|g(?:f|l)?)|earerr)|a(?:sin(?:h(?:f|l)?|f|l)?|cos(?:h(?:f|l)?|f|l)?|tan(?:h(?:f|l)?|f|l)?|lloc|rg(?:f|l)?|bs(?:f|l)?)|real(?:f|l)?|brt(?:f|l)?)|t(?:ime|o(?:upper|lower)|an(?:h(?:f|l)?|f|l)?|runc(?:f|l)?|gamma(?:f|l)?|mp(?:nam|file))|i(?:s(?:space|n(?:ormal|an)|cntrl|inf|digit|u(?:nordered|pper)|p(?:unct|rint)|finite|w(?:space|c(?:ntrl|type)|digit|upper|p(?:unct|rint)|lower|al(?:num|pha)|graph|xdigit|blank)|l(?:ower|ess(?:equal|greater)?)|al(?:num|pha)|gr(?:eater(?:equal)?|aph)|xdigit|blank)|logb(?:f|l)?|max(?:div|abs))|di(?:v|fftime)|_Exit|unget(?:c|wc)|p(?:ow(?:f|l)?|ut(?:s|c(?:har)?|wc(?:har)?)|error|rintf)|e(?:rf(?:c(?:f|l)?|f|l)?|x(?:it|p(?:2(?:f|l)?|f|l|m1(?:f|l)?)?))|v(?:s(?:scanf|nprintf|canf|printf|w(?:scanf|printf))|printf|f(?:scanf|printf|w(?:scanf|printf))|w(?:scanf|printf)|a_(?:start|copy|end|arg))|qsort|f(?:s(?:canf|e(?:tpos|ek))|close|tell|open|dim(?:f|l)?|p(?:classify|ut(?:s|c|w(?:s|c))|rintf)|e(?:holdexcept|set(?:e(?:nv|xceptflag)|round)|clearexcept|testexcept|of|updateenv|r(?:aiseexcept|ror)|get(?:e(?:nv|xceptflag)|round))|flush|w(?:scanf|ide|printf|rite)|loor(?:f|l)?|abs(?:f|l)?|get(?:s|c|pos|w(?:s|c))|re(?:open|e|ad|xp(?:f|l)?)|m(?:in(?:f|l)?|od(?:f|l)?|a(?:f|l|x(?:f|l)?)?))|l(?:d(?:iv|exp(?:f|l)?)|o(?:ngjmp|cal(?:time|econv)|g(?:1(?:p(?:f|l)?|0(?:f|l)?)|2(?:f|l)?|f|l|b(?:f|l)?)?)|abs|l(?:div|abs|r(?:int(?:f|l)?|ound(?:f|l)?))|r(?:int(?:f|l)?|ound(?:f|l)?)|gamma(?:f|l)?)|w(?:scanf|c(?:s(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?|mbs)|pbrk|ftime|len|r(?:chr|tombs)|xfrm)|to(?:b|mb)|rtomb)|printf|mem(?:set|c(?:hr|py|mp)|move))|a(?:s(?:sert|ctime|in(?:h(?:f|l)?|f|l)?)|cos(?:h(?:f|l)?|f|l)?|t(?:o(?:i|f|l(?:l)?)|exit|an(?:h(?:f|l)?|2(?:f|l)?|f|l)?)|b(?:s|ort))|g(?:et(?:s|c(?:har)?|env|wc(?:har)?)|mtime)|r(?:int(?:f|l)?|ound(?:f|l)?|e(?:name|alloc|wind|m(?:ove|quo(?:f|l)?|ainder(?:f|l)?))|a(?:nd|ise))|b(?:search|towc)|m(?:odf(?:f|l)?|em(?:set|c(?:hr|py|mp)|move)|ktime|alloc|b(?:s(?:init|towcs|rtowcs)|towc|len|r(?:towc|len)))\\b",u=function(){var e="break|case|continue|default|do|else|for|goto|if|_Pragma|return|switch|while|catch|operator|try|throw|using",t="asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|_Imaginary|int|long|short|signed|struct|typedef|union|unsigned|void|class|wchar_t|template",n="const|extern|register|restrict|static|volatile|inline|private:|protected:|public:|friend|explicit|virtual|export|mutable|typename",r="and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eqconst_cast|dynamic_cast|reinterpret_cast|static_cast|sizeof|namespace",s="NULL|true|false|TRUE|FALSE",u=this.$keywords=this.createKeywordMapper({"keyword.control":e,"storage.type":t,"storage.modifier":n,"keyword.operator":r,"variable.language":"this","constant.language":s},"identifier"),a="[a-zA-Z\\$_¡-ï¿¿][a-zA-Zd\\$_¡-ï¿¿]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"keyword",regex:"(?:#include|#import|#pragma|#line|#define|#undef|#if|#ifdef|#else|#elif|#ifndef)\\b",next:"directive"},{token:"keyword",regex:"(?:#endif)\\b"},{token:"support.function.C99.c",regex:o},{token:u,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}],directive:[{token:"constant.other.multiline",regex:/\\/},{token:"constant.other",regex:"\\s*<.+?>",next:"start"},{token:"constant.other",regex:'\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]',next:"start"},{token:"constant.other",regex:"\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']",next:"start"},{token:"constant.other.multiline",regex:/.*\\/},{token:"constant.other",regex:/[^\\\/]+/,next:"start"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(u,s),t.c_cppHighlightRules=u}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-clojure.js b/common/static/js/vendor/ace/mode-clojure.js new file mode 100644 index 0000000000..2b9d49eace --- /dev/null +++ b/common/static/js/vendor/ace/mode-clojure.js @@ -0,0 +1 @@ +ace.define("ace/mode/clojure",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/clojure_highlight_rules","ace/mode/matching_parens_outdent","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./clojure_highlight_rules").ClojureHighlightRules,u=e("./matching_parens_outdent").MatchingParensOutdent,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u};r.inherits(f,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)#/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,";")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/[\(\[]/);o&&(r+=" "),o=t.match(/[\)]/),o&&(r="")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/clojure_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="* *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - -> ->> .. / < <= = == > > >= >= accessor aclone add-classpath add-watch agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq zero? zipmap",t="throw try var def do fn if let loop monitor-enter monitor-exit new quote recur set!",n="true false nil",r=this.createKeywordMapper({keyword:t,"constant.language":n,"support.function":e},"identifier",!1," ");this.$rules={start:[{token:"comment",regex:";.*$"},{token:"keyword",regex:"[\\(|\\)]"},{token:"keyword",regex:"[\\'\\(]"},{token:"keyword",regex:"[\\[|\\]]"},{token:"keyword",regex:"[\\{|\\}|\\#\\{|\\#\\}]"},{token:"keyword",regex:"[\\&]"},{token:"keyword",regex:"[\\#\\^\\{]"},{token:"keyword",regex:"[\\%]"},{token:"keyword",regex:"[@]"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"[!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+||=|!=|<=|>=|<>|<|>|!|&&]"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$\\-]*\\b"},{token:"string",regex:'"',next:"string"},{token:"string",regex:/:[\w*+!\-_?:\/]+/},{token:"string.regexp",regex:'/#"(?:\\.|(?:\\")|[^""\n])*"/g'}],string:[{token:"constant.language.escape",regex:"\\\\.|\\\\$"},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}]}};r.inherits(s,i),t.ClojureHighlightRules=s}),ace.define("ace/mode/matching_parens_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\)/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\))/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingParensOutdent=i}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-coffee.js b/common/static/js/vendor/ace/mode-coffee.js new file mode 100644 index 0000000000..f712ad15f5 --- /dev/null +++ b/common/static/js/vendor/ace/mode-coffee.js @@ -0,0 +1 @@ +ace.define("ace/mode/coffee",["require","exports","module","ace/tokenizer","ace/mode/coffee_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/coffee","ace/range","ace/mode/text","ace/worker/worker_client","ace/lib/oop"],function(e,t,n){function c(){this.$tokenizer=new r((new i).getRules()),this.$outdent=new s,this.foldingRules=new o}var r=e("../tokenizer").Tokenizer,i=e("./coffee_highlight_rules").CoffeeHighlightRules,s=e("./matching_brace_outdent").MatchingBraceOutdent,o=e("./folding/coffee").FoldMode,u=e("../range").Range,a=e("./text").Mode,f=e("../worker/worker_client").WorkerClient,l=e("../lib/oop");l.inherits(c,a),function(){var e=/(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/,t=/^(\s*)#/,n=/^\s*###(?!#)/,r=/^\s*/;this.getNextLineIndent=function(t,n,r){var i=this.$getIndent(n),s=this.$tokenizer.getLineTokens(n,t).tokens;return(!s.length||s[s.length-1].type!=="comment")&&t==="start"&&e.test(n)&&(i+=r),i},this.toggleCommentLines=function(e,i,s,o){console.log("toggle");var a=new u(0,0,0,0);for(var f=s;f<=o;++f){var l=i.getLine(f);if(n.test(l))continue;t.test(l)?l=l.replace(t,"$1"):l=l.replace(r,"$&#"),a.end.row=a.start.row=f,a.end.column=l.length+1,i.replace(a,l)}},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/coffee_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("error",function(t){e.setAnnotations([t.data])}),t.on("ok",function(t){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/coffee_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){function s(){var e="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",t={token:"string",regex:".+"},n="this|throw|then|try|typeof|super|switch|return|break|by|continue|catch|class|in|instanceof|is|isnt|if|else|extends|for|forown|finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|or|on|unless|until|and|yes",r="true|false|null|undefined|NaN|Infinity",i="case|const|default|function|var|void|with|enum|export|implements|interface|let|package|private|protected|public|static|yield|__hasProp|slice|bind|indexOf",s="Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|String|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray",o="Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|encodeURIComponent|decodeURI|decodeURIComponent|String|",u="window|arguments|prototype|document",a=this.createKeywordMapper({keyword:n,"constant.language":r,"invalid.illegal":i,"language.support.class":s,"language.support.function":o,"variable.language":u},"identifier"),f={"({args})->":{token:["paren.lparen","text","paren.lparen","text","variable.parameter","text","paren.rparen","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)(\\{)(\\s*)([$@A-Za-z_\\x7f-\\uffff][$@\\w\\s,\\x7f-\\uffff]*)(\\s*)(\\})(\\s*)(\\))(\\s*)([\\-=]>)"},"({})->":{token:["paren.lparen","text","paren.lparen","text","paren.rparen","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)(\\{)(\\s*)(\\})(\\s*)(\\))(\\s*)([\\-=]>)"},"(args)->":{token:["paren.lparen","text","variable.parameter","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)([$@A-Za-z_\\x7f-\\uffff][\\s\\x21-\\uffff]*)(\\s*)(\\))(\\s*)([\\-=]>)"},"()->":{token:["paren.lparen","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)(\\))(\\s*)([\\-=]>)"}};this.$rules={start:[{token:"constant.numeric",regex:"(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"},{token:"string",regex:"'''",next:"qdoc"},{token:"string",regex:'"""',next:"qqdoc"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"string",regex:"`",next:"js"},{token:"string.regex",regex:"///",next:"heregex"},{token:"string.regex",regex:/(?:\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)(?:[imgy]{0,4})(?!\w)/},{token:"comment",regex:"###(?!#)",next:"comment"},{token:"comment",regex:"#.*"},{token:["punctuation.operator","identifier"],regex:"(\\.)("+i+")"},{token:"punctuation.operator",regex:"\\."},{token:["keyword","text","language.support.class","text","keyword","text","language.support.class"],regex:"(class)(\\s+)("+e+")(\\s+)(extends)(\\s+)("+e+")"},{token:["keyword","text","language.support.class"],regex:"(class)(\\s+)("+e+")"},{token:["entity.name.function","text","keyword.operator","text"].concat(f["({args})->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["({args})->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["({args})->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["({args})->"].regex},{token:["entity.name.function","text","keyword.operator","text"].concat(f["({})->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["({})->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["({})->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["({})->"].regex},{token:["entity.name.function","text","keyword.operator","text"].concat(f["(args)->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["(args)->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["(args)->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["(args)->"].regex},{token:["entity.name.function","text","keyword.operator","text"].concat(f["()->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["()->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["()->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["()->"].regex},{token:["entity.name.function","text","keyword.operator","text","storage.type"],regex:"("+e+")(\\s*)(=)(\\s*)([\\-=]>)"},{token:["entity.name.function","text","punctuation.operator","text","storage.type"],regex:"("+e+")(\\s*)(:)(\\s*)([\\-=]>)"},f["({args})->"],f["({})->"],f["(args)->"],f["()->"],{token:"identifier",regex:"(?:(?:\\.|::)\\s*)"+e},{token:"variable",regex:"@(?:"+e+")?"},{token:a,regex:e},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\."},{token:"storage.type",regex:"[\\-=]>"},{token:"keyword.operator",regex:"(?:[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|[!*+-=><])"},{token:"paren.lparen",regex:"[({[]"},{token:"paren.rparen",regex:"[\\]})]"},{token:"text",regex:"\\s+"}],qdoc:[{token:"string",regex:".*?'''",next:"start"},t],qqdoc:[{token:"string",regex:'.*?"""',next:"start"},t],qstring:[{token:"string",regex:"[^\\\\']*(?:\\\\.[^\\\\']*)*'",next:"start"},t],qqstring:[{token:"string",regex:'[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',next:"start"},t],js:[{token:"string",regex:"[^\\\\`]*(?:\\\\.[^\\\\`]*)*`",next:"start"},t],heregex:[{token:"string.regex",regex:".*?///[imgy]{0,4}",next:"start"},{token:"comment.regex",regex:"\\s+(?:#.*)?"},{token:"string.regex",regex:"\\S+"}],comment:[{token:"comment",regex:".*?###",next:"start"},{token:"comment",regex:".+"}]}}var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules;r.inherits(s,i),t.CoffeeHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},i.tag(this.$rules,"tag","start")};r.inherits(o,s),t.XmlHighlightRules=o}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../lib/lang"),s=e("../../range").Range,o=e("./fold_mode").FoldMode,u=e("../../token_iterator").TokenIterator,a=t.FoldMode=function(e){o.call(this),this.voidElements=e||{}};r.inherits(a,o),function(){this.getFoldWidget=function(e,t,n){var r=this._getFirstTagInLine(e,n);return r.closing?t=="markbeginend"?"end":"":!r.tagName||this.voidElements[r.tagName.toLowerCase()]?"":r.selfClosing?"":r.value.indexOf("/"+r.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(e,t){var n=e.getTokens(t),r="";for(var s=0;s?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/coldfusion_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/text_highlight_rules","ace/mode/xml_util"],function(e,t,n){var r=e("../lib/oop"),i=e("./css_highlight_rules").CssHighlightRules,s=e("./javascript_highlight_rules").JavaScriptHighlightRules,o=e("./text_highlight_rules").TextHighlightRules,u=e("./xml_util"),a=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<(?=script)",next:"script"},{token:"meta.tag",regex:"<(?=style)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start"),u.tag(this.$rules,"style","css-start"),u.tag(this.$rules,"script","js-start"),this.embedRules(s,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(i,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(a,o),t.ColdfusionHighlightRules=a}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-csharp.js b/common/static/js/vendor/ace/mode-csharp.js new file mode 100644 index 0000000000..b69c05456e --- /dev/null +++ b/common/static/js/vendor/ace/mode-csharp.js @@ -0,0 +1 @@ +ace.define("ace/mode/csharp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/csharp_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./csharp_highlight_rules").CSharpHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new a,this.foldingRules=new f};r.inherits(l,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[]\s*$/);o&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){return null}}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/csharp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"this",keyword:"abstract|event|new|struct|as|explicit|null|switch|base|extern|object|this|bool|false|operator|throw|break|finally|out|true|byte|fixed|override|try|case|float|params|typeof|catch|for|private|uint|char|foreach|protected|ulong|checked|goto|public|unchecked|class|if|readonly|unsafe|const|implicit|ref|ushort|continue|in|return|using|decimal|int|sbyte|virtual|default|interface|sealed|volatile|delegate|internal|short|void|do|is|sizeof|while|double|lock|stackalloc|else|long|static|enum|namespace|string|var|dynamic","constant.language":"null|true|false"},"identifier");this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:e,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.CSharpHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-css.js b/common/static/js/vendor/ace/mode-css.js new file mode 100644 index 0000000000..305980afac --- /dev/null +++ b/common/static/js/vendor/ace/mode-css.js @@ -0,0 +1 @@ +ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-curly.js b/common/static/js/vendor/ace/mode-curly.js new file mode 100644 index 0000000000..1dfbff17ef --- /dev/null +++ b/common/static/js/vendor/ace/mode-curly.js @@ -0,0 +1 @@ +ace.define("ace/mode/curly",["require","exports","module","ace/lib/oop","ace/mode/html","ace/tokenizer","ace/mode/matching_brace_outdent","ace/mode/html_highlight_rules","ace/mode/folding/html","ace/mode/curly_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./html").Mode,s=e("../tokenizer").Tokenizer,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./html_highlight_rules").HtmlHighlightRules,a=e("./folding/html").FoldMode,f=e("./curly_highlight_rules").CurlyHighlightRules,l=function(){var e=new f;this.$outdent=new o,this.foldingRules=new a,this.$tokenizer=new s(e.getRules())};r.inherits(l,i),function(){}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/html","ace/mode/folding/html"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("./javascript").Mode,o=e("./css").Mode,u=e("../tokenizer").Tokenizer,a=e("./html_highlight_rules").HtmlHighlightRules,f=e("./behaviour/html").HtmlBehaviour,l=e("./folding/html").FoldMode,c=function(){var e=new a;this.$tokenizer=new u(e.getRules()),this.$behaviour=new f,this.$embeds=e.getEmbeds(),this.createModeDelegates({"js-":s,"css-":o}),this.foldingRules=new l};r.inherits(c,i),function(){this.toggleCommentLines=function(e,t,n,r){return 0},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/html",["require","exports","module","ace/lib/oop","ace/mode/behaviour/xml","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function a(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour/xml").XmlBehaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,u=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],f=function(){this.inherit(i),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),f=new o(r,s.row,s.column),l=f.getCurrentToken(),c=!1;if(!l||!a(l,"meta.tag")&&(!a(l,"text")||!l.value.match("/"))){do l=f.stepBackward();while(l&&(a(l,"string")||a(l,"keyword.operator")||a(l,"entity.attribute-name")||a(l,"text")))}else c=!0;if(!l||!a(l,"meta.tag-name")||f.stepBackward().value.match("/"))return;var h=l.value;if(c)var h=h.substring(0,s.column-l.start);if(u.indexOf(h)!==-1)return;return{text:">",selection:[1,1]}}})};r.inherits(f,i),t.HtmlBehaviour=f}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}),ace.define("ace/mode/curly_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/html_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./html_highlight_rules").HtmlHighlightRules,s=function(){var e={start:[{token:"variable",regex:"{{",next:"curly_mode"}],curly_mode:[{token:"variable",regex:"}}",next:"start"}]},t=(new i).getRules();t.start=e.start.concat(t.start),t.curly_mode=e.curly_mode,this.$rules=t};r.inherits(s,i),t.CurlyHighlightRules=s}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-dart.js b/common/static/js/vendor/ace/mode-dart.js new file mode 100644 index 0000000000..f41e6ac053 --- /dev/null +++ b/common/static/js/vendor/ace/mode-dart.js @@ -0,0 +1 @@ +ace.define("ace/mode/dart",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/dart_highlight_rules","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./dart_highlight_rules").DartHighlightRules,u=e("./folding/cstyle").FoldMode,a=function(){var e=new o;this.foldingRules=new u,this.$tokenizer=new s(e.getRules())};r.inherits(a,i),function(){}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/dart_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="true|false|null",t="this|super",n="try|catch|finally|throw|break|case|continue|default|do|else|for|if|in|return|switch|while|new",r="abstract|class|extends|external|factory|implements|interface|get|native|operator|set|typedef",i="static|final|const",s="void|bool|num|int|double|Dynamic|var|String",o=this.createKeywordMapper({"constant.language.dart":e,"variable.language.dart":t,"keyword.control.dart":n,"keyword.declaration.dart":r,"storage.modifier.dart":i,"storage.type.primitive.dart":s},"identifier"),u={token:"string",regex:".+"};this.$rules={start:[{token:"comment",regex:/\/\/.*$/},{token:"comment",regex:/\/\*/,next:"comment"},{token:["meta.preprocessor.script.dart"],regex:"^(#!.*)$"},{token:["keyword.other.import.dart","meta.declaration.dart"],regex:"#(?:\\b)(?:library|import|source|resource)(?:\\b)"},{token:["keyword.other.import.dart","text"],regex:"(?:\\b)(prefix)(\\s*:)"},{regex:"\\bas\\b",token:"keyword.cast.dart"},{regex:"\\?|:",token:"keyword.control.ternary.dart"},{regex:"(?:\\b)(is\\!?)(?:\\b)",token:["keyword.operator.dart"]},{regex:"(<<|>>>?|~|\\^|\\||&)",token:["keyword.operator.bitwise.dart"]},{regex:"((?:&|\\^|\\||<<|>>>?)=)",token:["keyword.operator.assignment.bitwise.dart"]},{regex:"(===?|!==?|<=?|>=?)",token:["keyword.operator.comparison.dart"]},{regex:"((?:[+*/%-]|\\~)=)",token:["keyword.operator.assignment.arithmetic.dart"]},{regex:"=",token:"keyword.operator.assignment.dart"},{token:"string",regex:"'''",next:"qdoc"},{token:"string",regex:'"""',next:"qqdoc"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{regex:"(\\-\\-|\\+\\+)",token:["keyword.operator.increment-decrement.dart"]},{regex:"(\\-|\\+|\\*|\\/|\\~\\/|%)",token:["keyword.operator.arithmetic.dart"]},{regex:"(!|&&|\\|\\|)",token:["keyword.operator.logical.dart"]},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:o,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qdoc:[{token:"string",regex:".*?'''",next:"start"},u],qqdoc:[{token:"string",regex:'.*?"""',next:"start"},u],qstring:[{token:"string",regex:"[^\\\\']*(?:\\\\.[^\\\\']*)*'",next:"start"},u],qqstring:[{token:"string",regex:'[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',next:"start"},u]}};r.inherits(s,i),t.DartHighlightRules=s}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-diff.js b/common/static/js/vendor/ace/mode-diff.js new file mode 100644 index 0000000000..64266565bf --- /dev/null +++ b/common/static/js/vendor/ace/mode-diff.js @@ -0,0 +1 @@ +ace.define("ace/mode/diff",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/diff_highlight_rules","ace/mode/folding/diff"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./diff_highlight_rules").DiffHighlightRules,u=e("./folding/diff").FoldMode,a=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.foldingRules=new u(["diff","index","\\+{3}","@@|\\*{5}"],"i")};r.inherits(a,i),function(){}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/diff_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{regex:"^(?:\\*{15}|={67}|-{3}|\\+{3})$",token:"punctuation.definition.separator.diff",name:"keyword"},{regex:"^(@@)(\\s*.+?\\s*)(@@)(.*)$",token:["constant","constant.numeric","constant","comment.doc.tag"]},{regex:"^(\\d+)([,\\d]+)(a|d|c)(\\d+)([,\\d]+)(.*)$",token:["constant.numeric","punctuation.definition.range.diff","constant.function","constant.numeric","punctuation.definition.range.diff","invalid"],name:"meta."},{regex:"^(?:(\\-{3}|\\+{3}|\\*{3})( .+))$",token:["constant.numeric","meta.tag"]},{regex:"^([!+>])(.*?)(\\s*)$",token:["support.constant","text","invalid"]},{regex:"^([<\\-])(.*?)(\\s*)$",token:["support.function","string","invalid"]},{regex:"^(diff)(\\s+--\\w+)?(.+?)( .+)?$",token:["variable","variable","keyword","variable"]},{regex:"^Index.+$",token:"variable"},{regex:"^(.*?)(\\s*)$",token:["invisible","invalid"]}]}};r.inherits(s,i),t.DiffHighlightRules=s}),ace.define("ace/mode/folding/diff",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(e,t){this.regExpList=e,this.flag=t,this.foldingStartMarker=RegExp("^("+e.join("|")+")",this.flag)};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i={row:n,column:r.length},o=this.regExpList;for(var u=1;u<=o.length;u++){var a=RegExp("^("+o.slice(0,u).join("|")+")",this.flag);if(a.test(r))break}for(var f=e.getLength();++n/},{token:"punctuation.operator",regex:/,|;/},{token:"paren.lparen",regex:/[\[{]/},{token:"paren.rparen",regex:/[\]}]/},{token:"comment",regex:/^#!.*$/},{token:function(n){return e.hasOwnProperty(n.toLowerCase())?"keyword":t.hasOwnProperty(n.toLowerCase())?"variable":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'[^"\\\\]+',merge:!0},{token:"string",regex:"\\\\$",next:"qqstring",merge:!0},{token:"string",regex:'"|$',next:"start",merge:!0}],qstring:[{token:"string",regex:"[^'\\\\]+",merge:!0},{token:"string",regex:"\\\\$",next:"qstring",merge:!0},{token:"string",regex:"'|$",next:"start",merge:!0}]}};r.inherits(u,s),t.DotHighlightRules=u}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-glsl.js b/common/static/js/vendor/ace/mode-glsl.js new file mode 100644 index 0000000000..516e732a50 --- /dev/null +++ b/common/static/js/vendor/ace/mode-glsl.js @@ -0,0 +1 @@ +ace.define("ace/mode/glsl",["require","exports","module","ace/lib/oop","ace/mode/c_cpp","ace/tokenizer","ace/mode/glsl_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./c_cpp").Mode,s=e("../tokenizer").Tokenizer,o=e("./glsl_highlight_rules").glslHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),t.Mode=c}),ace.define("ace/mode/c_cpp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/c_cpp_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./c_cpp_highlight_rules").c_cppHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var u=t.match(/^.*[\{\(\[]\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/c_cpp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=t.cFunctions="\\s*\\bhypot(?:f|l)?|s(?:scanf|ystem|nprintf|ca(?:nf|lb(?:n(?:f|l)?|ln(?:f|l)?))|i(?:n(?:h(?:f|l)?|f|l)?|gn(?:al|bit))|tr(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?)|error|pbrk|ftime|len|rchr|xfrm)|printf|et(?:jmp|vbuf|locale|buf)|qrt(?:f|l)?|w(?:scanf|printf)|rand)|n(?:e(?:arbyint(?:f|l)?|xt(?:toward(?:f|l)?|after(?:f|l)?))|an(?:f|l)?)|c(?:s(?:in(?:h(?:f|l)?|f|l)?|qrt(?:f|l)?)|cos(?:h(?:f)?|f|l)?|imag(?:f|l)?|t(?:ime|an(?:h(?:f|l)?|f|l)?)|o(?:s(?:h(?:f|l)?|f|l)?|nj(?:f|l)?|pysign(?:f|l)?)|p(?:ow(?:f|l)?|roj(?:f|l)?)|e(?:il(?:f|l)?|xp(?:f|l)?)|l(?:o(?:ck|g(?:f|l)?)|earerr)|a(?:sin(?:h(?:f|l)?|f|l)?|cos(?:h(?:f|l)?|f|l)?|tan(?:h(?:f|l)?|f|l)?|lloc|rg(?:f|l)?|bs(?:f|l)?)|real(?:f|l)?|brt(?:f|l)?)|t(?:ime|o(?:upper|lower)|an(?:h(?:f|l)?|f|l)?|runc(?:f|l)?|gamma(?:f|l)?|mp(?:nam|file))|i(?:s(?:space|n(?:ormal|an)|cntrl|inf|digit|u(?:nordered|pper)|p(?:unct|rint)|finite|w(?:space|c(?:ntrl|type)|digit|upper|p(?:unct|rint)|lower|al(?:num|pha)|graph|xdigit|blank)|l(?:ower|ess(?:equal|greater)?)|al(?:num|pha)|gr(?:eater(?:equal)?|aph)|xdigit|blank)|logb(?:f|l)?|max(?:div|abs))|di(?:v|fftime)|_Exit|unget(?:c|wc)|p(?:ow(?:f|l)?|ut(?:s|c(?:har)?|wc(?:har)?)|error|rintf)|e(?:rf(?:c(?:f|l)?|f|l)?|x(?:it|p(?:2(?:f|l)?|f|l|m1(?:f|l)?)?))|v(?:s(?:scanf|nprintf|canf|printf|w(?:scanf|printf))|printf|f(?:scanf|printf|w(?:scanf|printf))|w(?:scanf|printf)|a_(?:start|copy|end|arg))|qsort|f(?:s(?:canf|e(?:tpos|ek))|close|tell|open|dim(?:f|l)?|p(?:classify|ut(?:s|c|w(?:s|c))|rintf)|e(?:holdexcept|set(?:e(?:nv|xceptflag)|round)|clearexcept|testexcept|of|updateenv|r(?:aiseexcept|ror)|get(?:e(?:nv|xceptflag)|round))|flush|w(?:scanf|ide|printf|rite)|loor(?:f|l)?|abs(?:f|l)?|get(?:s|c|pos|w(?:s|c))|re(?:open|e|ad|xp(?:f|l)?)|m(?:in(?:f|l)?|od(?:f|l)?|a(?:f|l|x(?:f|l)?)?))|l(?:d(?:iv|exp(?:f|l)?)|o(?:ngjmp|cal(?:time|econv)|g(?:1(?:p(?:f|l)?|0(?:f|l)?)|2(?:f|l)?|f|l|b(?:f|l)?)?)|abs|l(?:div|abs|r(?:int(?:f|l)?|ound(?:f|l)?))|r(?:int(?:f|l)?|ound(?:f|l)?)|gamma(?:f|l)?)|w(?:scanf|c(?:s(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?|mbs)|pbrk|ftime|len|r(?:chr|tombs)|xfrm)|to(?:b|mb)|rtomb)|printf|mem(?:set|c(?:hr|py|mp)|move))|a(?:s(?:sert|ctime|in(?:h(?:f|l)?|f|l)?)|cos(?:h(?:f|l)?|f|l)?|t(?:o(?:i|f|l(?:l)?)|exit|an(?:h(?:f|l)?|2(?:f|l)?|f|l)?)|b(?:s|ort))|g(?:et(?:s|c(?:har)?|env|wc(?:har)?)|mtime)|r(?:int(?:f|l)?|ound(?:f|l)?|e(?:name|alloc|wind|m(?:ove|quo(?:f|l)?|ainder(?:f|l)?))|a(?:nd|ise))|b(?:search|towc)|m(?:odf(?:f|l)?|em(?:set|c(?:hr|py|mp)|move)|ktime|alloc|b(?:s(?:init|towcs|rtowcs)|towc|len|r(?:towc|len)))\\b",u=function(){var e="break|case|continue|default|do|else|for|goto|if|_Pragma|return|switch|while|catch|operator|try|throw|using",t="asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|_Imaginary|int|long|short|signed|struct|typedef|union|unsigned|void|class|wchar_t|template",n="const|extern|register|restrict|static|volatile|inline|private:|protected:|public:|friend|explicit|virtual|export|mutable|typename",r="and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eqconst_cast|dynamic_cast|reinterpret_cast|static_cast|sizeof|namespace",s="NULL|true|false|TRUE|FALSE",u=this.$keywords=this.createKeywordMapper({"keyword.control":e,"storage.type":t,"storage.modifier":n,"keyword.operator":r,"variable.language":"this","constant.language":s},"identifier"),a="[a-zA-Z\\$_¡-ï¿¿][a-zA-Zd\\$_¡-ï¿¿]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"keyword",regex:"(?:#include|#import|#pragma|#line|#define|#undef|#if|#ifdef|#else|#elif|#ifndef)\\b",next:"directive"},{token:"keyword",regex:"(?:#endif)\\b"},{token:"support.function.C99.c",regex:o},{token:u,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}],directive:[{token:"constant.other.multiline",regex:/\\/},{token:"constant.other",regex:"\\s*<.+?>",next:"start"},{token:"constant.other",regex:'\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]',next:"start"},{token:"constant.other",regex:"\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']",next:"start"},{token:"constant.other.multiline",regex:/.*\\/},{token:"constant.other",regex:/[^\\\/]+/,next:"start"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(u,s),t.c_cppHighlightRules=u}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/glsl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/c_cpp_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./c_cpp_highlight_rules").c_cppHighlightRules,s=function(){var e="attribute|const|uniform|varying|break|continue|do|for|while|if|else|in|out|inout|float|int|void|bool|true|false|lowp|mediump|highp|precision|invariant|discard|return|mat2|mat3|mat4|vec2|vec3|vec4|ivec2|ivec3|ivec4|bvec2|bvec3|bvec4|sampler2D|samplerCube|struct",t="radians|degrees|sin|cos|tan|asin|acos|atan|pow|exp|log|exp2|log2|sqrt|inversesqrt|abs|sign|floor|ceil|fract|mod|min|max|clamp|mix|step|smoothstep|length|distance|dot|cross|normalize|faceforward|reflect|refract|matrixCompMult|lessThan|lessThanEqual|greaterThan|greaterThanEqual|equal|notEqual|any|all|not|dFdx|dFdy|fwidth|texture2D|texture2DProj|texture2DLod|texture2DProjLod|textureCube|textureCubeLod|gl_MaxVertexAttribs|gl_MaxVertexUniformVectors|gl_MaxVaryingVectors|gl_MaxVertexTextureImageUnits|gl_MaxCombinedTextureImageUnits|gl_MaxTextureImageUnits|gl_MaxFragmentUniformVectors|gl_MaxDrawBuffers|gl_DepthRangeParameters|gl_DepthRange|gl_Position|gl_PointSize|gl_FragCoord|gl_FrontFacing|gl_PointCoord|gl_FragColor|gl_FragData",n=this.createKeywordMapper({"variable.language":"this",keyword:e,"constant.language":t},"identifier");this.$rules=(new i).$rules,this.$rules.start.forEach(function(e){typeof e.token=="function"&&(e.token=n)})};r.inherits(s,i),t.glslHighlightRules=s}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-golang.js b/common/static/js/vendor/ace/mode-golang.js new file mode 100644 index 0000000000..c2324176bc --- /dev/null +++ b/common/static/js/vendor/ace/mode-golang.js @@ -0,0 +1 @@ +ace.define("ace/mode/golang",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/golang_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./golang_highlight_rules").GolangHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.foldingRules=new f};r.inherits(l,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new Range(0,0,0,0);for(var o=n;o<=r;o++){var a=t.getLine(o),f=a.match(s);u.start.row=o,u.end.row=o,u.end.column=f[0].length,t.replace(u,f[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var u=t.match(/^.*[\{\(\[]\s*$/);u&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/golang_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e="true|else|false|break|case|return|goto|if|const|continue|struct|default|switch|for|func|import|package|chan|defer|fallthrough|go|interface|map|rangeselect|type|var",t="nil|true|false|iota",n=this.createKeywordMapper({"variable.language":"this",keyword:e,"constant.language":t},"identifier");this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant",regex:"<[a-zA-Z0-9.]+>"},{token:"keyword",regex:"(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)"},{token:n,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.GolangHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-groovy.js b/common/static/js/vendor/ace/mode-groovy.js new file mode 100644 index 0000000000..9c35406fc1 --- /dev/null +++ b/common/static/js/vendor/ace/mode-groovy.js @@ -0,0 +1 @@ +ace.define("ace/mode/groovy",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/groovy_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./javascript").Mode,s=e("../tokenizer").Tokenizer,o=e("./groovy_highlight_rules").GroovyHighlightRules,u=function(){i.call(this),this.$tokenizer=new s((new o).getRules())};r.inherits(u,i),function(){this.createWorker=function(e){return null}}.call(u.prototype),t.Mode=u}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/groovy_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e="assert|with|abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|def|float|native|super|while",t="null|Infinity|NaN|undefined",n="AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object",r=this.createKeywordMapper({"variable.language":"this",keyword:e,"support.function":n,"constant.language":t},"identifier");this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'"""',next:"qqstring"},{token:"string",regex:"'''",next:"qstring"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\?:|\\?\\.|\\*\\.|<=>|=~|==~|\\.@|\\*\\.@|\\.&|as|in|is|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:/\\(?:u[0-9A-Fa-f]{4}|.|$)/},{token:"constant.language.escape",regex:/\$[\w\d]+/},{token:"constant.language.escape",regex:/\$\{[^"\}]+\}?/},{token:"string",regex:'"{3,5}',next:"start"},{token:"string",regex:".+?"}],qstring:[{token:"constant.language.escape",regex:/\\(?:u[0-9A-Fa-f]{4}|.|$)/},{token:"string",regex:"'{3,5}",next:"start"},{token:"string",regex:".+?"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.GroovyHighlightRules=o}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-haml.js b/common/static/js/vendor/ace/mode-haml.js new file mode 100644 index 0000000000..ec95a39933 --- /dev/null +++ b/common/static/js/vendor/ace/mode-haml.js @@ -0,0 +1 @@ +ace.define("ace/mode/haml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/haml_highlight_rules","ace/mode/folding/coffee"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./haml_highlight_rules").HamlHighlightRules,u=e("./folding/coffee").FoldMode,a=function(){var e=new o;this.foldingRules=new u,this.$tokenizer=new s(e.getRules())};r.inherits(a,i),function(){}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/haml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/ruby_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=e("./ruby_highlight_rules"),o=s.RubyHighlightRules,u=function(){this.$rules={start:[{token:"punctuation.section.comment",regex:/^\s*\/.*/},{token:"punctuation.section.comment",regex:/^\s*#.*/},{token:"string.quoted.double",regex:"==.+?=="},{token:"keyword.other.doctype",regex:"^!!!\\s*(?:[a-zA-Z0-9-_]+)?"},s.qString,s.qqString,s.tString,{token:["entity.name.tag.haml"],regex:/^\s*%[\w:]+/,next:"tag_single"},{token:["meta.escape.haml"],regex:"^\\s*\\\\."},s.constantNumericHex,s.constantNumericFloat,s.constantOtherSymbol,{token:"text",regex:"=|-|~",next:"embedded_ruby"}],tag_single:[{token:"entity.other.attribute-name.class.haml",regex:"\\.[\\w-]+"},{token:"entity.other.attribute-name.id.haml",regex:"#[\\w-]+"},{token:"punctuation.section",regex:"\\{",next:"section"},s.constantOtherSymbol,{token:"text",regex:/\s/,next:"start"},{token:["text","punctuation"],regex:"($)|((?!\\.|#|\\{|\\[|=|-|~|\\/))",next:"start"}],section:[s.constantOtherSymbol,s.qString,s.qqString,s.tString,s.constantNumericHex,s.constantNumericFloat,{token:"punctuation.section",regex:"\\}",next:"start"}],embedded_ruby:[s.constantNumericHex,s.constantNumericFloat,{token:"support.class",regex:"[A-Z][a-zA-Z_\\d]+"},{token:(new o).getKeywords(),regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:["keyword","text","text"],regex:"(?:do|\\{)(?: \\|[^|]+\\|)?$",next:"start"},{token:["text"],regex:"^$",next:"start"},{token:["text"],regex:"^(?!.*\\|\\s*$)",next:"start"}]}};r.inherits(u,i),t.HamlHighlightRules=u}),ace.define("ace/mode/ruby_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=t.constantOtherSymbol={token:"constant.other.symbol.ruby",regex:"[:](?:[A-Za-z_]|[@$](?=[a-zA-Z0-9_]))[a-zA-Z0-9_]*[!=?]?"},o=t.qString={token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},u=t.qqString={token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},a=t.tString={token:"string",regex:"[`](?:(?:\\\\.)|(?:[^'\\\\]))*?[`]"},f=t.constantNumericHex={token:"constant.numeric",regex:"0[xX][0-9a-fA-F](?:[0-9a-fA-F]|_(?=[0-9a-fA-F]))*\\b"},l=t.constantNumericFloat={token:"constant.numeric",regex:"[+-]?\\d(?:\\d|_(?=\\d))*(?:(?:\\.\\d(?:\\d|_(?=\\d))*)?(?:[eE][+-]?\\d+)?)?\\b"},c=function(){var e="abort|Array|assert|assert_equal|assert_not_equal|assert_same|assert_not_same|assert_nil|assert_not_nil|assert_match|assert_no_match|assert_in_delta|assert_throws|assert_raise|assert_nothing_raised|assert_instance_of|assert_kind_of|assert_respond_to|assert_operator|assert_send|assert_difference|assert_no_difference|assert_recognizes|assert_generates|assert_response|assert_redirected_to|assert_template|assert_select|assert_select_email|assert_select_rjs|assert_select_encoded|css_select|at_exit|attr|attr_writer|attr_reader|attr_accessor|attr_accessible|autoload|binding|block_given?|callcc|caller|catch|chomp|chomp!|chop|chop!|defined?|delete_via_redirect|eval|exec|exit|exit!|fail|Float|flunk|follow_redirect!|fork|form_for|form_tag|format|gets|global_variables|gsub|gsub!|get_via_redirect|h|host!|https?|https!|include|Integer|lambda|link_to|link_to_unless_current|link_to_function|link_to_remote|load|local_variables|loop|open|open_session|p|print|printf|proc|putc|puts|post_via_redirect|put_via_redirect|raise|rand|raw|readline|readlines|redirect?|request_via_redirect|require|scan|select|set_trace_func|sleep|split|sprintf|srand|String|stylesheet_link_tag|syscall|system|sub|sub!|test|throw|trace_var|trap|untrace_var|atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan|render|javascript_include_tag|csrf_meta_tag|label_tag|text_field_tag|submit_tag|check_box_tag|content_tag|radio_button_tag|text_area_tag|password_field_tag|hidden_field_tag|fields_for|select_tag|options_for_select|options_from_collection_for_select|collection_select|time_zone_select|select_date|select_time|select_datetime|date_select|time_select|datetime_select|select_year|select_month|select_day|select_hour|select_minute|select_second|file_field_tag|file_field|respond_to|skip_before_filter|around_filter|after_filter|verify|protect_from_forgery|rescue_from|helper_method|redirect_to|before_filter|send_data|send_file|validates_presence_of|validates_uniqueness_of|validates_length_of|validates_format_of|validates_acceptance_of|validates_associated|validates_exclusion_of|validates_inclusion_of|validates_numericality_of|validates_with|validates_each|authenticate_or_request_with_http_basic|authenticate_or_request_with_http_digest|filter_parameter_logging|match|get|post|resources|redirect|scope|assert_routing|translate|localize|extract_locale_from_tld|t|l|caches_page|expire_page|caches_action|expire_action|cache|expire_fragment|expire_cache_for|observe|cache_sweeper|has_many|has_one|belongs_to|has_and_belongs_to_many",t="alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|__FILE__|finally|for|gem|if|in|__LINE__|module|next|not|or|private|protected|public|redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield",n="true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING",r="$DEBUG|$defout|$FILENAME|$LOAD_PATH|$SAFE|$stdin|$stdout|$stderr|$VERBOSE|$!|root_url|flash|session|cookies|params|request|response|logger|self",i=this.$keywords=this.createKeywordMapper({keyword:t,"constant.language":n,"variable.language":r,"support.function":e,"invalid.deprecated":"debugger"},"identifier");this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"comment",regex:"^=begin\\s",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},o,u,a,{token:"text",regex:"::"},{token:"variable.instance",regex:"@{1,2}[a-zA-Z_\\d]+"},{token:"support.class",regex:"[A-Z][a-zA-Z_\\d]+"},s,f,l,{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:i,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"punctuation.separator.key-value",regex:"=>"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:"^=end\\s.*$",next:"start"},{token:"comment",regex:".+"}]}};r.inherits(c,i),t.RubyHighlightRules=c}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({<]"},{token:"paren.rparen",regex:"[\\])}>]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.HaxeHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-html.js b/common/static/js/vendor/ace/mode-html.js new file mode 100644 index 0000000000..ac3a13f5b6 --- /dev/null +++ b/common/static/js/vendor/ace/mode-html.js @@ -0,0 +1 @@ +ace.define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/html","ace/mode/folding/html"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("./javascript").Mode,o=e("./css").Mode,u=e("../tokenizer").Tokenizer,a=e("./html_highlight_rules").HtmlHighlightRules,f=e("./behaviour/html").HtmlBehaviour,l=e("./folding/html").FoldMode,c=function(){var e=new a;this.$tokenizer=new u(e.getRules()),this.$behaviour=new f,this.$embeds=e.getEmbeds(),this.createModeDelegates({"js-":s,"css-":o}),this.foldingRules=new l};r.inherits(c,i),function(){this.toggleCommentLines=function(e,t,n,r){return 0},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/html",["require","exports","module","ace/lib/oop","ace/mode/behaviour/xml","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function a(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour/xml").XmlBehaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,u=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],f=function(){this.inherit(i),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),f=new o(r,s.row,s.column),l=f.getCurrentToken(),c=!1;if(!l||!a(l,"meta.tag")&&(!a(l,"text")||!l.value.match("/"))){do l=f.stepBackward();while(l&&(a(l,"string")||a(l,"keyword.operator")||a(l,"entity.attribute-name")||a(l,"text")))}else c=!0;if(!l||!a(l,"meta.tag-name")||f.stepBackward().value.match("/"))return;var h=l.value;if(c)var h=h.substring(0,s.column-l.start);if(u.indexOf(h)!==-1)return;return{text:">",selection:[1,1]}}})};r.inherits(f,i),t.HtmlBehaviour=f}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-jade.js b/common/static/js/vendor/ace/mode-jade.js new file mode 100644 index 0000000000..7e27287046 --- /dev/null +++ b/common/static/js/vendor/ace/mode-jade.js @@ -0,0 +1 @@ +ace.define("ace/mode/jade",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/jade_highlight_rules","ace/mode/folding/coffee"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./jade_highlight_rules").JadeHighlightRules,u=e("./folding/coffee").FoldMode,a=function(){var e=new o;this.$tokenizer=new s(e.getRules()),this.foldingRules=new u};r.inherits(a,i),function(){}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/jade_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/markdown_highlight_rules","ace/mode/scss_highlight_rules","ace/mode/less_highlight_rules","ace/mode/coffee_highlight_rules","ace/mode/javascript_highlight_rules"],function(e,t,n){function l(e,t){return{token:"entity.name.function.jade",regex:"^\\s*\\:"+e,next:t+"start"}}var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=e("./markdown_highlight_rules").MarkdownHighlightRules,o=e("./scss_highlight_rules").ScssHighlightRules,u=e("./less_highlight_rules").LessHighlightRules,a=e("./coffee_highlight_rules").CoffeeHighlightRules,f=e("./javascript_highlight_rules").JavaScriptHighlightRules,c=function(){var e="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"keyword.control.import.include.jade",regex:"\\s*\\binclude\\b"},{token:"keyword.other.doctype.jade",regex:"^!!!\\s*(?:[a-zA-Z0-9-_]+)?"},{token:"punctuation.section.comment",regex:"^\\s*//(?:\\s*[^-\\s]|\\s+\\S)(?:.*$)"},{token:function(e,t){return"punctuation.section.comment"},regex:"^((\\s*)//)(?:\\s*$)",next:"comment_block"},l("markdown","markdown-"),l("sass","sass-"),l("less","less-"),l("coffee","coffee-"),{token:["storage.type.function.jade","entity.name.function.jade","punctuation.definition.parameters.begin.jade","variable.parameter.function.jade","punctuation.definition.parameters.end.jade"],regex:"^(\\s*mixin)( [\\w\\-]+)(\\s*\\()(.*?)(\\))"},{token:["storage.type.function.jade","entity.name.function.jade"],regex:"^(\\s*mixin)( [\\w\\-]+)"},{token:"source.js.embedded.jade",regex:"^\\s*(?:-|=|!=)",next:"js-start"},{token:"string.interpolated.jade",regex:"[#!]\\{[^\\}]+\\}"},{token:["meta.tag.any.jade","entity.variable.tag.jade"],regex:/^\s*(?!\w+\:)(?:[\w]+|(?=\.|#)])/,next:"tag_single"},{token:"suport.type.attribute.id.jade",regex:"#\\w+"},{token:"suport.type.attribute.class.jade",regex:"\\.\\w+"},{token:"punctuation",regex:"\\s*(?:\\()",next:"tag_attributes"}],comment_block:[{token:function(e){return"text"},regex:"^(\\1\\S|$)",captures:"1",next:"start"},{token:"comment.block.jade",regex:".+"}],tag_single:[{token:"entity.other.attribute-name.class.jade",regex:"\\.[\\w-]+"},{token:"entity.other.attribute-name.id.jade",regex:"#[\\w-]+"},{token:["text","punctuation"],regex:"($)|((?!\\.|#|=|-))",next:"start"}],tag_attributes:[{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"entity.other.attribute-name.jade",regex:"\\b[a-zA-Z\\-:]+"},{token:["entity.other.attribute-name.jade","punctuation"],regex:"\\b([a-zA-Z:\\.-]+)(=)",next:"attribute_strings"},{token:"punctuation",regex:"\\)",next:"start"}],attribute_strings:[{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"}],qqstring:[{token:"constant.language.escape",regex:e},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"tag_attributes"}],qstring:[{token:"constant.language.escape",regex:e},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"tag_attributes"}]},this.embedRules(f,"js-",[{token:"text",regex:".$",next:"start"}])};r.inherits(c,i),t.JadeHighlightRules=c}),ace.define("ace/mode/markdown_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/html_highlight_rules","ace/mode/css_highlight_rules"],function(e,t,n){function f(e,t){return{token:"support.function",regex:"^```"+e+"\\s*$",next:t+"start"}}var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=e("./javascript_highlight_rules").JavaScriptHighlightRules,o=e("./xml_highlight_rules").XmlHighlightRules,u=e("./html_highlight_rules").HtmlHighlightRules,a=e("./css_highlight_rules").CssHighlightRules,l=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{token:["support.function","support.function","support.function"],regex:"(`+)([^\\r]*?[^`])(\\1)"},{token:"support.function",regex:"^[ ]{4}.+"},{token:"markup.heading.1",regex:"^=+(?=\\s*$)"},{token:"markup.heading.2",regex:"^\\-+(?=\\s*$)"},{token:function(e){return"markup.heading."+e.search(/[^#]/)},regex:"^#{1,6}(?:[^ #].*| +.*(?:[^ #].*|[^ ]+.* +#+ *))$"},f("(?:javascript|js)","js-"),f("xml","xml-"),f("html","html-"),f("css","css-"),{token:"support.function",regex:"^```\\s*[a-zA-Z]*(?:{.*?\\})?\\s*$",next:"githubblock"},{token:"string",regex:"^>[ ].+$",next:"blockquote"},{token:["text","constant","text","url","string","text"],regex:'^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:["][^"]+["])?(\\s*))$'},{token:["text","string","text","constant","text"],regex:"(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"},{token:["text","string","text","markup.underline","string","text"],regex:'(\\[)(\\[[^\\]]*\\]|[^\\[\\]]*)(\\]\\([ \\t]*)(?)((?:[ ]*"(?:.*?)"[ \\t]*)?)(\\))'},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\*[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\-[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\_[ ]?){3,}\\s*$"},{token:"markup.list",regex:"^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",next:"listblock"},{token:["string","string","string"],regex:"([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:["string","string","string"],regex:"([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:["text","url","text"],regex:"(<)((?:https?|ftp|dict):[^'\">\\s]+|(?:mailto:)?[-.\\w]+\\@[-a-z0-9]+(?:\\.[-a-z0-9]+)*\\.[a-z]+)(>)"},{token:"text",regex:"[^\\*_%$`\\[#<>]+"}],listblock:[{token:"empty_line",regex:"^$",next:"start"},{token:"markup.list",regex:".+"}],blockquote:[{token:"empty_line",regex:"^\\s*$",next:"start"},{token:"string",regex:".+"}],githubblock:[{token:"support.function",regex:"^```",next:"start"},{token:"support.function",regex:".+"}]},this.embedRules(s,"js-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(u,"html-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(a,"css-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(o,"xml-",[{token:"support.function",regex:"^```",next:"start"}]);var e=(new u).getRules();for(var t in e)this.$rules[t]?this.$rules[t]=this.$rules[t].concat(e[t]):this.$rules[t]=e[t]};r.inherits(l,i),t.MarkdownHighlightRules=l}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./xml_util"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},i.tag(this.$rules,"tag","start")};r.inherits(o,s),t.XmlHighlightRules=o}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/scss_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=i.arrayToMap(function(){var e="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),t="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),n="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),r=[];for(var i=0,s=e.length;i|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]}};r.inherits(o,s),t.ScssHighlightRules=o}),ace.define("ace/mode/less_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=i.arrayToMap(function(){var e="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),t="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),n="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),r=[];for(var i=0,s=e.length;i|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}]}};r.inherits(o,s),t.LessHighlightRules=o}),ace.define("ace/mode/coffee_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){function s(){var e="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",t={token:"string",regex:".+"},n="this|throw|then|try|typeof|super|switch|return|break|by|continue|catch|class|in|instanceof|is|isnt|if|else|extends|for|forown|finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|or|on|unless|until|and|yes",r="true|false|null|undefined|NaN|Infinity",i="case|const|default|function|var|void|with|enum|export|implements|interface|let|package|private|protected|public|static|yield|__hasProp|slice|bind|indexOf",s="Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|String|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray",o="Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|encodeURIComponent|decodeURI|decodeURIComponent|String|",u="window|arguments|prototype|document",a=this.createKeywordMapper({keyword:n,"constant.language":r,"invalid.illegal":i,"language.support.class":s,"language.support.function":o,"variable.language":u},"identifier"),f={"({args})->":{token:["paren.lparen","text","paren.lparen","text","variable.parameter","text","paren.rparen","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)(\\{)(\\s*)([$@A-Za-z_\\x7f-\\uffff][$@\\w\\s,\\x7f-\\uffff]*)(\\s*)(\\})(\\s*)(\\))(\\s*)([\\-=]>)"},"({})->":{token:["paren.lparen","text","paren.lparen","text","paren.rparen","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)(\\{)(\\s*)(\\})(\\s*)(\\))(\\s*)([\\-=]>)"},"(args)->":{token:["paren.lparen","text","variable.parameter","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)([$@A-Za-z_\\x7f-\\uffff][\\s\\x21-\\uffff]*)(\\s*)(\\))(\\s*)([\\-=]>)"},"()->":{token:["paren.lparen","text","paren.rparen","text","storage.type"],regex:"(\\()(\\s*)(\\))(\\s*)([\\-=]>)"}};this.$rules={start:[{token:"constant.numeric",regex:"(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"},{token:"string",regex:"'''",next:"qdoc"},{token:"string",regex:'"""',next:"qqdoc"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"string",regex:"`",next:"js"},{token:"string.regex",regex:"///",next:"heregex"},{token:"string.regex",regex:/(?:\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)(?:[imgy]{0,4})(?!\w)/},{token:"comment",regex:"###(?!#)",next:"comment"},{token:"comment",regex:"#.*"},{token:["punctuation.operator","identifier"],regex:"(\\.)("+i+")"},{token:"punctuation.operator",regex:"\\."},{token:["keyword","text","language.support.class","text","keyword","text","language.support.class"],regex:"(class)(\\s+)("+e+")(\\s+)(extends)(\\s+)("+e+")"},{token:["keyword","text","language.support.class"],regex:"(class)(\\s+)("+e+")"},{token:["entity.name.function","text","keyword.operator","text"].concat(f["({args})->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["({args})->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["({args})->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["({args})->"].regex},{token:["entity.name.function","text","keyword.operator","text"].concat(f["({})->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["({})->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["({})->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["({})->"].regex},{token:["entity.name.function","text","keyword.operator","text"].concat(f["(args)->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["(args)->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["(args)->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["(args)->"].regex},{token:["entity.name.function","text","keyword.operator","text"].concat(f["()->"].token),regex:"("+e+")(\\s*)(=)(\\s*)"+f["()->"].regex},{token:["entity.name.function","text","punctuation.operator","text"].concat(f["()->"].token),regex:"("+e+")(\\s*)(:)(\\s*)"+f["()->"].regex},{token:["entity.name.function","text","keyword.operator","text","storage.type"],regex:"("+e+")(\\s*)(=)(\\s*)([\\-=]>)"},{token:["entity.name.function","text","punctuation.operator","text","storage.type"],regex:"("+e+")(\\s*)(:)(\\s*)([\\-=]>)"},f["({args})->"],f["({})->"],f["(args)->"],f["()->"],{token:"identifier",regex:"(?:(?:\\.|::)\\s*)"+e},{token:"variable",regex:"@(?:"+e+")?"},{token:a,regex:e},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\."},{token:"storage.type",regex:"[\\-=]>"},{token:"keyword.operator",regex:"(?:[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|[!*+-=><])"},{token:"paren.lparen",regex:"[({[]"},{token:"paren.rparen",regex:"[\\]})]"},{token:"text",regex:"\\s+"}],qdoc:[{token:"string",regex:".*?'''",next:"start"},t],qqdoc:[{token:"string",regex:'.*?"""',next:"start"},t],qstring:[{token:"string",regex:"[^\\\\']*(?:\\\\.[^\\\\']*)*'",next:"start"},t],qqstring:[{token:"string",regex:'[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',next:"start"},t],js:[{token:"string",regex:"[^\\\\`]*(?:\\\\.[^\\\\`]*)*`",next:"start"},t],heregex:[{token:"string.regex",regex:".*?///[imgy]{0,4}",next:"start"},{token:"comment.regex",regex:"\\s+(?:#.*)?"},{token:"string.regex",regex:"\\S+"}],comment:[{token:"comment",regex:".*?###",next:"start"},{token:"comment",regex:".+"}]}}var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules;r.inherits(s,i),t.CoffeeHighlightRules=s}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/java_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e="abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while",t="null|Infinity|NaN|undefined",n="AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object",r=this.createKeywordMapper({"variable.language":"this",keyword:e,"constant.language":t,"support.function":n},"identifier");this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaHighlightRules=o}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-javascript.js b/common/static/js/vendor/ace/mode-javascript.js new file mode 100644 index 0000000000..4c9a57f3c5 --- /dev/null +++ b/common/static/js/vendor/ace/mode-javascript.js @@ -0,0 +1 @@ +ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-json.js b/common/static/js/vendor/ace/mode-json.js new file mode 100644 index 0000000000..a1b17990b7 --- /dev/null +++ b/common/static/js/vendor/ace/mode-json.js @@ -0,0 +1 @@ +ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./json_highlight_rules").JsonHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode,l=e("../worker/worker_client").WorkerClient,c=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new a,this.foldingRules=new f};r.inherits(c,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new l(["ace"],"ace/mode/json_worker","JsonWorker");return t.attachToDocument(e.getDocument()),t.on("error",function(t){e.setAnnotations([t.data])}),t.on("ok",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"},{token:"string",regex:"",next:"start"}]}};r.inherits(s,i),t.JsonHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-jsp.js b/common/static/js/vendor/ace/mode-jsp.js new file mode 100644 index 0000000000..58f6698836 --- /dev/null +++ b/common/static/js/vendor/ace/mode-jsp.js @@ -0,0 +1 @@ +ace.define("ace/mode/jsp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/jsp_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./jsp_highlight_rules").JspHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode,l=function(){var e=new o;this.$tokenizer=new s(e.getRules()),this.$outdent=new u,this.$behaviour=new a,this.foldingRules=new f};r.inherits(l,i),function(){}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/jsp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/html_highlight_rules","ace/mode/java_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./html_highlight_rules").HtmlHighlightRules,s=e("./java_highlight_rules").JavaHighlightRules,o=function(){i.call(this);for(var e in this.$rules)this.$rules[e].unshift({token:"meta.tag",regex:"<%@?|<%=?|]+>",next:"jsp-start"});var t="request|response|out|session|application|config|pageContext|page|Exception",n="page|include|taglib";this.embedRules(s,"jsp-"),this.$rules.start.unshift({token:"comment",regex:"<%--",next:"comment"}),this.$rules["jsp-start"].unshift({token:"meta.tag",regex:"%>|<\\/jsp:[^>]+>",next:"start"},{token:"variable.language",regex:t},{token:"keyword",regex:n}),this.$rules.comment.unshift({token:"comment",regex:".*?--%>",next:"start"})};r.inherits(o,i),t.JspHighlightRules=o}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/java_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e="abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while",t="null|Infinity|NaN|undefined",n="AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object",r=this.createKeywordMapper({"variable.language":"this",keyword:e,"constant.language":t,"support.function":n},"identifier");this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-jsx.js b/common/static/js/vendor/ace/mode-jsx.js new file mode 100644 index 0000000000..838f38f508 --- /dev/null +++ b/common/static/js/vendor/ace/mode-jsx.js @@ -0,0 +1 @@ +ace.define("ace/mode/jsx",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/jsx_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){function l(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new a,this.foldingRules=new f}var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./jsx_highlight_rules").JsxHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode;r.inherits(l,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[]\s*$/);o&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/jsx_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./doc_comment_highlight_rules").DocCommentHighlightRules,o=e("./text_highlight_rules").TextHighlightRules,u=function(){var e=i.arrayToMap("break|do|instanceof|typeof|case|else|new|var|catch|finally|return|void|continue|for|switch|default|while|function|this|if|throw|delete|in|try|class|extends|super|import|from|into|implements|interface|static|mixin|override|abstract|final|number|int|string|boolean|variant|log|assert".split("|")),t=i.arrayToMap("null|true|false|NaN|Infinity|__FILE__|__LINE__|undefined".split("|")),n=i.arrayToMap("debugger|with|const|export|let|private|public|yield|protected|extern|native|as|operator|__fake__|__readonly__".split("|")),r="[a-zA-Z_][a-zA-Z0-9_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},s.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:["storage.type","text","entity.name.function"],regex:"(function)(\\s+)("+r+")"},{token:function(r){return r=="this"?"variable.language":r=="function"?"storage.type":e.hasOwnProperty(r)||n.hasOwnProperty(r)?"keyword":t.hasOwnProperty(r)?"constant.language":/^_?[A-Z][a-zA-Z0-9_]*$/.test(r)?"language.support.class":"identifier"},regex:r},{token:"keyword.operator",regex:"!|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({<]"},{token:"paren.rparen",regex:"[\\])}>]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}]},this.embedRules(s,"doc-",[s.getEndRule("start")])};r.inherits(u,o),t.JsxHighlightRules=u}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-latex.js b/common/static/js/vendor/ace/mode-latex.js new file mode 100644 index 0000000000..0f364f8768 --- /dev/null +++ b/common/static/js/vendor/ace/mode-latex.js @@ -0,0 +1 @@ +ace.define("ace/mode/latex",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/latex_highlight_rules","ace/mode/folding/latex","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./latex_highlight_rules").LatexHighlightRules,u=e("./folding/latex").FoldMode,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.foldingRules=new u};r.inherits(f,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\%/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"%")},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/latex_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"keyword",regex:"\\\\(?:[^a-zA-Z]|[a-zA-Z]+)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"string",regex:"\\$(?:(?:\\\\.)|(?:[^\\$\\\\]))*?\\$"},{token:"comment",regex:"%.*$"}]}};r.inherits(s,i),t.LatexHighlightRules=s}),ace.define("ace/mode/folding/latex",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range","ace/token_iterator"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=e("../../token_iterator").TokenIterator,u=t.FoldMode=function(){};r.inherits(u,i),function(){this.foldingStartMarker=/^\s*\\(begin)|(section|subsection)\b|{\s*$/,this.foldingStopMarker=/^\s*\\(end)\b|^\s*}/,this.getFoldWidgetRange=function(e,t,n){var r=e.doc.getLine(n),i=this.foldingStartMarker.exec(r);if(i)return i[1]?this.latexBlock(e,n,i[0].length-1):i[2]?this.latexSection(e,n,i[0].length-1):this.openingBracketBlock(e,"{",n,i.index);var i=this.foldingStopMarker.exec(r);if(i)return i[1]?this.latexBlock(e,n,i[0].length-1):this.closingBracketBlock(e,"}",n,i.index+i[0].length)},this.latexBlock=function(e,t,n){var r={"\\begin":1,"\\end":-1},i=new o(e,t,n),u=i.getCurrentToken();if(!u||u.type!=="keyword")return;var a=u.value,f=r[a],l=function(){var e=i.stepForward(),t=e.type=="lparen"?i.stepForward().value:"";return f===-1&&(i.stepBackward(),t&&i.stepBackward()),t},c=[l()],h=f===-1?i.getCurrentTokenColumn():e.getLine(t).length,p=t;i.step=f===-1?i.stepBackward:i.stepForward;while(u=i.step()){if(u.type!=="keyword")continue;var d=r[u.value];if(!d)continue;var v=l();if(d===f)c.unshift(v);else if(c.shift()!==v||!c.length)break}if(c.length)return;var t=i.getCurrentTokenRow();return f===-1?new s(t,e.getLine(t).length,p,h):new s(p,h,t,i.getCurrentTokenColumn())},this.latexSection=function(e,t,n){var r=["\\subsection","\\section","\\begin","\\end"],i=new o(e,t,n),u=i.getCurrentToken();if(!u||u.type!="keyword")return;var a=r.indexOf(u.value),f=0,l=t;while(u=i.stepForward()){if(u.type!=="keyword")continue;var c=r.indexOf(u.value);if(c>=2){f||(l=i.getCurrentTokenRow()-1),f+=c==2?1:-1;if(f<0)break}else if(c>=a)break}f||(l=i.getCurrentTokenRow()-1);while(l>t&&!/\S/.test(e.getLine(l)))l--;return new s(t,e.getLine(t).length,l,e.getLine(l).length)}}.call(u.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-less.js b/common/static/js/vendor/ace/mode-less.js new file mode 100644 index 0000000000..0db8a18852 --- /dev/null +++ b/common/static/js/vendor/ace/mode-less.js @@ -0,0 +1 @@ +ace.define("ace/mode/less",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/less_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./less_highlight_rules").LessHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./folding/cstyle").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/less_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=i.arrayToMap(function(){var e="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),t="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),n="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),r=[];for(var i=0,s=e.length;i|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}]}};r.inherits(o,s),t.LessHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-liquid.js b/common/static/js/vendor/ace/mode-liquid.js new file mode 100644 index 0000000000..8e9ff3cf2f --- /dev/null +++ b/common/static/js/vendor/ace/mode-liquid.js @@ -0,0 +1 @@ +ace.define("ace/mode/liquid",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/liquid_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./liquid_highlight_rules").LiquidHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u};r.inherits(f,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=[],o=/^(\s*)#/;for(var u=n;u<=r;u++)if(!o.test(t.getLine(u))){i=!1;break}if(i){var f=new a(0,0,0,0);for(var u=n;u<=r;u++){var l=t.getLine(u),c=l.match(o);f.start.row=u,f.end.row=u,f.end.column=c[0].length,t.replace(f,c[1])}}else t.indentRows(n,r,"#")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var u=t.match(/^.*[\{\(\[]\s*$/);u&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/liquid_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./css_highlight_rules").CssHighlightRules,s=e("./javascript_highlight_rules").JavaScriptHighlightRules,o=e("./xml_util"),u=e("./text_highlight_rules").TextHighlightRules,a=function(){var e="date|capitalize|downcase|upcase|first|last|join|sort|map|size|escape|escape_once|strip_html|strip_newlines|newline_to_br|replace|replace_first|truncate|truncatewords|prepend|append|minus|plus|times|divided_by|split",t="capture|endcapture|case|endcase|when|comment|endcomment|cycle|for|endfor|in|reversed|if|endif|else|elsif|include|endinclude|unless|endunless|style|text|image|widget|plugin|marker|endmarker|tablerow|endtablerow",n="forloop|tablerowloop",r="assign",u=this.createKeywordMapper({"variable.language":n,keyword:t,"support.function":e,"keyword.definition":r},"identifier");this.$rules={start:[{token:"variable",regex:"{%",next:"liquid_start"},{token:"variable",regex:"{{",next:"liquid_start"},{token:"meta.tag",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<(?=\\s*script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=\\s*style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}],liquid_start:[{token:"variable",regex:"}}",next:"start"},{token:"variable",regex:"%}",next:"start"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:u,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"/|\\*|\\-|\\+|=|!=|\\?\\:"},{token:"paren.lparen",regex:/[\[\({]/},{token:"paren.rparen",regex:/[\])}]/},{token:"text",regex:"\\s+"}]},o.tag(this.$rules,"tag","start"),o.tag(this.$rules,"style","css-start"),o.tag(this.$rules,"script","js-start"),this.embedRules(s,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(i,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(a,u),t.LiquidHighlightRules=a}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-lisp.js b/common/static/js/vendor/ace/mode-lisp.js new file mode 100644 index 0000000000..a27f23686e --- /dev/null +++ b/common/static/js/vendor/ace/mode-lisp.js @@ -0,0 +1 @@ +ace.define("ace/mode/lisp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/lisp_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./lisp_highlight_rules").LispHighlightRules,u=function(){var e=new o;this.$tokenizer=new s(e.getRules())};r.inherits(u,i),function(){}.call(u.prototype),t.Mode=u}),ace.define("ace/mode/lisp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="case|do|let|loop|if|else|when",t="eq|neq|and|or",n="null|nil",r="cons|car|cdr|cond|lambda|format|setq|setf|quote|eval|append|list|listp|memberp|t|load|progn",i=this.createKeywordMapper({"keyword.control":e,"keyword.operator":t,"constant.language":n,"support.function":r},"identifier",!0);this.$rules={start:[{token:"comment",regex:";.*$"},{token:["storage.type.function-type.lisp","text","entity.name.function.lisp"],regex:"(?:\\b(?:(defun|defmethod|defmacro))\\b)(\\s+)((?:\\w|\\-|\\!|\\?)*)"},{token:["punctuation.definition.constant.character.lisp","constant.character.lisp"],regex:"(#)((?:\\w|[\\\\+-=<>'\"&#])+)"},{token:["punctuation.definition.variable.lisp","variable.other.global.lisp","punctuation.definition.variable.lisp"],regex:"(\\*)(\\S*)(\\*)"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+(?:L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(?:L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"},{token:i,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"string",regex:'"(?=.)',next:"qqstring"}],qqstring:[{token:"constant.character.escape.lisp",regex:"\\\\."},{token:"string",regex:'[^"\\\\]+',merge:!0},{token:"string",regex:"\\\\$",next:"qqstring",merge:!0},{token:"string",regex:'"|$',next:"start",merge:!0}]}};r.inherits(s,i),t.LispHighlightRules=s}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-lua.js b/common/static/js/vendor/ace/mode-lua.js new file mode 100644 index 0000000000..77a3efaa80 --- /dev/null +++ b/common/static/js/vendor/ace/mode-lua.js @@ -0,0 +1 @@ +ace.define("ace/mode/lua",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/lua_highlight_rules","ace/mode/folding/lua","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./lua_highlight_rules").LuaHighlightRules,u=e("./folding/lua").FoldMode,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.foldingRules=new u};r.inherits(f,i),function(){function n(t){var n=0;for(var r=0;r0?1:0}var e={"function":1,then:1,"do":1,"else":1,elseif:1,repeat:1,end:-1,until:-1},t=["else","elseif","end","until"];this.getNextLineIndent=function(e,t,r){var i=this.$getIndent(t),s=0,o=this.$tokenizer.getLineTokens(t,e),u=o.tokens;return e=="start"&&(s=n(u)),s>0?i+r:s<0&&i.substr(i.length-r.length)==r&&!this.checkOutdent(e,t,"\n")?i.substr(0,i.length-r.length):i},this.checkOutdent=function(e,n,r){if(r!="\n"&&r!="\r"&&r!="\r\n")return!1;if(n.match(/^\s*[\)\}\]]$/))return!0;var i=this.$tokenizer.getLineTokens(n.trim(),e).tokens;return!i||!i.length?!1:i[0].type=="keyword"&&t.indexOf(i[0].value)!=-1},this.autoOutdent=function(e,t,r){var i=t.getLine(r-1),s=this.$getIndent(i).length,o=this.$tokenizer.getLineTokens(i,"start").tokens,u=t.getTabString().length,f=s+u*n(o),l=this.$getIndent(t.getLine(r)).length;if(l|<=|=>|==|~=|=|\\:|\\.\\.\\.|\\.\\."},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qcomment:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"comment",regex:".+"}],qcomment1:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"comment",regex:".+"}],qcomment2:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"comment",regex:".+"}],qcomment3:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"comment",regex:".+"}],qcomment4:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"comment",regex:".+"}],qcomment5:[{token:function(e){var t=/\](\=+)\]/,n=this.rules.qcomment5[0],r;n.next="start";if((r=t.exec(e))!=null&&(r=r[1])!=undefined){var i=r.length,s;(s=v.pop())!=i&&(v.push(s),n.next="qcomment5")}return"comment"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"comment",regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"string",regex:".+"}],qstring1:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"string",regex:".+"}],qstring2:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"string",regex:".+"}],qstring3:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"string",regex:".+"}],qstring4:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"string",regex:".+"}],qstring5:[{token:function(e){var t=/\](\=+)\]/,n=this.rules.qstring5[0],r;n.next="start";if((r=t.exec(e))!=null&&(r=r[1])!=undefined){var i=r.length,s;(s=v.pop())!=i&&(v.push(s),n.next="qstring5")}return"string"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.LuaHighlightRules=s}),ace.define("ace/mode/folding/lua",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range","ace/token_iterator"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=e("../../token_iterator").TokenIterator,u=t.FoldMode=function(){};r.inherits(u,i),function(){this.foldingStartMarker=/\b(function|then|do|repeat)\b|{\s*$|(\[=*\[)/,this.foldingStopMarker=/\bend\b|^\s*}|\]=*\]/,this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=this.foldingStartMarker.test(r),s=this.foldingStopMarker.test(r);if(i&&!s){var o=r.match(this.foldingStartMarker);if(o[1]=="then"&&/\belseif\b/.test(r))return;if(o[1]){if(e.getTokenAt(n,o.index+1).type==="keyword")return"start"}else{if(!o[2])return"start";var u=e.bgTokenizer.getState(n)||"";if(u.indexOf("comment")!=-1||u.indexOf("string")!=-1)return"start"}}if(t!="markbeginend"||!s||i&&s)return"";var o=r.match(this.foldingStopMarker);if(o[0]==="end"){if(e.getTokenAt(n,o.index+1).type==="keyword")return"end"}else{if(o[0][0]!=="]")return"end";var u=e.bgTokenizer.getState(n-1)||"";if(u.indexOf("comment")!=-1||u.indexOf("string")!=-1)return"end"}},this.getFoldWidgetRange=function(e,t,n){var r=e.doc.getLine(n),i=this.foldingStartMarker.exec(r);if(i)return i[1]?this.luaBlock(e,n,i.index+1):i[2]?e.getCommentFoldRange(n,i.index+1):this.openingBracketBlock(e,"{",n,i.index);var i=this.foldingStopMarker.exec(r);if(i)return i[0]==="end"&&e.getTokenAt(n,i.index+1).type==="keyword"?this.luaBlock(e,n,i.index+1):i[0][0]==="]"?e.getCommentFoldRange(n,i.index+1):this.closingBracketBlock(e,"}",n,i.index+i[0].length)},this.luaBlock=function(e,t,n){var r=new o(e,t,n),i={"function":1,"do":1,then:1,elseif:-1,end:-1,repeat:1,until:-1},u=r.getCurrentToken();if(!u||u.type!="keyword")return;var a=u.value,f=[a],l=i[a];if(!l)return;var c=l===-1?r.getCurrentTokenColumn():e.getLine(t).length,h=t;r.step=l===-1?r.stepBackward:r.stepForward;while(u=r.step()){if(u.type!=="keyword")continue;var p=l*i[u.value];if(p>0)f.unshift(u.value);else if(p<=0){f.shift();if(!f.length&&u.value!="elseif")break;p===0&&f.unshift(u.value)}}var t=r.getCurrentTokenRow();return l===-1?new s(t,e.getLine(t).length,h,c):new s(h,c,t,r.getCurrentTokenColumn())}}.call(u.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-luapage.js b/common/static/js/vendor/ace/mode-luapage.js new file mode 100644 index 0000000000..39c90d3f52 --- /dev/null +++ b/common/static/js/vendor/ace/mode-luapage.js @@ -0,0 +1 @@ +ace.define("ace/mode/luapage",["require","exports","module","ace/lib/oop","ace/mode/html","ace/mode/lua","ace/tokenizer","ace/mode/luapage_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./html").Mode,s=e("./lua").Mode,o=e("../tokenizer").Tokenizer,u=e("./luapage_highlight_rules").LuaPageHighlightRules,a=function(){var e=new u;this.$tokenizer=new o((new u).getRules()),this.$embeds=e.getEmbeds(),this.createModeDelegates({"lua-":s})};r.inherits(a,i),t.Mode=a}),ace.define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/html","ace/mode/folding/html"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("./javascript").Mode,o=e("./css").Mode,u=e("../tokenizer").Tokenizer,a=e("./html_highlight_rules").HtmlHighlightRules,f=e("./behaviour/html").HtmlBehaviour,l=e("./folding/html").FoldMode,c=function(){var e=new a;this.$tokenizer=new u(e.getRules()),this.$behaviour=new f,this.$embeds=e.getEmbeds(),this.createModeDelegates({"js-":s,"css-":o}),this.foldingRules=new l};r.inherits(c,i),function(){this.toggleCommentLines=function(e,t,n,r){return 0},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/html",["require","exports","module","ace/lib/oop","ace/mode/behaviour/xml","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function a(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour/xml").XmlBehaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,u=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],f=function(){this.inherit(i),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),f=new o(r,s.row,s.column),l=f.getCurrentToken(),c=!1;if(!l||!a(l,"meta.tag")&&(!a(l,"text")||!l.value.match("/"))){do l=f.stepBackward();while(l&&(a(l,"string")||a(l,"keyword.operator")||a(l,"entity.attribute-name")||a(l,"text")))}else c=!0;if(!l||!a(l,"meta.tag-name")||f.stepBackward().value.match("/"))return;var h=l.value;if(c)var h=h.substring(0,s.column-l.start);if(u.indexOf(h)!==-1)return;return{text:">",selection:[1,1]}}})};r.inherits(f,i),t.HtmlBehaviour=f}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}),ace.define("ace/mode/lua",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/lua_highlight_rules","ace/mode/folding/lua","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./lua_highlight_rules").LuaHighlightRules,u=e("./folding/lua").FoldMode,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.foldingRules=new u};r.inherits(f,i),function(){function n(t){var n=0;for(var r=0;r0?1:0}var e={"function":1,then:1,"do":1,"else":1,elseif:1,repeat:1,end:-1,until:-1},t=["else","elseif","end","until"];this.getNextLineIndent=function(e,t,r){var i=this.$getIndent(t),s=0,o=this.$tokenizer.getLineTokens(t,e),u=o.tokens;return e=="start"&&(s=n(u)),s>0?i+r:s<0&&i.substr(i.length-r.length)==r&&!this.checkOutdent(e,t,"\n")?i.substr(0,i.length-r.length):i},this.checkOutdent=function(e,n,r){if(r!="\n"&&r!="\r"&&r!="\r\n")return!1;if(n.match(/^\s*[\)\}\]]$/))return!0;var i=this.$tokenizer.getLineTokens(n.trim(),e).tokens;return!i||!i.length?!1:i[0].type=="keyword"&&t.indexOf(i[0].value)!=-1},this.autoOutdent=function(e,t,r){var i=t.getLine(r-1),s=this.$getIndent(i).length,o=this.$tokenizer.getLineTokens(i,"start").tokens,u=t.getTabString().length,f=s+u*n(o),l=this.$getIndent(t.getLine(r)).length;if(l|<=|=>|==|~=|=|\\:|\\.\\.\\.|\\.\\."},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qcomment:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"comment",regex:".+"}],qcomment1:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"comment",regex:".+"}],qcomment2:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"comment",regex:".+"}],qcomment3:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"comment",regex:".+"}],qcomment4:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"comment",regex:".+"}],qcomment5:[{token:function(e){var t=/\](\=+)\]/,n=this.rules.qcomment5[0],r;n.next="start";if((r=t.exec(e))!=null&&(r=r[1])!=undefined){var i=r.length,s;(s=v.pop())!=i&&(v.push(s),n.next="qcomment5")}return"comment"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"comment",regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"string",regex:".+"}],qstring1:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"string",regex:".+"}],qstring2:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"string",regex:".+"}],qstring3:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"string",regex:".+"}],qstring4:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"string",regex:".+"}],qstring5:[{token:function(e){var t=/\](\=+)\]/,n=this.rules.qstring5[0],r;n.next="start";if((r=t.exec(e))!=null&&(r=r[1])!=undefined){var i=r.length,s;(s=v.pop())!=i&&(v.push(s),n.next="qstring5")}return"string"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.LuaHighlightRules=s}),ace.define("ace/mode/folding/lua",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range","ace/token_iterator"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=e("../../token_iterator").TokenIterator,u=t.FoldMode=function(){};r.inherits(u,i),function(){this.foldingStartMarker=/\b(function|then|do|repeat)\b|{\s*$|(\[=*\[)/,this.foldingStopMarker=/\bend\b|^\s*}|\]=*\]/,this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=this.foldingStartMarker.test(r),s=this.foldingStopMarker.test(r);if(i&&!s){var o=r.match(this.foldingStartMarker);if(o[1]=="then"&&/\belseif\b/.test(r))return;if(o[1]){if(e.getTokenAt(n,o.index+1).type==="keyword")return"start"}else{if(!o[2])return"start";var u=e.bgTokenizer.getState(n)||"";if(u.indexOf("comment")!=-1||u.indexOf("string")!=-1)return"start"}}if(t!="markbeginend"||!s||i&&s)return"";var o=r.match(this.foldingStopMarker);if(o[0]==="end"){if(e.getTokenAt(n,o.index+1).type==="keyword")return"end"}else{if(o[0][0]!=="]")return"end";var u=e.bgTokenizer.getState(n-1)||"";if(u.indexOf("comment")!=-1||u.indexOf("string")!=-1)return"end"}},this.getFoldWidgetRange=function(e,t,n){var r=e.doc.getLine(n),i=this.foldingStartMarker.exec(r);if(i)return i[1]?this.luaBlock(e,n,i.index+1):i[2]?e.getCommentFoldRange(n,i.index+1):this.openingBracketBlock(e,"{",n,i.index);var i=this.foldingStopMarker.exec(r);if(i)return i[0]==="end"&&e.getTokenAt(n,i.index+1).type==="keyword"?this.luaBlock(e,n,i.index+1):i[0][0]==="]"?e.getCommentFoldRange(n,i.index+1):this.closingBracketBlock(e,"}",n,i.index+i[0].length)},this.luaBlock=function(e,t,n){var r=new o(e,t,n),i={"function":1,"do":1,then:1,elseif:-1,end:-1,repeat:1,until:-1},u=r.getCurrentToken();if(!u||u.type!="keyword")return;var a=u.value,f=[a],l=i[a];if(!l)return;var c=l===-1?r.getCurrentTokenColumn():e.getLine(t).length,h=t;r.step=l===-1?r.stepBackward:r.stepForward;while(u=r.step()){if(u.type!=="keyword")continue;var p=l*i[u.value];if(p>0)f.unshift(u.value);else if(p<=0){f.shift();if(!f.length&&u.value!="elseif")break;p===0&&f.unshift(u.value)}}var t=r.getCurrentTokenRow();return l===-1?new s(t,e.getLine(t).length,h,c):new s(h,c,t,r.getCurrentTokenColumn())}}.call(u.prototype)}),ace.define("ace/mode/luapage_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/html_highlight_rules","ace/mode/lua_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./html_highlight_rules").HtmlHighlightRules,s=e("./lua_highlight_rules").LuaHighlightRules,o=function(){this.$rules=(new i).getRules();for(var e in this.$rules)this.$rules[e].unshift({token:"keyword",regex:"<\\%\\=?",next:"lua-start"},{token:"keyword",regex:"<\\?lua\\=?",next:"lua-start"});this.embedRules(s,"lua-",[{token:"keyword",regex:"\\%>",next:"start"},{token:"keyword",regex:"\\?>",next:"start"}])};r.inherits(o,i),t.LuaPageHighlightRules=o}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-lucene.js b/common/static/js/vendor/ace/mode-lucene.js new file mode 100644 index 0000000000..f95c0af7e2 --- /dev/null +++ b/common/static/js/vendor/ace/mode-lucene.js @@ -0,0 +1 @@ +ace.define("ace/mode/lucene",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/lucene_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./lucene_highlight_rules").LuceneHighlightRules,u=function(){this.$tokenizer=new s((new o).getRules())};r.inherits(u,i),t.Mode=u}),ace.define("ace/mode/lucene_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){this.$rules={start:[{token:"constant.character.negation",regex:"[\\-]"},{token:"constant.character.interro",regex:"[\\?]"},{token:"constant.character.asterisk",regex:"[\\*]"},{token:"constant.character.proximity",regex:"~[0-9]+\\b"},{token:"keyword.operator",regex:"(?:AND|OR|NOT)\\b"},{token:"paren.lparen",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"keyword",regex:"[\\S]+:"},{token:"string",regex:'".*?"'},{token:"text",regex:"\\s+"}]}};r.inherits(o,s),t.LuceneHighlightRules=o}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-makefile.js b/common/static/js/vendor/ace/mode-makefile.js new file mode 100644 index 0000000000..c567fd920d --- /dev/null +++ b/common/static/js/vendor/ace/mode-makefile.js @@ -0,0 +1 @@ +ace.define("ace/mode/makefile",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/makefile_highlight_rules","ace/mode/folding/coffee"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./makefile_highlight_rules").MakefileHighlightRules,u=e("./folding/coffee").FoldMode,a=function(){var e=new o;this.foldingRules=new u,this.$tokenizer=new s(e.getRules())};r.inherits(a,i),function(){}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/makefile_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/sh_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=e("./sh_highlight_rules"),o=function(){var e=this.createKeywordMapper({keyword:s.reservedKeywords,"support.function.builtin":s.languageConstructs,"invalid.deprecated":"debugger"},"string");this.$rules={start:[{token:"string.interpolated.backtick.makefile",regex:"`",next:"shell-start"},{token:"punctuation.definition.comment.makefile",regex:/#(?=.)/,next:"comment"},{token:["keyword.control.makefile"],regex:"^(?:\\s*\\b)(\\-??include|ifeq|ifneq|ifdef|ifndef|else|endif|vpath|export|unexport|define|endef|override)(?:\\b)"},{token:["entity.name.function.makefile","text"],regex:"^([^\\t ]+(?:\\s[^\\t ]+)*:)(\\s*.*)"}],comment:[{token:"punctuation.definition.comment.makefile",regex:/.+\\/},{token:"punctuation.definition.comment.makefile",regex:".+",next:"start"}],"shell-start":[{token:e,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"string",regex:"\\w+"},{token:"string.interpolated.backtick.makefile",regex:"`",next:"start"}]}};r.inherits(o,i),t.MakefileHighlightRules=o}),ace.define("ace/mode/sh_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=t.reservedKeywords="!|{|}|case|do|done|elif|else|esac|fi|for|if|in|then|until|while|&|;|export|local|read|typeset|unset|elif|select|set",o=t.languageConstructs="[|]|alias|bg|bind|break|builtin|cd|command|compgen|complete|continue|dirs|disown|echo|enable|eval|exec|exit|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|popd|printf|pushd|pwd|return|set|shift|shopt|source|suspend|test|times|trap|type|ulimit|umask|unalias|wait",u=function(){var e=this.createKeywordMapper({keyword:s,"support.function.builtin":o,"invalid.deprecated":"debugger"},"identifier"),t="(?:(?:[1-9]\\d*)|(?:0))",n="(?:\\.\\d+)",r="(?:\\d+)",i="(?:(?:"+r+"?"+n+")|(?:"+r+"\\.))",u="(?:(?:"+i+"|"+r+")"+")",a="(?:"+u+"|"+i+")",f="(?:&"+r+")",l="[a-zA-Z][a-zA-Z0-9_]*",c="(?:(?:\\$"+l+")|(?:"+l+"=))",h="(?:\\$(?:SHLVL|\\$|\\!|\\?))",p="(?:"+l+"\\s*\\(\\))";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:'"(?:[^\\\\]|\\\\.)*?"'},{token:"variable.language",regex:h},{token:"variable",regex:c},{token:"support.function",regex:p},{token:"support.function",regex:f},{token:"string",regex:"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:a},{token:"constant.numeric",regex:t+"\\b"},{token:e,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|~|<|>|<=|=>|=|!="},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}]}};r.inherits(u,i),t.ShHighlightRules=u}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./xml_highlight_rules").XmlHighlightRules,u=e("./behaviour/xml").XmlBehaviour,a=e("./folding/xml").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules()),this.$behaviour=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./xml_util"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},i.tag(this.$rules,"tag","start")};r.inherits(o,s),t.XmlHighlightRules=o}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}),ace.define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/html","ace/mode/folding/html"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("./javascript").Mode,o=e("./css").Mode,u=e("../tokenizer").Tokenizer,a=e("./html_highlight_rules").HtmlHighlightRules,f=e("./behaviour/html").HtmlBehaviour,l=e("./folding/html").FoldMode,c=function(){var e=new a;this.$tokenizer=new u(e.getRules()),this.$behaviour=new f,this.$embeds=e.getEmbeds(),this.createModeDelegates({"js-":s,"css-":o}),this.foldingRules=new l};r.inherits(c,i),function(){this.toggleCommentLines=function(e,t,n,r){return 0},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/behaviour/html",["require","exports","module","ace/lib/oop","ace/mode/behaviour/xml","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function a(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour/xml").XmlBehaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,u=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],f=function(){this.inherit(i),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),f=new o(r,s.row,s.column),l=f.getCurrentToken(),c=!1;if(!l||!a(l,"meta.tag")&&(!a(l,"text")||!l.value.match("/"))){do l=f.stepBackward();while(l&&(a(l,"string")||a(l,"keyword.operator")||a(l,"entity.attribute-name")||a(l,"text")))}else c=!0;if(!l||!a(l,"meta.tag-name")||f.stepBackward().value.match("/"))return;var h=l.value;if(c)var h=h.substring(0,s.column-l.start);if(u.indexOf(h)!==-1)return;return{text:">",selection:[1,1]}}})};r.inherits(f,i),t.HtmlBehaviour=f}),ace.define("ace/mode/folding/html",["require","exports","module","ace/lib/oop","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../../lib/oop"),i=e("./mixed").FoldMode,s=e("./xml").FoldMode,o=e("./cstyle").FoldMode,u=t.FoldMode=function(){i.call(this,new s({area:1,base:1,br:1,col:1,command:1,embed:1,hr:1,img:1,input:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,li:1,dt:1,dd:1,p:1,rt:1,rp:1,optgroup:1,option:1,colgroup:1,td:1,th:1}),{"js-":new o,"css-":new o})};r.inherits(u,i)}),ace.define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=t.FoldMode=function(e,t){this.defaultMode=e,this.subModes=t};r.inherits(s,i),function(){this.$getMode=function(e){for(var t in this.subModes)if(e.indexOf(t)===0)return this.subModes[t];return null},this.$tryMode=function(e,t,n,r){var i=this.$getMode(e);return i?i.getFoldWidget(t,n,r):""},this.getFoldWidget=function(e,t,n){return this.$tryMode(e.getState(n-1),e,t,n)||this.$tryMode(e.getState(n),e,t,n)||this.defaultMode.getFoldWidget(e,t,n)},this.getFoldWidgetRange=function(e,t,n){var r=this.$getMode(e.getState(n-1));if(!r||!r.getFoldWidget(e,t,n))r=this.$getMode(e.getState(n));if(!r||!r.getFoldWidget(e,t,n))r=this.defaultMode;return r.getFoldWidgetRange(e,t,n)}}.call(s.prototype)}),ace.define("ace/mode/markdown_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/html_highlight_rules","ace/mode/css_highlight_rules"],function(e,t,n){function f(e,t){return{token:"support.function",regex:"^```"+e+"\\s*$",next:t+"start"}}var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=e("./javascript_highlight_rules").JavaScriptHighlightRules,o=e("./xml_highlight_rules").XmlHighlightRules,u=e("./html_highlight_rules").HtmlHighlightRules,a=e("./css_highlight_rules").CssHighlightRules,l=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{token:["support.function","support.function","support.function"],regex:"(`+)([^\\r]*?[^`])(\\1)"},{token:"support.function",regex:"^[ ]{4}.+"},{token:"markup.heading.1",regex:"^=+(?=\\s*$)"},{token:"markup.heading.2",regex:"^\\-+(?=\\s*$)"},{token:function(e){return"markup.heading."+e.search(/[^#]/)},regex:"^#{1,6}(?:[^ #].*| +.*(?:[^ #].*|[^ ]+.* +#+ *))$"},f("(?:javascript|js)","js-"),f("xml","xml-"),f("html","html-"),f("css","css-"),{token:"support.function",regex:"^```\\s*[a-zA-Z]*(?:{.*?\\})?\\s*$",next:"githubblock"},{token:"string",regex:"^>[ ].+$",next:"blockquote"},{token:["text","constant","text","url","string","text"],regex:'^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:["][^"]+["])?(\\s*))$'},{token:["text","string","text","constant","text"],regex:"(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"},{token:["text","string","text","markup.underline","string","text"],regex:'(\\[)(\\[[^\\]]*\\]|[^\\[\\]]*)(\\]\\([ \\t]*)(?)((?:[ ]*"(?:.*?)"[ \\t]*)?)(\\))'},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\*[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\-[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\_[ ]?){3,}\\s*$"},{token:"markup.list",regex:"^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",next:"listblock"},{token:["string","string","string"],regex:"([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:["string","string","string"],regex:"([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:["text","url","text"],regex:"(<)((?:https?|ftp|dict):[^'\">\\s]+|(?:mailto:)?[-.\\w]+\\@[-a-z0-9]+(?:\\.[-a-z0-9]+)*\\.[a-z]+)(>)"},{token:"text",regex:"[^\\*_%$`\\[#<>]+"}],listblock:[{token:"empty_line",regex:"^$",next:"start"},{token:"markup.list",regex:".+"}],blockquote:[{token:"empty_line",regex:"^\\s*$",next:"start"},{token:"string",regex:".+"}],githubblock:[{token:"support.function",regex:"^```",next:"start"},{token:"support.function",regex:".+"}]},this.embedRules(s,"js-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(u,"html-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(a,"css-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(o,"xml-",[{token:"support.function",regex:"^```",next:"start"}]);var e=(new u).getRules();for(var t in e)this.$rules[t]?this.$rules[t]=this.$rules[t].concat(e[t]):this.$rules[t]=e[t]};r.inherits(l,i),t.MarkdownHighlightRules=l}),ace.define("ace/mode/folding/markdown",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.foldingStartMarker=/^(?:[=-]+\s*$|#{1,6} |`{3})/,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?r[0]=="`"?e.bgTokenizer.getState(n)=="start"?"end":"start":"start":""},this.getFoldWidgetRange=function(e,t,n){function l(t){return f=e.getTokens(t)[0],f&&f.type.lastIndexOf(c,0)===0}function h(){var e=f.value[0];return e=="="?6:e=="-"?5:7-f.value.search(/[^#]/)}var r=e.getLine(n),i=r.length,o=e.getLength(),u=n,a=n;if(!r.match(this.foldingStartMarker))return;if(r[0]=="`"){if(e.bgTokenizer.getState(n)!=="start"){while(++n0){r=e.getLine(n);if(r[0]=="`"&r.substring(0,3)=="```")break}return new s(n,r.length,u,0)}var f,c="markup.heading";if(l(n)){var p=h();while(++n=p)break}a=n-(!f||["=","-"].indexOf(f.value[0])==-1?1:2);if(a>u)while(a>u&&/^\s*$/.test(e.getLine(a)))a--;if(a>u){var v=e.getLine(a).length;return new s(u,i,a,v)}}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-objectivec.js b/common/static/js/vendor/ace/mode-objectivec.js new file mode 100644 index 0000000000..0890b101d7 --- /dev/null +++ b/common/static/js/vendor/ace/mode-objectivec.js @@ -0,0 +1 @@ +ace.define("ace/mode/objectivec",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/objectivec_highlight_rules","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./objectivec_highlight_rules").ObjectiveCHighlightRules,u=e("./folding/cstyle").FoldMode,a=function(){var e=new o;this.foldingRules=new u,this.$tokenizer=new s(e.getRules())};r.inherits(a,i),function(){}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/objectivec_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/c_cpp_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./c_cpp_highlight_rules"),o=s.c_cppHighlightRules,u=function(){var e="\\\\(?:[abefnrtv'\"?\\\\]|[0-3]\\d{1,2}|[4-7]\\d?|222|x[a-zA-Z0-9]+)",t=[{regex:"\\b_cmd\\b",token:"variable.other.selector.objc"},{regex:"\\b(?:self|super)\\b",token:"variable.language.objc"}],n=new o,r=n.getRules();this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:["storage.type.objc","punctuation.definition.storage.type.objc","entity.name.type.objc","text","entity.other.inherited-class.objc"],regex:"(@)(interface|protocol)(?!.+;)(\\s+[A-Za-z_][A-Za-z0-9_]*)(\\s*:\\s*)([A-Za-z]+)"},{token:["storage.type.objc"],regex:"(@end)"},{token:["storage.type.objc","entity.name.type.objc","entity.other.inherited-class.objc"],regex:"(@implementation)(\\s+[A-Za-z_][A-Za-z0-9_]*)(\\s*?::\\s*(?:[A-Za-z][A-Za-z0-9]*))?"},{token:"string.begin.objc",regex:'@"',next:"constant_NSString"},{token:"storage.type.objc",regex:"\\bid\\s*<",next:"protocol_list"},{token:"keyword.control.macro.objc",regex:"\\bNS_DURING|NS_HANDLER|NS_ENDHANDLER\\b"},{token:["punctuation.definition.keyword.objc","keyword.control.exception.objc"],regex:"(@)(try|catch|finally|throw)\\b"},{token:["punctuation.definition.keyword.objc","keyword.other.objc"],regex:"(@)(defs|encode)\\b"},{token:["storage.type.id.objc","text"],regex:"(\\bid\\b)(\\s|\\n)?"},{token:"storage.type.objc",regex:"\\bIBOutlet|IBAction|BOOL|SEL|id|unichar|IMP|Class\\b"},{token:["punctuation.definition.storage.type.objc","storage.type.objc"],regex:"(@)(class|protocol)\\b"},{token:["punctuation.definition.storage.type.objc","punctuation.definition.storage.type.objc","punctuation"],regex:"(@)(selector)(\\s*\\()",next:"selectors"},{token:["punctuation.definition.storage.modifier.objc","storage.modifier.objc"],regex:"(@)(synchronized|public|private|protected|package)\\b"},{token:"constant.language.objc",regex:"\\bYES|NO|Nil|nil\\b"},{token:"support.variable.foundation",regex:"\\bNSApp\\b"},{token:["support.function.cocoa.leopard"],regex:"(?:\\b)(NS(?:Rect(?:ToCGRect|FromCGRect)|MakeCollectable|S(?:tringFromProtocol|ize(?:ToCGSize|FromCGSize))|Draw(?:NinePartImage|ThreePartImage)|P(?:oint(?:ToCGPoint|FromCGPoint)|rotocolFromString)|EventMaskFromType|Value))(?:\\b)"},{token:["support.function.cocoa"],regex:"(?:\\b)(NS(?:R(?:ound(?:DownToMultipleOfPageSize|UpToMultipleOfPageSize)|un(?:CriticalAlertPanel(?:RelativeToWindow)?|InformationalAlertPanel(?:RelativeToWindow)?|AlertPanel(?:RelativeToWindow)?)|e(?:set(?:MapTable|HashTable)|c(?:ycleZone|t(?:Clip(?:List)?|F(?:ill(?:UsingOperation|List(?:UsingOperation|With(?:Grays|Colors(?:UsingOperation)?))?)?|romString))|ordAllocationEvent)|turnAddress|leaseAlertPanel|a(?:dPixel|l(?:MemoryAvailable|locateCollectable))|gisterServicesProvider)|angeFromString)|Get(?:SizeAndAlignment|CriticalAlertPanel|InformationalAlertPanel|UncaughtExceptionHandler|FileType(?:s)?|WindowServerMemory|AlertPanel)|M(?:i(?:n(?:X|Y)|d(?:X|Y))|ouseInRect|a(?:p(?:Remove|Get|Member|Insert(?:IfAbsent|KnownAbsent)?)|ke(?:R(?:ect|ange)|Size|Point)|x(?:Range|X|Y)))|B(?:itsPer(?:SampleFromDepth|PixelFromDepth)|e(?:stDepth|ep|gin(?:CriticalAlertSheet|InformationalAlertSheet|AlertSheet)))|S(?:ho(?:uldRetainWithZone|w(?:sServicesMenuItem|AnimationEffect))|tringFrom(?:R(?:ect|ange)|MapTable|S(?:ize|elector)|HashTable|Class|Point)|izeFromString|e(?:t(?:ShowsServicesMenuItem|ZoneName|UncaughtExceptionHandler|FocusRingStyle)|lectorFromString|archPathForDirectoriesInDomains)|wap(?:Big(?:ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(?:ToHost|LongToHost))|Short|Host(?:ShortTo(?:Big|Little)|IntTo(?:Big|Little)|DoubleTo(?:Big|Little)|FloatTo(?:Big|Little)|Long(?:To(?:Big|Little)|LongTo(?:Big|Little)))|Int|Double|Float|L(?:ittle(?:ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(?:ToHost|LongToHost))|ong(?:Long)?)))|H(?:ighlightRect|o(?:stByteOrder|meDirectory(?:ForUser)?)|eight|ash(?:Remove|Get|Insert(?:IfAbsent|KnownAbsent)?)|FSType(?:CodeFromFileType|OfFile))|N(?:umberOfColorComponents|ext(?:MapEnumeratorPair|HashEnumeratorItem))|C(?:o(?:n(?:tainsRect|vert(?:GlyphsToPackedGlyphs|Swapped(?:DoubleToHost|FloatToHost)|Host(?:DoubleToSwapped|FloatToSwapped)))|unt(?:MapTable|HashTable|Frames|Windows(?:ForContext)?)|py(?:M(?:emoryPages|apTableWithZone)|Bits|HashTableWithZone|Object)|lorSpaceFromDepth|mpare(?:MapTables|HashTables))|lassFromString|reate(?:MapTable(?:WithZone)?|HashTable(?:WithZone)?|Zone|File(?:namePboardType|ContentsPboardType)))|TemporaryDirectory|I(?:s(?:ControllerMarker|EmptyRect|FreedObject)|n(?:setRect|crementExtraRefCount|te(?:r(?:sect(?:sRect|ionR(?:ect|ange))|faceStyleForKey)|gralRect)))|Zone(?:Realloc|Malloc|Name|Calloc|Fr(?:omPointer|ee))|O(?:penStepRootDirectory|ffsetRect)|D(?:i(?:sableScreenUpdates|videRect)|ottedFrameRect|e(?:c(?:imal(?:Round|Multiply|S(?:tring|ubtract)|Normalize|Co(?:py|mpa(?:ct|re))|IsNotANumber|Divide|Power|Add)|rementExtraRefCountWasZero)|faultMallocZone|allocate(?:MemoryPages|Object))|raw(?:Gr(?:oove|ayBezel)|B(?:itmap|utton)|ColorTiledRects|TiledRects|DarkBezel|W(?:hiteBezel|indowBackground)|LightBezel))|U(?:serName|n(?:ionR(?:ect|ange)|registerServicesProvider)|pdateDynamicServices)|Java(?:Bundle(?:Setup|Cleanup)|Setup(?:VirtualMachine)?|Needs(?:ToLoadClasses|VirtualMachine)|ClassesF(?:orBundle|romPath)|ObjectNamedInPath|ProvidesClasses)|P(?:oint(?:InRect|FromString)|erformService|lanarFromDepth|ageSize)|E(?:n(?:d(?:MapTableEnumeration|HashTableEnumeration)|umerate(?:MapTable|HashTable)|ableScreenUpdates)|qual(?:R(?:ects|anges)|Sizes|Points)|raseRect|xtraRefCount)|F(?:ileTypeForHFSTypeCode|ullUserName|r(?:ee(?:MapTable|HashTable)|ame(?:Rect(?:WithWidth(?:UsingOperation)?)?|Address)))|Wi(?:ndowList(?:ForContext)?|dth)|Lo(?:cationInRange|g(?:v|PageSize)?)|A(?:ccessibility(?:R(?:oleDescription(?:ForUIElement)?|aiseBadArgumentException)|Unignored(?:Children(?:ForOnlyChild)?|Descendant|Ancestor)|PostNotification|ActionDescription)|pplication(?:Main|Load)|vailableWindowDepths|ll(?:MapTable(?:Values|Keys)|HashTableObjects|ocate(?:MemoryPages|Collectable|Object)))))(?:\\b)"},{token:["support.class.cocoa.leopard"],regex:"(?:\\b)(NS(?:RuleEditor|G(?:arbageCollector|radient)|MapTable|HashTable|Co(?:ndition|llectionView(?:Item)?)|T(?:oolbarItemGroup|extInputClient|r(?:eeNode|ackingArea))|InvocationOperation|Operation(?:Queue)?|D(?:ictionaryController|ockTile)|P(?:ointer(?:Functions|Array)|athC(?:o(?:ntrol(?:Delegate)?|mponentCell)|ell(?:Delegate)?)|r(?:intPanelAccessorizing|edicateEditor(?:RowTemplate)?))|ViewController|FastEnumeration|Animat(?:ionContext|ablePropertyContainer)))(?:\\b)"},{token:["support.class.cocoa"],regex:"(?:\\b)(NS(?:R(?:u(?:nLoop|ler(?:Marker|View))|e(?:sponder|cursiveLock|lativeSpecifier)|an(?:domSpecifier|geSpecifier))|G(?:etCommand|lyph(?:Generator|Storage|Info)|raphicsContext)|XML(?:Node|D(?:ocument|TD(?:Node)?)|Parser|Element)|M(?:iddleSpecifier|ov(?:ie(?:View)?|eCommand)|utable(?:S(?:tring|et)|C(?:haracterSet|opying)|IndexSet|D(?:ictionary|ata)|URLRequest|ParagraphStyle|A(?:ttributedString|rray))|e(?:ssagePort(?:NameServer)?|nu(?:Item(?:Cell)?|View)?|t(?:hodSignature|adata(?:Item|Query(?:ResultGroup|AttributeValueTuple)?)))|a(?:ch(?:BootstrapServer|Port)|trix))|B(?:itmapImageRep|ox|u(?:ndle|tton(?:Cell)?)|ezierPath|rowser(?:Cell)?)|S(?:hadow|c(?:anner|r(?:ipt(?:SuiteRegistry|C(?:o(?:ercionHandler|mmand(?:Description)?)|lassDescription)|ObjectSpecifier|ExecutionContext|WhoseTest)|oll(?:er|View)|een))|t(?:epper(?:Cell)?|atus(?:Bar|Item)|r(?:ing|eam))|imple(?:HorizontalTypesetter|CString)|o(?:cketPort(?:NameServer)?|und|rtDescriptor)|p(?:e(?:cifierTest|ech(?:Recognizer|Synthesizer)|ll(?:Server|Checker))|litView)|e(?:cureTextField(?:Cell)?|t(?:Command)?|archField(?:Cell)?|rializer|gmentedC(?:ontrol|ell))|lider(?:Cell)?|avePanel)|H(?:ost|TTP(?:Cookie(?:Storage)?|URLResponse)|elpManager)|N(?:ib(?:Con(?:nector|trolConnector)|OutletConnector)?|otification(?:Center|Queue)?|u(?:ll|mber(?:Formatter)?)|etService(?:Browser)?|ameSpecifier)|C(?:ha(?:ngeSpelling|racterSet)|o(?:n(?:stantString|nection|trol(?:ler)?|ditionLock)|d(?:ing|er)|unt(?:Command|edSet)|pying|lor(?:Space|P(?:ick(?:ing(?:Custom|Default)|er)|anel)|Well|List)?|m(?:p(?:oundPredicate|arisonPredicate)|boBox(?:Cell)?))|u(?:stomImageRep|rsor)|IImageRep|ell|l(?:ipView|o(?:seCommand|neCommand)|assDescription)|a(?:ched(?:ImageRep|URLResponse)|lendar(?:Date)?)|reateCommand)|T(?:hread|ypesetter|ime(?:Zone|r)|o(?:olbar(?:Item(?:Validations)?)?|kenField(?:Cell)?)|ext(?:Block|Storage|Container|Tab(?:le(?:Block)?)?|Input|View|Field(?:Cell)?|List|Attachment(?:Cell)?)?|a(?:sk|b(?:le(?:Header(?:Cell|View)|Column|View)|View(?:Item)?))|reeController)|I(?:n(?:dex(?:S(?:pecifier|et)|Path)|put(?:Manager|S(?:tream|erv(?:iceProvider|er(?:MouseTracker)?)))|vocation)|gnoreMisspelledWords|mage(?:Rep|Cell|View)?)|O(?:ut(?:putStream|lineView)|pen(?:GL(?:Context|Pixel(?:Buffer|Format)|View)|Panel)|bj(?:CTypeSerializationCallBack|ect(?:Controller)?))|D(?:i(?:st(?:antObject(?:Request)?|ributed(?:NotificationCenter|Lock))|ctionary|rectoryEnumerator)|ocument(?:Controller)?|e(?:serializer|cimalNumber(?:Behaviors|Handler)?|leteCommand)|at(?:e(?:Components|Picker(?:Cell)?|Formatter)?|a)|ra(?:wer|ggingInfo))|U(?:ser(?:InterfaceValidations|Defaults(?:Controller)?)|RL(?:Re(?:sponse|quest)|Handle(?:Client)?|C(?:onnection|ache|redential(?:Storage)?)|Download(?:Delegate)?|Prot(?:ocol(?:Client)?|ectionSpace)|AuthenticationChallenge(?:Sender)?)?|n(?:iqueIDSpecifier|doManager|archiver))|P(?:ipe|o(?:sitionalSpecifier|pUpButton(?:Cell)?|rt(?:Message|NameServer|Coder)?)|ICTImageRep|ersistentDocument|DFImageRep|a(?:steboard|nel|ragraphStyle|geLayout)|r(?:int(?:Info|er|Operation|Panel)|o(?:cessInfo|tocolChecker|perty(?:Specifier|ListSerialization)|gressIndicator|xy)|edicate))|E(?:numerator|vent|PSImageRep|rror|x(?:ception|istsCommand|pression))|V(?:iew(?:Animation)?|al(?:idated(?:ToobarItem|UserInterfaceItem)|ue(?:Transformer)?))|Keyed(?:Unarchiver|Archiver)|Qui(?:ckDrawView|tCommand)|F(?:ile(?:Manager|Handle|Wrapper)|o(?:nt(?:Manager|Descriptor|Panel)?|rm(?:Cell|atter)))|W(?:hoseSpecifier|indow(?:Controller)?|orkspace)|L(?:o(?:c(?:k(?:ing)?|ale)|gicalTest)|evelIndicator(?:Cell)?|ayoutManager)|A(?:ssertionHandler|nimation|ctionCell|ttributedString|utoreleasePool|TSTypesetter|ppl(?:ication|e(?:Script|Event(?:Manager|Descriptor)))|ffineTransform|lert|r(?:chiver|ray(?:Controller)?))))(?:\\b)"},{token:["support.type.cocoa.leopard"],regex:"(?:\\b)(NS(?:R(?:u(?:nLoop|ler(?:Marker|View))|e(?:sponder|cursiveLock|lativeSpecifier)|an(?:domSpecifier|geSpecifier))|G(?:etCommand|lyph(?:Generator|Storage|Info)|raphicsContext)|XML(?:Node|D(?:ocument|TD(?:Node)?)|Parser|Element)|M(?:iddleSpecifier|ov(?:ie(?:View)?|eCommand)|utable(?:S(?:tring|et)|C(?:haracterSet|opying)|IndexSet|D(?:ictionary|ata)|URLRequest|ParagraphStyle|A(?:ttributedString|rray))|e(?:ssagePort(?:NameServer)?|nu(?:Item(?:Cell)?|View)?|t(?:hodSignature|adata(?:Item|Query(?:ResultGroup|AttributeValueTuple)?)))|a(?:ch(?:BootstrapServer|Port)|trix))|B(?:itmapImageRep|ox|u(?:ndle|tton(?:Cell)?)|ezierPath|rowser(?:Cell)?)|S(?:hadow|c(?:anner|r(?:ipt(?:SuiteRegistry|C(?:o(?:ercionHandler|mmand(?:Description)?)|lassDescription)|ObjectSpecifier|ExecutionContext|WhoseTest)|oll(?:er|View)|een))|t(?:epper(?:Cell)?|atus(?:Bar|Item)|r(?:ing|eam))|imple(?:HorizontalTypesetter|CString)|o(?:cketPort(?:NameServer)?|und|rtDescriptor)|p(?:e(?:cifierTest|ech(?:Recognizer|Synthesizer)|ll(?:Server|Checker))|litView)|e(?:cureTextField(?:Cell)?|t(?:Command)?|archField(?:Cell)?|rializer|gmentedC(?:ontrol|ell))|lider(?:Cell)?|avePanel)|H(?:ost|TTP(?:Cookie(?:Storage)?|URLResponse)|elpManager)|N(?:ib(?:Con(?:nector|trolConnector)|OutletConnector)?|otification(?:Center|Queue)?|u(?:ll|mber(?:Formatter)?)|etService(?:Browser)?|ameSpecifier)|C(?:ha(?:ngeSpelling|racterSet)|o(?:n(?:stantString|nection|trol(?:ler)?|ditionLock)|d(?:ing|er)|unt(?:Command|edSet)|pying|lor(?:Space|P(?:ick(?:ing(?:Custom|Default)|er)|anel)|Well|List)?|m(?:p(?:oundPredicate|arisonPredicate)|boBox(?:Cell)?))|u(?:stomImageRep|rsor)|IImageRep|ell|l(?:ipView|o(?:seCommand|neCommand)|assDescription)|a(?:ched(?:ImageRep|URLResponse)|lendar(?:Date)?)|reateCommand)|T(?:hread|ypesetter|ime(?:Zone|r)|o(?:olbar(?:Item(?:Validations)?)?|kenField(?:Cell)?)|ext(?:Block|Storage|Container|Tab(?:le(?:Block)?)?|Input|View|Field(?:Cell)?|List|Attachment(?:Cell)?)?|a(?:sk|b(?:le(?:Header(?:Cell|View)|Column|View)|View(?:Item)?))|reeController)|I(?:n(?:dex(?:S(?:pecifier|et)|Path)|put(?:Manager|S(?:tream|erv(?:iceProvider|er(?:MouseTracker)?)))|vocation)|gnoreMisspelledWords|mage(?:Rep|Cell|View)?)|O(?:ut(?:putStream|lineView)|pen(?:GL(?:Context|Pixel(?:Buffer|Format)|View)|Panel)|bj(?:CTypeSerializationCallBack|ect(?:Controller)?))|D(?:i(?:st(?:antObject(?:Request)?|ributed(?:NotificationCenter|Lock))|ctionary|rectoryEnumerator)|ocument(?:Controller)?|e(?:serializer|cimalNumber(?:Behaviors|Handler)?|leteCommand)|at(?:e(?:Components|Picker(?:Cell)?|Formatter)?|a)|ra(?:wer|ggingInfo))|U(?:ser(?:InterfaceValidations|Defaults(?:Controller)?)|RL(?:Re(?:sponse|quest)|Handle(?:Client)?|C(?:onnection|ache|redential(?:Storage)?)|Download(?:Delegate)?|Prot(?:ocol(?:Client)?|ectionSpace)|AuthenticationChallenge(?:Sender)?)?|n(?:iqueIDSpecifier|doManager|archiver))|P(?:ipe|o(?:sitionalSpecifier|pUpButton(?:Cell)?|rt(?:Message|NameServer|Coder)?)|ICTImageRep|ersistentDocument|DFImageRep|a(?:steboard|nel|ragraphStyle|geLayout)|r(?:int(?:Info|er|Operation|Panel)|o(?:cessInfo|tocolChecker|perty(?:Specifier|ListSerialization)|gressIndicator|xy)|edicate))|E(?:numerator|vent|PSImageRep|rror|x(?:ception|istsCommand|pression))|V(?:iew(?:Animation)?|al(?:idated(?:ToobarItem|UserInterfaceItem)|ue(?:Transformer)?))|Keyed(?:Unarchiver|Archiver)|Qui(?:ckDrawView|tCommand)|F(?:ile(?:Manager|Handle|Wrapper)|o(?:nt(?:Manager|Descriptor|Panel)?|rm(?:Cell|atter)))|W(?:hoseSpecifier|indow(?:Controller)?|orkspace)|L(?:o(?:c(?:k(?:ing)?|ale)|gicalTest)|evelIndicator(?:Cell)?|ayoutManager)|A(?:ssertionHandler|nimation|ctionCell|ttributedString|utoreleasePool|TSTypesetter|ppl(?:ication|e(?:Script|Event(?:Manager|Descriptor)))|ffineTransform|lert|r(?:chiver|ray(?:Controller)?))))(?:\\b)"},{token:["support.class.quartz"],regex:"(?:\\b)(C(?:I(?:Sampler|Co(?:ntext|lor)|Image(?:Accumulator)?|PlugIn(?:Registration)?|Vector|Kernel|Filter(?:Generator|Shape)?)|A(?:Renderer|MediaTiming(?:Function)?|BasicAnimation|ScrollLayer|Constraint(?:LayoutManager)?|T(?:iledLayer|extLayer|rans(?:ition|action))|OpenGLLayer|PropertyAnimation|KeyframeAnimation|Layer|A(?:nimation(?:Group)?|ction))))(?:\\b)"},{token:["support.type.quartz"],regex:"(?:\\b)(C(?:G(?:Float|Point|Size|Rect)|IFormat|AConstraintAttribute))(?:\\b)"},{token:["support.type.cocoa"],regex:"(?:\\b)(NS(?:R(?:ect(?:Edge)?|ange)|G(?:lyph(?:Relation|LayoutMode)?|radientType)|M(?:odalSession|a(?:trixMode|p(?:Table|Enumerator)))|B(?:itmapImageFileType|orderType|uttonType|ezelStyle|ackingStoreType|rowserColumnResizingType)|S(?:cr(?:oll(?:er(?:Part|Arrow)|ArrowPosition)|eenAuxiliaryOpaque)|tringEncoding|ize|ocketNativeHandle|election(?:Granularity|Direction|Affinity)|wapped(?:Double|Float)|aveOperationType)|Ha(?:sh(?:Table|Enumerator)|ndler(?:2)?)|C(?:o(?:ntrol(?:Size|Tint)|mp(?:ositingOperation|arisonResult))|ell(?:State|Type|ImagePosition|Attribute))|T(?:hreadPrivate|ypesetterGlyphInfo|i(?:ckMarkPosition|tlePosition|meInterval)|o(?:ol(?:TipTag|bar(?:SizeMode|DisplayMode))|kenStyle)|IFFCompression|ext(?:TabType|Alignment)|ab(?:State|leViewDropOperation|ViewType)|rackingRectTag)|ImageInterpolation|Zone|OpenGL(?:ContextAuxiliary|PixelFormatAuxiliary)|D(?:ocumentChangeType|atePickerElementFlags|ra(?:werState|gOperation))|UsableScrollerParts|P(?:oint|r(?:intingPageOrder|ogressIndicator(?:Style|Th(?:ickness|readInfo))))|EventType|KeyValueObservingOptions|Fo(?:nt(?:SymbolicTraits|TraitMask|Action)|cusRingType)|W(?:indow(?:OrderingMode|Depth)|orkspace(?:IconCreationOptions|LaunchOptions)|ritingDirection)|L(?:ineBreakMode|ayout(?:Status|Direction))|A(?:nimation(?:Progress|Effect)|ppl(?:ication(?:TerminateReply|DelegateReply|PrintReply)|eEventManagerSuspensionID)|ffineTransformStruct|lertStyle)))(?:\\b)"},{token:["support.constant.cocoa"],regex:"(?:\\b)(NS(?:NotFound|Ordered(?:Ascending|Descending|Same)))(?:\\b)"},{token:["support.constant.notification.cocoa.leopard"],regex:"(?:\\b)(NS(?:MenuDidBeginTracking|ViewDidUpdateTrackingAreas)?Notification)(?:\\b)"},{token:["support.constant.notification.cocoa"],regex:"(?:\\b)(NS(?:Menu(?:Did(?:RemoveItem|SendAction|ChangeItem|EndTracking|AddItem)|WillSendAction)|S(?:ystemColorsDidChange|plitView(?:DidResizeSubviews|WillResizeSubviews))|C(?:o(?:nt(?:extHelpModeDid(?:Deactivate|Activate)|rolT(?:intDidChange|extDid(?:BeginEditing|Change|EndEditing)))|lor(?:PanelColorDidChange|ListDidChange)|mboBox(?:Selection(?:IsChanging|DidChange)|Will(?:Dismiss|PopUp)))|lassDescriptionNeededForClass)|T(?:oolbar(?:DidRemoveItem|WillAddItem)|ext(?:Storage(?:DidProcessEditing|WillProcessEditing)|Did(?:BeginEditing|Change|EndEditing)|View(?:DidChange(?:Selection|TypingAttributes)|WillChangeNotifyingTextView))|ableView(?:Selection(?:IsChanging|DidChange)|ColumnDid(?:Resize|Move)))|ImageRepRegistryDidChange|OutlineView(?:Selection(?:IsChanging|DidChange)|ColumnDid(?:Resize|Move)|Item(?:Did(?:Collapse|Expand)|Will(?:Collapse|Expand)))|Drawer(?:Did(?:Close|Open)|Will(?:Close|Open))|PopUpButton(?:CellWillPopUp|WillPopUp)|View(?:GlobalFrameDidChange|BoundsDidChange|F(?:ocusDidChange|rameDidChange))|FontSetChanged|W(?:indow(?:Did(?:Resi(?:ze|gn(?:Main|Key))|M(?:iniaturize|ove)|Become(?:Main|Key)|ChangeScreen(?:|Profile)|Deminiaturize|Update|E(?:ndSheet|xpose))|Will(?:M(?:iniaturize|ove)|BeginSheet|Close))|orkspace(?:SessionDid(?:ResignActive|BecomeActive)|Did(?:Mount|TerminateApplication|Unmount|PerformFileOperation|Wake|LaunchApplication)|Will(?:Sleep|Unmount|PowerOff|LaunchApplication)))|A(?:ntialiasThresholdChanged|ppl(?:ication(?:Did(?:ResignActive|BecomeActive|Hide|ChangeScreenParameters|U(?:nhide|pdate)|FinishLaunching)|Will(?:ResignActive|BecomeActive|Hide|Terminate|U(?:nhide|pdate)|FinishLaunching))|eEventManagerWillProcessFirstEvent)))Notification)(?:\\b)"},{token:["support.constant.cocoa.leopard"],regex:"(?:\\b)(NS(?:RuleEditor(?:RowType(?:Simple|Compound)|NestingMode(?:Si(?:ngle|mple)|Compound|List))|GradientDraws(?:BeforeStartingLocation|AfterEndingLocation)|M(?:inusSetExpressionType|a(?:chPortDeallocate(?:ReceiveRight|SendRight|None)|pTable(?:StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality)))|B(?:oxCustom|undleExecutableArchitecture(?:X86|I386|PPC(?:64)?)|etweenPredicateOperatorType|ackgroundStyle(?:Raised|Dark|L(?:ight|owered)))|S(?:tring(?:DrawingTruncatesLastVisibleLine|EncodingConversion(?:ExternalRepresentation|AllowLossy))|ubqueryExpressionType|p(?:e(?:ech(?:SentenceBoundary|ImmediateBoundary|WordBoundary)|llingState(?:GrammarFlag|SpellingFlag))|litViewDividerStyleThi(?:n|ck))|e(?:rvice(?:RequestTimedOutError|M(?:iscellaneousError|alformedServiceDictionaryError)|InvalidPasteboardDataError|ErrorM(?:inimum|aximum)|Application(?:NotFoundError|LaunchFailedError))|gmentStyle(?:Round(?:Rect|ed)|SmallSquare|Capsule|Textured(?:Rounded|Square)|Automatic)))|H(?:UDWindowMask|ashTable(?:StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality))|N(?:oModeColorPanel|etServiceNoAutoRename)|C(?:hangeRedone|o(?:ntainsPredicateOperatorType|l(?:orRenderingIntent(?:RelativeColorimetric|Saturation|Default|Perceptual|AbsoluteColorimetric)|lectorDisabledOption))|ellHit(?:None|ContentArea|TrackableArea|EditableTextArea))|T(?:imeZoneNameStyle(?:S(?:hort(?:Standard|DaylightSaving)|tandard)|DaylightSaving)|extFieldDatePickerStyle|ableViewSelectionHighlightStyle(?:Regular|SourceList)|racking(?:Mouse(?:Moved|EnteredAndExited)|CursorUpdate|InVisibleRect|EnabledDuringMouseDrag|A(?:ssumeInside|ctive(?:In(?:KeyWindow|ActiveApp)|WhenFirstResponder|Always))))|I(?:n(?:tersectSetExpressionType|dexedColorSpaceModel)|mageScale(?:None|Proportionally(?:Down|UpOrDown)|AxesIndependently))|Ope(?:nGLPFAAllowOfflineRenderers|rationQueue(?:DefaultMaxConcurrentOperationCount|Priority(?:High|Normal|Very(?:High|Low)|Low)))|D(?:iacriticInsensitiveSearch|ownloadsDirectory)|U(?:nionSetExpressionType|TF(?:16(?:BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)|32(?:BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)))|P(?:ointerFunctions(?:Ma(?:chVirtualMemory|llocMemory)|Str(?:ongMemory|uctPersonality)|C(?:StringPersonality|opyIn)|IntegerPersonality|ZeroingWeakMemory|O(?:paque(?:Memory|Personality)|bjectP(?:ointerPersonality|ersonality)))|at(?:hStyle(?:Standard|NavigationBar|PopUp)|ternColorSpaceModel)|rintPanelShows(?:Scaling|Copies|Orientation|P(?:a(?:perSize|ge(?:Range|SetupAccessory))|review)))|Executable(?:RuntimeMismatchError|NotLoadableError|ErrorM(?:inimum|aximum)|L(?:inkError|oadError)|ArchitectureMismatchError)|KeyValueObservingOption(?:Initial|Prior)|F(?:i(?:ndPanelSubstringMatchType(?:StartsWith|Contains|EndsWith|FullWord)|leRead(?:TooLargeError|UnknownStringEncodingError))|orcedOrderingSearch)|Wi(?:ndow(?:BackingLocation(?:MainMemory|Default|VideoMemory)|Sharing(?:Read(?:Only|Write)|None)|CollectionBehavior(?:MoveToActiveSpace|CanJoinAllSpaces|Default))|dthInsensitiveSearch)|AggregateExpressionType))(?:\\b)"},{token:["support.constant.cocoa"],regex:"(?:\\b)(NS(?:R(?:GB(?:ModeColorPanel|ColorSpaceModel)|ight(?:Mouse(?:D(?:own(?:Mask)?|ragged(?:Mask)?)|Up(?:Mask)?)|T(?:ext(?:Movement|Alignment)|ab(?:sBezelBorder|StopType))|ArrowFunctionKey)|ound(?:RectBezelStyle|Bankers|ed(?:BezelStyle|TokenStyle|DisclosureBezelStyle)|Down|Up|Plain|Line(?:CapStyle|JoinStyle))|un(?:StoppedResponse|ContinuesResponse|AbortedResponse)|e(?:s(?:izableWindowMask|et(?:CursorRectsRunLoopOrdering|FunctionKey))|ce(?:ssedBezelStyle|iver(?:sCantHandleCommandScriptError|EvaluationScriptError))|turnTextMovement|doFunctionKey|quiredArgumentsMissingScriptError|l(?:evancyLevelIndicatorStyle|ative(?:Before|After))|gular(?:SquareBezelStyle|ControlSize)|moveTraitFontAction)|a(?:n(?:domSubelement|geDateMode)|tingLevelIndicatorStyle|dio(?:ModeMatrix|Button)))|G(?:IFFileType|lyph(?:Below|Inscribe(?:B(?:elow|ase)|Over(?:strike|Below)|Above)|Layout(?:WithPrevious|A(?:tAPoint|gainstAPoint))|A(?:ttribute(?:BidiLevel|Soft|Inscribe|Elastic)|bove))|r(?:ooveBorder|eaterThan(?:Comparison|OrEqualTo(?:Comparison|PredicateOperatorType)|PredicateOperatorType)|a(?:y(?:ModeColorPanel|ColorSpaceModel)|dient(?:None|Con(?:cave(?:Strong|Weak)|vex(?:Strong|Weak)))|phiteControlTint)))|XML(?:N(?:o(?:tationDeclarationKind|de(?:CompactEmptyElement|IsCDATA|OptionsNone|Use(?:SingleQuotes|DoubleQuotes)|Pre(?:serve(?:NamespaceOrder|C(?:haracterReferences|DATA)|DTD|Prefixes|E(?:ntities|mptyElements)|Quotes|Whitespace|A(?:ttributeOrder|ll))|ttyPrint)|ExpandEmptyElement))|amespaceKind)|CommentKind|TextKind|InvalidKind|D(?:ocument(?:X(?:MLKind|HTMLKind|Include)|HTMLKind|T(?:idy(?:XML|HTML)|extKind)|IncludeContentTypeDeclaration|Validate|Kind)|TDKind)|P(?:arser(?:GTRequiredError|XMLDeclNot(?:StartedError|FinishedError)|Mi(?:splaced(?:XMLDeclarationError|CDATAEndStringError)|xedContentDeclNot(?:StartedError|FinishedError))|S(?:t(?:andaloneValueError|ringNot(?:StartedError|ClosedError))|paceRequiredError|eparatorRequiredError)|N(?:MTOKENRequiredError|o(?:t(?:ationNot(?:StartedError|FinishedError)|WellBalancedError)|DTDError)|amespaceDeclarationError|AMERequiredError)|C(?:haracterRef(?:In(?:DTDError|PrologError|EpilogError)|AtEOFError)|o(?:nditionalSectionNot(?:StartedError|FinishedError)|mment(?:NotFinishedError|ContainsDoubleHyphenError))|DATANotFinishedError)|TagNameMismatchError|In(?:ternalError|valid(?:HexCharacterRefError|C(?:haracter(?:RefError|InEntityError|Error)|onditionalSectionError)|DecimalCharacterRefError|URIError|Encoding(?:NameError|Error)))|OutOfMemoryError|D(?:ocumentStartError|elegateAbortedParseError|OCTYPEDeclNotFinishedError)|U(?:RI(?:RequiredError|FragmentError)|n(?:declaredEntityError|parsedEntityError|knownEncodingError|finishedTagError))|P(?:CDATARequiredError|ublicIdentifierRequiredError|arsedEntityRef(?:MissingSemiError|NoNameError|In(?:Internal(?:SubsetError|Error)|PrologError|EpilogError)|AtEOFError)|r(?:ocessingInstructionNot(?:StartedError|FinishedError)|ematureDocumentEndError))|E(?:n(?:codingNotSupportedError|tity(?:Ref(?:In(?:DTDError|PrologError|EpilogError)|erence(?:MissingSemiError|WithoutNameError)|LoopError|AtEOFError)|BoundaryError|Not(?:StartedError|FinishedError)|Is(?:ParameterError|ExternalError)|ValueRequiredError))|qualExpectedError|lementContentDeclNot(?:StartedError|FinishedError)|xt(?:ernalS(?:tandaloneEntityError|ubsetNotFinishedError)|raContentError)|mptyDocumentError)|L(?:iteralNot(?:StartedError|FinishedError)|T(?:RequiredError|SlashRequiredError)|essThanSymbolInAttributeError)|Attribute(?:RedefinedError|HasNoValueError|Not(?:StartedError|FinishedError)|ListNot(?:StartedError|FinishedError)))|rocessingInstructionKind)|E(?:ntity(?:GeneralKind|DeclarationKind|UnparsedKind|P(?:ar(?:sedKind|ameterKind)|redefined))|lement(?:Declaration(?:MixedKind|UndefinedKind|E(?:lementKind|mptyKind)|Kind|AnyKind)|Kind))|Attribute(?:N(?:MToken(?:sKind|Kind)|otationKind)|CDATAKind|ID(?:Ref(?:sKind|Kind)|Kind)|DeclarationKind|En(?:tit(?:yKind|iesKind)|umerationKind)|Kind))|M(?:i(?:n(?:XEdge|iaturizableWindowMask|YEdge|uteCalendarUnit)|terLineJoinStyle|ddleSubelement|xedState)|o(?:nthCalendarUnit|deSwitchFunctionKey|use(?:Moved(?:Mask)?|E(?:ntered(?:Mask)?|ventSubtype|xited(?:Mask)?))|veToBezierPathElement|mentary(?:ChangeButton|Push(?:Button|InButton)|Light(?:Button)?))|enuFunctionKey|a(?:c(?:intoshInterfaceStyle|OSRomanStringEncoding)|tchesPredicateOperatorType|ppedRead|x(?:XEdge|YEdge))|ACHOperatingSystem)|B(?:MPFileType|o(?:ttomTabsBezelBorder|ldFontMask|rderlessWindowMask|x(?:Se(?:condary|parator)|OldStyle|Primary))|uttLineCapStyle|e(?:zelBorder|velLineJoinStyle|low(?:Bottom|Top)|gin(?:sWith(?:Comparison|PredicateOperatorType)|FunctionKey))|lueControlTint|ack(?:spaceCharacter|tabTextMovement|ingStore(?:Retained|Buffered|Nonretained)|TabCharacter|wardsSearch|groundTab)|r(?:owser(?:NoColumnResizing|UserColumnResizing|AutoColumnResizing)|eakFunctionKey))|S(?:h(?:ift(?:JISStringEncoding|KeyMask)|ow(?:ControlGlyphs|InvisibleGlyphs)|adowlessSquareBezelStyle)|y(?:s(?:ReqFunctionKey|tem(?:D(?:omainMask|efined(?:Mask)?)|FunctionKey))|mbolStringEncoding)|c(?:a(?:nnedOption|le(?:None|ToFit|Proportionally))|r(?:oll(?:er(?:NoPart|Increment(?:Page|Line|Arrow)|Decrement(?:Page|Line|Arrow)|Knob(?:Slot)?|Arrows(?:M(?:inEnd|axEnd)|None|DefaultSetting))|Wheel(?:Mask)?|LockFunctionKey)|eenChangedEventType))|t(?:opFunctionKey|r(?:ingDrawing(?:OneShot|DisableScreenFontSubstitution|Uses(?:DeviceMetrics|FontLeading|LineFragmentOrigin))|eam(?:Status(?:Reading|NotOpen|Closed|Open(?:ing)?|Error|Writing|AtEnd)|Event(?:Has(?:BytesAvailable|SpaceAvailable)|None|OpenCompleted|E(?:ndEncountered|rrorOccurred)))))|i(?:ngle(?:DateMode|UnderlineStyle)|ze(?:DownFontAction|UpFontAction))|olarisOperatingSystem|unOSOperatingSystem|pecialPageOrder|e(?:condCalendarUnit|lect(?:By(?:Character|Paragraph|Word)|i(?:ng(?:Next|Previous)|onAffinity(?:Downstream|Upstream))|edTab|FunctionKey)|gmentSwitchTracking(?:Momentary|Select(?:One|Any)))|quareLineCapStyle|witchButton|ave(?:ToOperation|Op(?:tions(?:Yes|No|Ask)|eration)|AsOperation)|mall(?:SquareBezelStyle|C(?:ontrolSize|apsFontMask)|IconButtonBezelStyle))|H(?:ighlightModeMatrix|SBModeColorPanel|o(?:ur(?:Minute(?:SecondDatePickerElementFlag|DatePickerElementFlag)|CalendarUnit)|rizontalRuler|meFunctionKey)|TTPCookieAcceptPolicy(?:Never|OnlyFromMainDocumentDomain|Always)|e(?:lp(?:ButtonBezelStyle|KeyMask|FunctionKey)|avierFontAction)|PUXOperatingSystem)|Year(?:MonthDa(?:yDatePickerElementFlag|tePickerElementFlag)|CalendarUnit)|N(?:o(?:n(?:StandardCharacterSetFontMask|ZeroWindingRule|activatingPanelMask|LossyASCIIStringEncoding)|Border|t(?:ification(?:SuspensionBehavior(?:Hold|Coalesce|D(?:eliverImmediately|rop))|NoCoalescing|CoalescingOn(?:Sender|Name)|DeliverImmediately|PostToAllSessions)|PredicateType|EqualToPredicateOperatorType)|S(?:cr(?:iptError|ollerParts)|ubelement|pecifierError)|CellMask|T(?:itle|opLevelContainersSpecifierError|abs(?:BezelBorder|NoBorder|LineBorder))|I(?:nterfaceStyle|mage)|UnderlineStyle|FontChangeAction)|u(?:ll(?:Glyph|CellType)|m(?:eric(?:Search|PadKeyMask)|berFormatter(?:Round(?:Half(?:Down|Up|Even)|Ceiling|Down|Up|Floor)|Behavior(?:10|Default)|S(?:cientificStyle|pellOutStyle)|NoStyle|CurrencyStyle|DecimalStyle|P(?:ercentStyle|ad(?:Before(?:Suffix|Prefix)|After(?:Suffix|Prefix))))))|e(?:t(?:Services(?:BadArgumentError|NotFoundError|C(?:ollisionError|ancelledError)|TimeoutError|InvalidError|UnknownError|ActivityInProgress)|workDomainMask)|wlineCharacter|xt(?:StepInterfaceStyle|FunctionKey))|EXTSTEPStringEncoding|a(?:t(?:iveShortGlyphPacking|uralTextAlignment)|rrowFontMask))|C(?:hange(?:ReadOtherContents|GrayCell(?:Mask)?|BackgroundCell(?:Mask)?|Cleared|Done|Undone|Autosaved)|MYK(?:ModeColorPanel|ColorSpaceModel)|ircular(?:BezelStyle|Slider)|o(?:n(?:stantValueExpressionType|t(?:inuousCapacityLevelIndicatorStyle|entsCellMask|ain(?:sComparison|erSpecifierError)|rol(?:Glyph|KeyMask))|densedFontMask)|lor(?:Panel(?:RGBModeMask|GrayModeMask|HSBModeMask|C(?:MYKModeMask|olorListModeMask|ustomPaletteModeMask|rayonModeMask)|WheelModeMask|AllModesMask)|ListModeColorPanel)|reServiceDirectory|m(?:p(?:osite(?:XOR|Source(?:In|O(?:ut|ver)|Atop)|Highlight|C(?:opy|lear)|Destination(?:In|O(?:ut|ver)|Atop)|Plus(?:Darker|Lighter))|ressedFontMask)|mandKeyMask))|u(?:stom(?:SelectorPredicateOperatorType|PaletteModeColorPanel)|r(?:sor(?:Update(?:Mask)?|PointingDevice)|veToBezierPathElement))|e(?:nterT(?:extAlignment|abStopType)|ll(?:State|H(?:ighlighted|as(?:Image(?:Horizontal|OnLeftOrBottom)|OverlappingImage))|ChangesContents|Is(?:Bordered|InsetButton)|Disabled|Editable|LightsBy(?:Gray|Background|Contents)|AllowsMixedState))|l(?:ipPagination|o(?:s(?:ePathBezierPathElement|ableWindowMask)|ckAndCalendarDatePickerStyle)|ear(?:ControlTint|DisplayFunctionKey|LineFunctionKey))|a(?:seInsensitive(?:Search|PredicateOption)|n(?:notCreateScriptCommandError|cel(?:Button|TextMovement))|chesDirectory|lculation(?:NoError|Overflow|DivideByZero|Underflow|LossOfPrecision)|rriageReturnCharacter)|r(?:itical(?:Request|AlertStyle)|ayonModeColorPanel))|T(?:hick(?:SquareBezelStyle|erSquareBezelStyle)|ypesetter(?:Behavior|HorizontalTabAction|ContainerBreakAction|ZeroAdvancementAction|OriginalBehavior|ParagraphBreakAction|WhitespaceAction|L(?:ineBreakAction|atestBehavior))|i(?:ckMark(?:Right|Below|Left|Above)|tledWindowMask|meZoneDatePickerElementFlag)|o(?:olbarItemVisibilityPriority(?:Standard|High|User|Low)|pTabsBezelBorder|ggleButton)|IFF(?:Compression(?:N(?:one|EXT)|CCITTFAX(?:3|4)|OldJPEG|JPEG|PackBits|LZW)|FileType)|e(?:rminate(?:Now|Cancel|Later)|xt(?:Read(?:InapplicableDocumentTypeError|WriteErrorM(?:inimum|aximum))|Block(?:M(?:i(?:nimum(?:Height|Width)|ddleAlignment)|a(?:rgin|ximum(?:Height|Width)))|B(?:o(?:ttomAlignment|rder)|aselineAlignment)|Height|TopAlignment|P(?:ercentageValueType|adding)|Width|AbsoluteValueType)|StorageEdited(?:Characters|Attributes)|CellType|ured(?:RoundedBezelStyle|BackgroundWindowMask|SquareBezelStyle)|Table(?:FixedLayoutAlgorithm|AutomaticLayoutAlgorithm)|Field(?:RoundedBezel|SquareBezel|AndStepperDatePickerStyle)|WriteInapplicableDocumentTypeError|ListPrependEnclosingMarker))|woByteGlyphPacking|ab(?:Character|TextMovement|le(?:tP(?:oint(?:Mask|EventSubtype)?|roximity(?:Mask|EventSubtype)?)|Column(?:NoResizing|UserResizingMask|AutoresizingMask)|View(?:ReverseSequentialColumnAutoresizingStyle|GridNone|S(?:olid(?:HorizontalGridLineMask|VerticalGridLineMask)|equentialColumnAutoresizingStyle)|NoColumnAutoresizing|UniformColumnAutoresizingStyle|FirstColumnOnlyAutoresizingStyle|LastColumnOnlyAutoresizingStyle)))|rackModeMatrix)|I(?:n(?:sert(?:CharFunctionKey|FunctionKey|LineFunctionKey)|t(?:Type|ernalS(?:criptError|pecifierError))|dexSubelement|validIndexSpecifierError|formational(?:Request|AlertStyle)|PredicateOperatorType)|talicFontMask|SO(?:2022JPStringEncoding|Latin(?:1StringEncoding|2StringEncoding))|dentityMappingCharacterCollection|llegalTextMovement|mage(?:R(?:ight|ep(?:MatchesDevice|LoadStatus(?:ReadingHeader|Completed|InvalidData|Un(?:expectedEOF|knownType)|WillNeedAllData)))|Below|C(?:ellType|ache(?:BySize|Never|Default|Always))|Interpolation(?:High|None|Default|Low)|O(?:nly|verlaps)|Frame(?:Gr(?:oove|ayBezel)|Button|None|Photo)|L(?:oadStatus(?:ReadError|C(?:ompleted|ancelled)|InvalidData|UnexpectedEOF)|eft)|A(?:lign(?:Right|Bottom(?:Right|Left)?|Center|Top(?:Right|Left)?|Left)|bove)))|O(?:n(?:State|eByteGlyphPacking|OffButton|lyScrollerArrows)|ther(?:Mouse(?:D(?:own(?:Mask)?|ragged(?:Mask)?)|Up(?:Mask)?)|TextMovement)|SF1OperatingSystem|pe(?:n(?:GL(?:GO(?:Re(?:setLibrary|tainRenderers)|ClearFormatCache|FormatCacheSize)|PFA(?:R(?:obust|endererID)|M(?:inimumPolicy|ulti(?:sample|Screen)|PSafe|aximumPolicy)|BackingStore|S(?:creenMask|te(?:ncilSize|reo)|ingleRenderer|upersample|ample(?:s|Buffers|Alpha))|NoRecovery|C(?:o(?:lor(?:Size|Float)|mpliant)|losestPolicy)|OffScreen|D(?:oubleBuffer|epthSize)|PixelBuffer|VirtualScreenCount|FullScreen|Window|A(?:cc(?:umSize|elerated)|ux(?:Buffers|DepthStencil)|l(?:phaSize|lRenderers))))|StepUnicodeReservedBase)|rationNotSupportedForKeyS(?:criptError|pecifierError))|ffState|KButton|rPredicateType|bjC(?:B(?:itfield|oolType)|S(?:hortType|tr(?:ingType|uctType)|electorType)|NoType|CharType|ObjectType|DoubleType|UnionType|PointerType|VoidType|FloatType|Long(?:Type|longType)|ArrayType))|D(?:i(?:s(?:c(?:losureBezelStyle|reteCapacityLevelIndicatorStyle)|playWindowRunLoopOrdering)|acriticInsensitivePredicateOption|rect(?:Selection|PredicateModifier))|o(?:c(?:ModalWindowMask|ument(?:Directory|ationDirectory))|ubleType|wn(?:TextMovement|ArrowFunctionKey))|e(?:s(?:cendingPageOrder|ktopDirectory)|cimalTabStopType|v(?:ice(?:NColorSpaceModel|IndependentModifierFlagsMask)|eloper(?:Directory|ApplicationDirectory))|fault(?:ControlTint|TokenStyle)|lete(?:Char(?:acter|FunctionKey)|FunctionKey|LineFunctionKey)|moApplicationDirectory)|a(?:yCalendarUnit|teFormatter(?:MediumStyle|Behavior(?:10|Default)|ShortStyle|NoStyle|FullStyle|LongStyle))|ra(?:wer(?:Clos(?:ingState|edState)|Open(?:ingState|State))|gOperation(?:Generic|Move|None|Copy|Delete|Private|Every|Link|All)))|U(?:ser(?:CancelledError|D(?:irectory|omainMask)|FunctionKey)|RL(?:Handle(?:NotLoaded|Load(?:Succeeded|InProgress|Failed))|CredentialPersistence(?:None|Permanent|ForSession))|n(?:scaledWindowMask|cachedRead|i(?:codeStringEncoding|talicFontMask|fiedTitleAndToolbarWindowMask)|d(?:o(?:CloseGroupingRunLoopOrdering|FunctionKey)|e(?:finedDateComponent|rline(?:Style(?:Single|None|Thick|Double)|Pattern(?:Solid|D(?:ot|ash(?:Dot(?:Dot)?)?)))))|known(?:ColorSpaceModel|P(?:ointingDevice|ageOrder)|KeyS(?:criptError|pecifierError))|boldFontMask)|tilityWindowMask|TF8StringEncoding|p(?:dateWindowsRunLoopOrdering|TextMovement|ArrowFunctionKey))|J(?:ustifiedTextAlignment|PEG(?:2000FileType|FileType)|apaneseEUC(?:GlyphPacking|StringEncoding))|P(?:o(?:s(?:t(?:Now|erFontMask|WhenIdle|ASAP)|iti(?:on(?:Replace|Be(?:fore|ginning)|End|After)|ve(?:IntType|DoubleType|FloatType)))|pUp(?:NoArrow|ArrowAt(?:Bottom|Center))|werOffEventType|rtraitOrientation)|NGFileType|ush(?:InCell(?:Mask)?|OnPushOffButton)|e(?:n(?:TipMask|UpperSideMask|PointingDevice|LowerSideMask)|riodic(?:Mask)?)|P(?:S(?:caleField|tatus(?:Title|Field)|aveButton)|N(?:ote(?:Title|Field)|ame(?:Title|Field))|CopiesField|TitleField|ImageButton|OptionsButton|P(?:a(?:perFeedButton|ge(?:Range(?:To|From)|ChoiceMatrix))|reviewButton)|LayoutButton)|lainTextTokenStyle|a(?:useFunctionKey|ragraphSeparatorCharacter|ge(?:DownFunctionKey|UpFunctionKey))|r(?:int(?:ing(?:ReplyLater|Success|Cancelled|Failure)|ScreenFunctionKey|erTable(?:NotFound|OK|Error)|FunctionKey)|o(?:p(?:ertyList(?:XMLFormat|MutableContainers(?:AndLeaves)?|BinaryFormat|Immutable|OpenStepFormat)|rietaryStringEncoding)|gressIndicator(?:BarStyle|SpinningStyle|Preferred(?:SmallThickness|Thickness|LargeThickness|AquaThickness)))|e(?:ssedTab|vFunctionKey))|L(?:HeightForm|CancelButton|TitleField|ImageButton|O(?:KButton|rientationMatrix)|UnitsButton|PaperNameButton|WidthForm))|E(?:n(?:terCharacter|d(?:sWith(?:Comparison|PredicateOperatorType)|FunctionKey))|v(?:e(?:nOddWindingRule|rySubelement)|aluatedObjectExpressionType)|qualTo(?:Comparison|PredicateOperatorType)|ra(?:serPointingDevice|CalendarUnit|DatePickerElementFlag)|x(?:clude(?:10|QuickDrawElementsIconCreationOption)|pandedFontMask|ecuteFunctionKey))|V(?:i(?:ew(?:M(?:in(?:XMargin|YMargin)|ax(?:XMargin|YMargin))|HeightSizable|NotSizable|WidthSizable)|aPanelFontAction)|erticalRuler|a(?:lidationErrorM(?:inimum|aximum)|riableExpressionType))|Key(?:SpecifierEvaluationScriptError|Down(?:Mask)?|Up(?:Mask)?|PathExpressionType|Value(?:MinusSetMutation|SetSetMutation|Change(?:Re(?:placement|moval)|Setting|Insertion)|IntersectSetMutation|ObservingOption(?:New|Old)|UnionSetMutation|ValidationError))|QTMovie(?:NormalPlayback|Looping(?:BackAndForthPlayback|Playback))|F(?:1(?:1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|7FunctionKey|i(?:nd(?:PanelAction(?:Replace(?:A(?:ndFind|ll(?:InSelection)?))?|S(?:howFindPanel|e(?:tFindString|lectAll(?:InSelection)?))|Next|Previous)|FunctionKey)|tPagination|le(?:Read(?:No(?:SuchFileError|PermissionError)|CorruptFileError|In(?:validFileNameError|applicableStringEncodingError)|Un(?:supportedSchemeError|knownError))|HandlingPanel(?:CancelButton|OKButton)|NoSuchFileError|ErrorM(?:inimum|aximum)|Write(?:NoPermissionError|In(?:validFileNameError|applicableStringEncodingError)|OutOfSpaceError|Un(?:supportedSchemeError|knownError))|LockingError)|xedPitchFontMask)|2(?:1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|o(?:nt(?:Mo(?:noSpaceTrait|dernSerifsClass)|BoldTrait|S(?:ymbolicClass|criptsClass|labSerifsClass|ansSerifClass)|C(?:o(?:ndensedTrait|llectionApplicationOnlyMask)|larendonSerifsClass)|TransitionalSerifsClass|I(?:ntegerAdvancementsRenderingMode|talicTrait)|O(?:ldStyleSerifsClass|rnamentalsClass)|DefaultRenderingMode|U(?:nknownClass|IOptimizedTrait)|Panel(?:S(?:hadowEffectModeMask|t(?:andardModesMask|rikethroughEffectModeMask)|izeModeMask)|CollectionModeMask|TextColorEffectModeMask|DocumentColorEffectModeMask|UnderlineEffectModeMask|FaceModeMask|All(?:ModesMask|EffectsModeMask))|ExpandedTrait|VerticalTrait|F(?:amilyClassMask|reeformSerifsClass)|Antialiased(?:RenderingMode|IntegerAdvancementsRenderingMode))|cusRing(?:Below|Type(?:None|Default|Exterior)|Only|Above)|urByteGlyphPacking|rm(?:attingError(?:M(?:inimum|aximum))?|FeedCharacter))|8FunctionKey|unction(?:ExpressionType|KeyMask)|3(?:1FunctionKey|2FunctionKey|3FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey)|9FunctionKey|4FunctionKey|P(?:RevertButton|S(?:ize(?:Title|Field)|etButton)|CurrentField|Preview(?:Button|Field))|l(?:oat(?:ingPointSamplesBitmapFormat|Type)|agsChanged(?:Mask)?)|axButton|5FunctionKey|6FunctionKey)|W(?:heelModeColorPanel|indow(?:s(?:NTOperatingSystem|CP125(?:1StringEncoding|2StringEncoding|3StringEncoding|4StringEncoding|0StringEncoding)|95(?:InterfaceStyle|OperatingSystem))|M(?:iniaturizeButton|ovedEventType)|Below|CloseButton|ToolbarButton|ZoomButton|Out|DocumentIconButton|ExposedEventType|Above)|orkspaceLaunch(?:NewInstance|InhibitingBackgroundOnly|Default|PreferringClassic|WithoutA(?:ctivation|ddingToRecents)|A(?:sync|nd(?:Hide(?:Others)?|Print)|llowingClassicStartup))|eek(?:day(?:CalendarUnit|OrdinalCalendarUnit)|CalendarUnit)|a(?:ntsBidiLevels|rningAlertStyle)|r(?:itingDirection(?:RightToLeft|Natural|LeftToRight)|apCalendarComponents))|L(?:i(?:stModeMatrix|ne(?:Moves(?:Right|Down|Up|Left)|B(?:order|reakBy(?:C(?:harWrapping|lipping)|Truncating(?:Middle|Head|Tail)|WordWrapping))|S(?:eparatorCharacter|weep(?:Right|Down|Up|Left))|ToBezierPathElement|DoesntMove|arSlider)|teralSearch|kePredicateOperatorType|ghterFontAction|braryDirectory)|ocalDomainMask|e(?:ssThan(?:Comparison|OrEqualTo(?:Comparison|PredicateOperatorType)|PredicateOperatorType)|ft(?:Mouse(?:D(?:own(?:Mask)?|ragged(?:Mask)?)|Up(?:Mask)?)|T(?:ext(?:Movement|Alignment)|ab(?:sBezelBorder|StopType))|ArrowFunctionKey))|a(?:yout(?:RightToLeft|NotDone|CantFit|OutOfGlyphs|Done|LeftToRight)|ndscapeOrientation)|ABColorSpaceModel)|A(?:sc(?:iiWithDoubleByteEUCGlyphPacking|endingPageOrder)|n(?:y(?:Type|PredicateModifier|EventMask)|choredSearch|imation(?:Blocking|Nonblocking(?:Threaded)?|E(?:ffect(?:DisappearingItemDefault|Poof)|ase(?:In(?:Out)?|Out))|Linear)|dPredicateType)|t(?:Bottom|tachmentCharacter|omicWrite|Top)|SCIIStringEncoding|d(?:obe(?:GB1CharacterCollection|CNS1CharacterCollection|Japan(?:1CharacterCollection|2CharacterCollection)|Korea1CharacterCollection)|dTraitFontAction|minApplicationDirectory)|uto(?:saveOperation|Pagination)|pp(?:lication(?:SupportDirectory|D(?:irectory|e(?:fined(?:Mask)?|legateReply(?:Success|Cancel|Failure)|activatedEventType))|ActivatedEventType)|KitDefined(?:Mask)?)|l(?:ternateKeyMask|pha(?:ShiftKeyMask|NonpremultipliedBitmapFormat|FirstBitmapFormat)|ert(?:SecondButtonReturn|ThirdButtonReturn|OtherReturn|DefaultReturn|ErrorReturn|FirstButtonReturn|AlternateReturn)|l(?:ScrollerParts|DomainsMask|PredicateModifier|LibrariesDirectory|ApplicationsDirectory))|rgument(?:sWrongScriptError|EvaluationScriptError)|bove(?:Bottom|Top)|WTEventType)))(?:\\b)"},{token:"support.function.C99.c",regex:s.cFunctions},{token:n.getKeywords(),regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"punctuation.section.scope.begin.objc",regex:"\\[",next:"bracketed_content"},{token:"meta.function.objc",regex:"^(?:-|\\+)\\s*"}],constant_NSString:[{token:"constant.character.escape.objc",regex:e},{token:"invalid.illegal.unknown-escape.objc",regex:"\\\\."},{token:"string",regex:'[^"\\\\]+'},{token:"punctuation.definition.string.end",regex:'"',next:"start"}],protocol_list:[{token:"punctuation.section.scope.end.objc",regex:">",next:"start"},{token:"support.other.protocol.objc",regex:"\bNS(?:GlyphStorage|M(?:utableCopying|enuItem)|C(?:hangeSpelling|o(?:ding|pying|lorPicking(?:Custom|Default)))|T(?:oolbarItemValidations|ext(?:Input|AttachmentCell))|I(?:nputServ(?:iceProvider|erMouseTracker)|gnoreMisspelledWords)|Obj(?:CTypeSerializationCallBack|ect)|D(?:ecimalNumberBehaviors|raggingInfo)|U(?:serInterfaceValidations|RL(?:HandleClient|DownloadDelegate|ProtocolClient|AuthenticationChallengeSender))|Validated(?:ToobarItem|UserInterfaceItem)|Locking)\b"}],selectors:[{token:"support.function.any-method.name-of-parameter.objc",regex:"\\b(?:[a-zA-Z_:][\\w]*)+"},{token:"punctuation",regex:"\\)",next:"start"}],bracketed_content:[{token:"punctuation.section.scope.end.objc",regex:"]",next:"start"},{token:["support.function.any-method.objc"],regex:"(?:predicateWithFormat:| NSPredicate predicateWithFormat:)",next:"start"},{token:["support.function.any-method.objc","punctuation.separator.arguments.objc"],regex:"\\w+(?::|(?=]))",next:"start"}],bracketed_strings:[{token:"punctuation.section.scope.end.objc",regex:"]",next:"start"},{token:"keyword.operator.logical.predicate.cocoa",regex:"\\b(?:AND|OR|NOT|IN)\\b"},{token:["invalid.illegal.unknown-method.objc","punctuation.separator.arguments.objc"],regex:"\\b(w+)(:)"},{regex:"\\b(?:ALL|ANY|SOME|NONE)\\b",token:"constant.language.predicate.cocoa"},{regex:"\\b(?:NULL|NIL|SELF|TRUE|YES|FALSE|NO|FIRST|LAST|SIZE)\\b",token:"constant.language.predicate.cocoa"},{regex:"\\b(?:MATCHES|CONTAINS|BEGINSWITH|ENDSWITH|BETWEEN)\\b",token:"keyword.operator.comparison.predicate.cocoa"},{regex:"\\bC(?:ASEINSENSITIVE|I)\\b",token:"keyword.other.modifier.predicate.cocoa"},{regex:"\\b(?:ANYKEY|SUBQUERY|CAST|TRUEPREDICATE|FALSEPREDICATE)\\b",token:"keyword.other.predicate.cocoa"},{regex:e,token:"constant.character.escape.objc"},{regex:"\\\\.",token:"invalid.illegal.unknown-escape.objc"},{token:"string",regex:'[^"\\\\]'},{token:"punctuation.definition.string.end.objc",regex:'"',next:"predicates"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],methods:[{token:"meta.function.objc",regex:"(?=\\{|#)|;",next:"start"}]};for(var u in r)this.$rules[u]?this.$rules[u].push&&this.$rules[u].push.apply(this.$rules[u],r[u]):this.$rules[u]=r[u];this.$rules.bracketed_content=this.$rules.bracketed_content.concat(this.$rules.start,t),this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(u,o),t.ObjectiveCHighlightRules=u}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/c_cpp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=t.cFunctions="\\s*\\bhypot(?:f|l)?|s(?:scanf|ystem|nprintf|ca(?:nf|lb(?:n(?:f|l)?|ln(?:f|l)?))|i(?:n(?:h(?:f|l)?|f|l)?|gn(?:al|bit))|tr(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?)|error|pbrk|ftime|len|rchr|xfrm)|printf|et(?:jmp|vbuf|locale|buf)|qrt(?:f|l)?|w(?:scanf|printf)|rand)|n(?:e(?:arbyint(?:f|l)?|xt(?:toward(?:f|l)?|after(?:f|l)?))|an(?:f|l)?)|c(?:s(?:in(?:h(?:f|l)?|f|l)?|qrt(?:f|l)?)|cos(?:h(?:f)?|f|l)?|imag(?:f|l)?|t(?:ime|an(?:h(?:f|l)?|f|l)?)|o(?:s(?:h(?:f|l)?|f|l)?|nj(?:f|l)?|pysign(?:f|l)?)|p(?:ow(?:f|l)?|roj(?:f|l)?)|e(?:il(?:f|l)?|xp(?:f|l)?)|l(?:o(?:ck|g(?:f|l)?)|earerr)|a(?:sin(?:h(?:f|l)?|f|l)?|cos(?:h(?:f|l)?|f|l)?|tan(?:h(?:f|l)?|f|l)?|lloc|rg(?:f|l)?|bs(?:f|l)?)|real(?:f|l)?|brt(?:f|l)?)|t(?:ime|o(?:upper|lower)|an(?:h(?:f|l)?|f|l)?|runc(?:f|l)?|gamma(?:f|l)?|mp(?:nam|file))|i(?:s(?:space|n(?:ormal|an)|cntrl|inf|digit|u(?:nordered|pper)|p(?:unct|rint)|finite|w(?:space|c(?:ntrl|type)|digit|upper|p(?:unct|rint)|lower|al(?:num|pha)|graph|xdigit|blank)|l(?:ower|ess(?:equal|greater)?)|al(?:num|pha)|gr(?:eater(?:equal)?|aph)|xdigit|blank)|logb(?:f|l)?|max(?:div|abs))|di(?:v|fftime)|_Exit|unget(?:c|wc)|p(?:ow(?:f|l)?|ut(?:s|c(?:har)?|wc(?:har)?)|error|rintf)|e(?:rf(?:c(?:f|l)?|f|l)?|x(?:it|p(?:2(?:f|l)?|f|l|m1(?:f|l)?)?))|v(?:s(?:scanf|nprintf|canf|printf|w(?:scanf|printf))|printf|f(?:scanf|printf|w(?:scanf|printf))|w(?:scanf|printf)|a_(?:start|copy|end|arg))|qsort|f(?:s(?:canf|e(?:tpos|ek))|close|tell|open|dim(?:f|l)?|p(?:classify|ut(?:s|c|w(?:s|c))|rintf)|e(?:holdexcept|set(?:e(?:nv|xceptflag)|round)|clearexcept|testexcept|of|updateenv|r(?:aiseexcept|ror)|get(?:e(?:nv|xceptflag)|round))|flush|w(?:scanf|ide|printf|rite)|loor(?:f|l)?|abs(?:f|l)?|get(?:s|c|pos|w(?:s|c))|re(?:open|e|ad|xp(?:f|l)?)|m(?:in(?:f|l)?|od(?:f|l)?|a(?:f|l|x(?:f|l)?)?))|l(?:d(?:iv|exp(?:f|l)?)|o(?:ngjmp|cal(?:time|econv)|g(?:1(?:p(?:f|l)?|0(?:f|l)?)|2(?:f|l)?|f|l|b(?:f|l)?)?)|abs|l(?:div|abs|r(?:int(?:f|l)?|ound(?:f|l)?))|r(?:int(?:f|l)?|ound(?:f|l)?)|gamma(?:f|l)?)|w(?:scanf|c(?:s(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?|mbs)|pbrk|ftime|len|r(?:chr|tombs)|xfrm)|to(?:b|mb)|rtomb)|printf|mem(?:set|c(?:hr|py|mp)|move))|a(?:s(?:sert|ctime|in(?:h(?:f|l)?|f|l)?)|cos(?:h(?:f|l)?|f|l)?|t(?:o(?:i|f|l(?:l)?)|exit|an(?:h(?:f|l)?|2(?:f|l)?|f|l)?)|b(?:s|ort))|g(?:et(?:s|c(?:har)?|env|wc(?:har)?)|mtime)|r(?:int(?:f|l)?|ound(?:f|l)?|e(?:name|alloc|wind|m(?:ove|quo(?:f|l)?|ainder(?:f|l)?))|a(?:nd|ise))|b(?:search|towc)|m(?:odf(?:f|l)?|em(?:set|c(?:hr|py|mp)|move)|ktime|alloc|b(?:s(?:init|towcs|rtowcs)|towc|len|r(?:towc|len)))\\b",u=function(){var e="break|case|continue|default|do|else|for|goto|if|_Pragma|return|switch|while|catch|operator|try|throw|using",t="asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|_Imaginary|int|long|short|signed|struct|typedef|union|unsigned|void|class|wchar_t|template",n="const|extern|register|restrict|static|volatile|inline|private:|protected:|public:|friend|explicit|virtual|export|mutable|typename",r="and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eqconst_cast|dynamic_cast|reinterpret_cast|static_cast|sizeof|namespace",s="NULL|true|false|TRUE|FALSE",u=this.$keywords=this.createKeywordMapper({"keyword.control":e,"storage.type":t,"storage.modifier":n,"keyword.operator":r,"variable.language":"this","constant.language":s},"identifier"),a="[a-zA-Z\\$_¡-ï¿¿][a-zA-Zd\\$_¡-ï¿¿]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"keyword",regex:"(?:#include|#import|#pragma|#line|#define|#undef|#if|#ifdef|#else|#elif|#ifndef)\\b",next:"directive"},{token:"keyword",regex:"(?:#endif)\\b"},{token:"support.function.C99.c",regex:o},{token:u,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}],directive:[{token:"constant.other.multiline",regex:/\\/},{token:"constant.other",regex:"\\s*<.+?>",next:"start"},{token:"constant.other",regex:'\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]',next:"start"},{token:"constant.other",regex:"\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']",next:"start"},{token:"constant.other.multiline",regex:/.*\\/},{token:"constant.other",regex:/[^\\\/]+/,next:"start"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(u,s),t.c_cppHighlightRules=u}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-ocaml.js b/common/static/js/vendor/ace/mode-ocaml.js new file mode 100644 index 0000000000..f5d7190fd6 --- /dev/null +++ b/common/static/js/vendor/ace/mode-ocaml.js @@ -0,0 +1 @@ +ace.define("ace/mode/ocaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/ocaml_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./ocaml_highlight_rules").OcamlHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u};r.inherits(f,i);var l=/(?:[({[=:]|[-=]>|\b(?:else|try|with))\s*$/;(function(){this.toggleCommentLines=function(e,t,n,r){var i,s,o=!0,u=/^\s*\(\*(.*)\*\)/;for(i=n;i<=r;i++)if(!u.test(t.getLine(i))){o=!1;break}var f=new a(0,0,0,0);for(i=n;i<=r;i++)s=t.getLine(i),f.start.row=i,f.end.row=i,f.end.column=s.length,t.replace(f,o?s.match(u)[1]:"(*"+s+"*)")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;return(!i.length||i[i.length-1].type!=="comment")&&e==="start"&&l.test(t)&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}).call(f.prototype),t.Mode=f}),ace.define("ace/mode/ocaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|object|of|open|or|private|rec|sig|struct|then|to|try|type|val|virtual|when|while|with",t="true|false",n="abs|abs_big_int|abs_float|abs_num|abstract_tag|accept|access|acos|add|add_available_units|add_big_int|add_buffer|add_channel|add_char|add_initializer|add_int_big_int|add_interfaces|add_num|add_string|add_substitute|add_substring|alarm|allocated_bytes|allow_only|allow_unsafe_modules|always|append|appname_get|appname_set|approx_num_exp|approx_num_fix|arg|argv|arith_status|array|array1_of_genarray|array2_of_genarray|array3_of_genarray|asin|asr|assoc|assq|at_exit|atan|atan2|auto_synchronize|background|basename|beginning_of_input|big_int_of_int|big_int_of_num|big_int_of_string|bind|bind_class|bind_tag|bits|bits_of_float|black|blit|blit_image|blue|bool|bool_of_string|bounded_full_split|bounded_split|bounded_split_delim|bprintf|break|broadcast|bscanf|button_down|c_layout|capitalize|cardinal|cardinal|catch|catch_break|ceil|ceiling_num|channel|char|char_of_int|chdir|check|check_suffix|chmod|choose|chop_extension|chop_suffix|chown|chown|chr|chroot|classify_float|clear|clear_available_units|clear_close_on_exec|clear_graph|clear_nonblock|clear_parser|close|close|closeTk|close_box|close_graph|close_in|close_in_noerr|close_out|close_out_noerr|close_process|close_process|close_process_full|close_process_in|close_process_out|close_subwindow|close_tag|close_tbox|closedir|closedir|closure_tag|code|combine|combine|combine|command|compact|compare|compare_big_int|compare_num|complex32|complex64|concat|conj|connect|contains|contains_from|contents|copy|cos|cosh|count|count|counters|create|create_alarm|create_image|create_matrix|create_matrix|create_matrix|create_object|create_object_and_run_initializers|create_object_opt|create_process|create_process|create_process_env|create_process_env|create_table|current|current_dir_name|current_point|current_x|current_y|curveto|custom_tag|cyan|data_size|decr|decr_num|default_available_units|delay|delete_alarm|descr_of_in_channel|descr_of_out_channel|destroy|diff|dim|dim1|dim2|dim3|dims|dirname|display_mode|div|div_big_int|div_num|double_array_tag|double_tag|draw_arc|draw_char|draw_circle|draw_ellipse|draw_image|draw_poly|draw_poly_line|draw_rect|draw_segments|draw_string|dummy_pos|dummy_table|dump_image|dup|dup2|elements|empty|end_of_input|environment|eprintf|epsilon_float|eq_big_int|eq_num|equal|err_formatter|error_message|escaped|establish_server|executable_name|execv|execve|execvp|execvpe|exists|exists2|exit|exp|failwith|fast_sort|fchmod|fchown|field|file|file_exists|fill|fill_arc|fill_circle|fill_ellipse|fill_poly|fill_rect|filter|final_tag|finalise|find|find_all|first_chars|firstkey|flatten|float|float32|float64|float_of_big_int|float_of_bits|float_of_int|float_of_num|float_of_string|floor|floor_num|flush|flush_all|flush_input|flush_str_formatter|fold|fold_left|fold_left2|fold_right|fold_right2|for_all|for_all2|force|force_newline|force_val|foreground|fork|format_of_string|formatter_of_buffer|formatter_of_out_channel|fortran_layout|forward_tag|fprintf|frexp|from|from_channel|from_file|from_file_bin|from_function|from_string|fscanf|fst|fstat|ftruncate|full_init|full_major|full_split|gcd_big_int|ge_big_int|ge_num|genarray_of_array1|genarray_of_array2|genarray_of_array3|get|get_all_formatter_output_functions|get_approx_printing|get_copy|get_ellipsis_text|get_error_when_null_denominator|get_floating_precision|get_formatter_output_functions|get_formatter_tag_functions|get_image|get_margin|get_mark_tags|get_max_boxes|get_max_indent|get_method|get_method_label|get_normalize_ratio|get_normalize_ratio_when_printing|get_print_tags|get_state|get_variable|getcwd|getegid|getegid|getenv|getenv|getenv|geteuid|geteuid|getgid|getgid|getgrgid|getgrgid|getgrnam|getgrnam|getgroups|gethostbyaddr|gethostbyname|gethostname|getitimer|getlogin|getpeername|getpid|getppid|getprotobyname|getprotobynumber|getpwnam|getpwuid|getservbyname|getservbyport|getsockname|getsockopt|getsockopt_float|getsockopt_int|getsockopt_optint|gettimeofday|getuid|global_replace|global_substitute|gmtime|green|grid|group_beginning|group_end|gt_big_int|gt_num|guard|handle_unix_error|hash|hash_param|hd|header_size|i|id|ignore|in_channel_length|in_channel_of_descr|incr|incr_num|index|index_from|inet_addr_any|inet_addr_of_string|infinity|infix_tag|init|init_class|input|input_binary_int|input_byte|input_char|input_line|input_value|int|int16_signed|int16_unsigned|int32|int64|int8_signed|int8_unsigned|int_of_big_int|int_of_char|int_of_float|int_of_num|int_of_string|integer_num|inter|interactive|inv|invalid_arg|is_block|is_empty|is_implicit|is_int|is_int_big_int|is_integer_num|is_relative|iter|iter2|iteri|join|junk|key_pressed|kill|kind|kprintf|kscanf|land|last_chars|layout|lazy_from_fun|lazy_from_val|lazy_is_val|lazy_tag|ldexp|le_big_int|le_num|length|lexeme|lexeme_char|lexeme_end|lexeme_end_p|lexeme_start|lexeme_start_p|lineto|link|list|listen|lnot|loadfile|loadfile_private|localtime|lock|lockf|log|log10|logand|lognot|logor|logxor|lor|lower_window|lowercase|lseek|lsl|lsr|lstat|lt_big_int|lt_num|lxor|magenta|magic|mainLoop|major|major_slice|make|make_formatter|make_image|make_lexer|make_matrix|make_self_init|map|map2|map_file|mapi|marshal|match_beginning|match_end|matched_group|matched_string|max|max_array_length|max_big_int|max_elt|max_float|max_int|max_num|max_string_length|mem|mem_assoc|mem_assq|memq|merge|min|min_big_int|min_elt|min_float|min_int|min_num|minor|minus_big_int|minus_num|minus_one|mkdir|mkfifo|mktime|mod|mod_big_int|mod_float|mod_num|modf|mouse_pos|moveto|mul|mult_big_int|mult_int_big_int|mult_num|nan|narrow|nat_of_num|nativeint|neg|neg_infinity|new_block|new_channel|new_method|new_variable|next|nextkey|nice|nice|no_scan_tag|norm|norm2|not|npeek|nth|nth_dim|num_digits_big_int|num_dims|num_of_big_int|num_of_int|num_of_nat|num_of_ratio|num_of_string|O|obj|object_tag|ocaml_version|of_array|of_channel|of_float|of_int|of_int32|of_list|of_nativeint|of_string|one|openTk|open_box|open_connection|open_graph|open_hbox|open_hovbox|open_hvbox|open_in|open_in_bin|open_in_gen|open_out|open_out_bin|open_out_gen|open_process|open_process_full|open_process_in|open_process_out|open_subwindow|open_tag|open_tbox|open_temp_file|open_vbox|opendbm|opendir|openfile|or|os_type|out_channel_length|out_channel_of_descr|output|output_binary_int|output_buffer|output_byte|output_char|output_string|output_value|over_max_boxes|pack|params|parent_dir_name|parse|parse_argv|partition|pause|peek|pipe|pixels|place|plot|plots|point_color|polar|poll|pop|pos_in|pos_out|pow|power_big_int_positive_big_int|power_big_int_positive_int|power_int_positive_big_int|power_int_positive_int|power_num|pp_close_box|pp_close_tag|pp_close_tbox|pp_force_newline|pp_get_all_formatter_output_functions|pp_get_ellipsis_text|pp_get_formatter_output_functions|pp_get_formatter_tag_functions|pp_get_margin|pp_get_mark_tags|pp_get_max_boxes|pp_get_max_indent|pp_get_print_tags|pp_open_box|pp_open_hbox|pp_open_hovbox|pp_open_hvbox|pp_open_tag|pp_open_tbox|pp_open_vbox|pp_over_max_boxes|pp_print_as|pp_print_bool|pp_print_break|pp_print_char|pp_print_cut|pp_print_float|pp_print_flush|pp_print_if_newline|pp_print_int|pp_print_newline|pp_print_space|pp_print_string|pp_print_tab|pp_print_tbreak|pp_set_all_formatter_output_functions|pp_set_ellipsis_text|pp_set_formatter_out_channel|pp_set_formatter_output_functions|pp_set_formatter_tag_functions|pp_set_margin|pp_set_mark_tags|pp_set_max_boxes|pp_set_max_indent|pp_set_print_tags|pp_set_tab|pp_set_tags|pred|pred_big_int|pred_num|prerr_char|prerr_endline|prerr_float|prerr_int|prerr_newline|prerr_string|print|print_as|print_bool|print_break|print_char|print_cut|print_endline|print_float|print_flush|print_if_newline|print_int|print_newline|print_space|print_stat|print_string|print_tab|print_tbreak|printf|prohibit|public_method_label|push|putenv|quo_num|quomod_big_int|quote|raise|raise_window|ratio_of_num|rcontains_from|read|read_float|read_int|read_key|read_line|readdir|readdir|readlink|really_input|receive|recv|recvfrom|red|ref|regexp|regexp_case_fold|regexp_string|regexp_string_case_fold|register|register_exception|rem|remember_mode|remove|remove_assoc|remove_assq|rename|replace|replace_first|replace_matched|repr|reset|reshape|reshape_1|reshape_2|reshape_3|rev|rev_append|rev_map|rev_map2|rewinddir|rgb|rhs_end|rhs_end_pos|rhs_start|rhs_start_pos|rindex|rindex_from|rlineto|rmdir|rmoveto|round_num|run_initializers|run_initializers_opt|scanf|search_backward|search_forward|seek_in|seek_out|select|self|self_init|send|sendto|set|set_all_formatter_output_functions|set_approx_printing|set_binary_mode_in|set_binary_mode_out|set_close_on_exec|set_close_on_exec|set_color|set_ellipsis_text|set_error_when_null_denominator|set_field|set_floating_precision|set_font|set_formatter_out_channel|set_formatter_output_functions|set_formatter_tag_functions|set_line_width|set_margin|set_mark_tags|set_max_boxes|set_max_indent|set_method|set_nonblock|set_nonblock|set_normalize_ratio|set_normalize_ratio_when_printing|set_print_tags|set_signal|set_state|set_tab|set_tag|set_tags|set_text_size|set_window_title|setgid|setgid|setitimer|setitimer|setsid|setsid|setsockopt|setsockopt|setsockopt_float|setsockopt_float|setsockopt_int|setsockopt_int|setsockopt_optint|setsockopt_optint|setuid|setuid|shift_left|shift_left|shift_left|shift_right|shift_right|shift_right|shift_right_logical|shift_right_logical|shift_right_logical|show_buckets|shutdown|shutdown|shutdown_connection|shutdown_connection|sigabrt|sigalrm|sigchld|sigcont|sigfpe|sighup|sigill|sigint|sigkill|sign_big_int|sign_num|signal|signal|sigpending|sigpending|sigpipe|sigprocmask|sigprocmask|sigprof|sigquit|sigsegv|sigstop|sigsuspend|sigsuspend|sigterm|sigtstp|sigttin|sigttou|sigusr1|sigusr2|sigvtalrm|sin|singleton|sinh|size|size|size_x|size_y|sleep|sleep|sleep|slice_left|slice_left|slice_left_1|slice_left_2|slice_right|slice_right|slice_right_1|slice_right_2|snd|socket|socket|socket|socketpair|socketpair|sort|sound|split|split_delim|sprintf|sprintf|sqrt|sqrt|sqrt_big_int|square_big_int|square_num|sscanf|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|stat|stat|stat|stat|stat|stats|stats|std_formatter|stdbuf|stderr|stderr|stderr|stdib|stdin|stdin|stdin|stdout|stdout|stdout|str_formatter|string|string_after|string_before|string_match|string_of_big_int|string_of_bool|string_of_float|string_of_format|string_of_inet_addr|string_of_inet_addr|string_of_int|string_of_num|string_partial_match|string_tag|sub|sub|sub_big_int|sub_left|sub_num|sub_right|subset|subset|substitute_first|substring|succ|succ|succ|succ|succ_big_int|succ_num|symbol_end|symbol_end_pos|symbol_start|symbol_start_pos|symlink|symlink|sync|synchronize|system|system|system|tag|take|tan|tanh|tcdrain|tcdrain|tcflow|tcflow|tcflush|tcflush|tcgetattr|tcgetattr|tcsendbreak|tcsendbreak|tcsetattr|tcsetattr|temp_file|text_size|time|time|time|timed_read|timed_write|times|times|tl|tl|tl|to_buffer|to_channel|to_float|to_hex|to_int|to_int32|to_list|to_list|to_list|to_nativeint|to_string|to_string|to_string|to_string|to_string|top|top|total_size|transfer|transp|truncate|truncate|truncate|truncate|truncate|truncate|try_lock|umask|umask|uncapitalize|uncapitalize|uncapitalize|union|union|unit_big_int|unlink|unlink|unlock|unmarshal|unsafe_blit|unsafe_fill|unsafe_get|unsafe_get|unsafe_set|unsafe_set|update|uppercase|uppercase|uppercase|uppercase|usage|utimes|utimes|wait|wait|wait|wait|wait_next_event|wait_pid|wait_read|wait_signal|wait_timed_read|wait_timed_write|wait_write|waitpid|white|widen|window_id|word_size|wrap|wrap_abort|write|yellow|yield|zero|zero_big_int|Arg|Arith_status|Array|Array1|Array2|Array3|ArrayLabels|Big_int|Bigarray|Buffer|Callback|CamlinternalOO|Char|Complex|Condition|Dbm|Digest|Dynlink|Event|Filename|Format|Gc|Genarray|Genlex|Graphics|GraphicsX11|Hashtbl|Int32|Int64|LargeFile|Lazy|Lexing|List|ListLabels|Make|Map|Marshal|MoreLabels|Mutex|Nativeint|Num|Obj|Oo|Parsing|Pervasives|Printexc|Printf|Queue|Random|Scanf|Scanning|Set|Sort|Stack|State|StdLabels|Str|Stream|String|StringLabels|Sys|Thread|ThreadUnix|Tk|Unix|UnixLabels|Weak",r=this.createKeywordMapper({"variable.language":"this",keyword:e,"constant.language":t,"support.function":n},"identifier"),i="(?:(?:[1-9]\\d*)|(?:0))",s="(?:0[oO]?[0-7]+)",o="(?:0[xX][\\dA-Fa-f]+)",u="(?:0[bB][01]+)",a="(?:"+i+"|"+s+"|"+o+"|"+u+")",f="(?:[eE][+-]?\\d+)",l="(?:\\.\\d+)",c="(?:\\d+)",h="(?:(?:"+c+"?"+l+")|(?:"+c+"\\.))",p="(?:(?:"+h+"|"+c+")"+f+")",d="(?:"+p+"|"+h+")";this.$rules={start:[{token:"comment",regex:"\\(\\*.*?\\*\\)\\s*?$"},{token:"comment",regex:"\\(\\*.*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"'.'"},{token:"string",regex:'"',next:"qstring"},{token:"constant.numeric",regex:"(?:"+d+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:d},{token:"constant.numeric",regex:a+"\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+\\.|\\-\\.|\\*\\.|\\/\\.|#|;;|\\+|\\-|\\*|\\*\\*\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|<-|="},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\)",next:"start"},{token:"comment",regex:".+"}],qstring:[{token:"string",regex:'"',next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.OcamlHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-perl.js b/common/static/js/vendor/ace/mode-perl.js new file mode 100644 index 0000000000..cd32690919 --- /dev/null +++ b/common/static/js/vendor/ace/mode-perl.js @@ -0,0 +1 @@ +ace.define("ace/mode/perl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/perl_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./perl_highlight_rules").PerlHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.foldingRules=new f};r.inherits(l,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)#/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"#")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[\:]\s*$/);o&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/perl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars",t="ARGV|ENV|INC|SIG",n="getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|getpeername|setpriority|getprotoent|setprotoent|getpriority|endprotoent|getservent|setservent|endservent|sethostent|socketpair|getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|map|die|uc|lc|do",r=this.createKeywordMapper({keyword:e,"constant.language":t,"support.function":n},"identifier");this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0x[0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\.\\.\\.|\\|\\|=|>>=|<<=|<=>|&&=|=>|!~|\\^=|&=|\\|=|\\.=|x=|%=|\\/=|\\*=|\\-=|\\+=|=~|\\*\\*|\\-\\-|\\.\\.|\\|\\||&&|\\+\\+|\\->|!=|==|>=|<=|>>|<<|,|=|\\?\\:|\\^|\\||x|%|\\/|\\*|<|&|\\\\|~|!|>|\\.|\\-|\\+|\\-C|\\-b|\\-S|\\-u|\\-t|\\-p|\\-l|\\-d|\\-f|\\-g|\\-s|\\-z|\\-k|\\-e|\\-O|\\-T|\\-B|\\-M|\\-A|\\-X|\\-W|\\-c|\\-R|\\-o|\\-x|\\-w|\\-r|\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.PerlHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-pgsql.js b/common/static/js/vendor/ace/mode-pgsql.js new file mode 100644 index 0000000000..f49c9705e5 --- /dev/null +++ b/common/static/js/vendor/ace/mode-pgsql.js @@ -0,0 +1 @@ +ace.define("ace/mode/pgsql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/pgsql_highlight_rules","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("../mode/text").Mode,s=e("../tokenizer").Tokenizer,o=e("./pgsql_highlight_rules").PgsqlHighlightRules,u=e("../range").Range,a=function(){this.$tokenizer=new s((new o).getRules())};r.inherits(a,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)--/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var a=new u(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);a.start.row=o,a.end.row=o,a.end.column=l[0].length,t.replace(a,l[1])}}else t.indentRows(n,r,"--")},this.getNextLineIndent=function(e,t,n){return e=="start"||e=="keyword.statementEnd"?"":this.$getIndent(t)}}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/pgsql_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules","ace/mode/perl_highlight_rules","ace/mode/python_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./doc_comment_highlight_rules").DocCommentHighlightRules,o=e("./text_highlight_rules").TextHighlightRules,u=e("./perl_highlight_rules").PerlHighlightRules,a=e("./python_highlight_rules").PythonHighlightRules,f=function(){var e="abort|absolute|abstime|access|aclitem|action|add|admin|after|aggregate|all|also|alter|always|analyse|analyze|and|any|anyarray|anyelement|anyenum|anynonarray|array|as|asc|assertion|assignment|asymmetric|at|attribute|authorization|backward|before|begin|between|bigint|binary|bit|bool|boolean|both|box|bpchar|by|bytea|cache|called|cascade|cascaded|case|cast|catalog|chain|char|character|characteristics|check|checkpoint|cid|cidr|circle|class|close|cluster|coalesce|collate|collation|column|comment|comments|commit|committed|concurrently|configuration|connection|constraint|constraints|content|continue|conversion|copy|cost|create|cross|cstring|csv|current|current_catalog|current_date|current_role|current_schema|current_time|current_timestamp|current_user|cursor|cycle|data|database|date|day|deallocate|dec|decimal|declare|default|defaults|deferrable|deferred|definer|delete|delimiter|delimiters|desc|dictionary|disable|discard|distinct|do|document|domain|double|drop|each|else|enable|encoding|encrypted|end|enum|escape|except|exclude|excluding|exclusive|execute|exists|explain|extension|external|extract|false|family|fdw_handler|fetch|first|float|float4|float8|following|for|force|foreign|forward|freeze|from|full|function|functions|global|grant|granted|greatest|group|gtsvector|handler|having|header|hold|hour|identity|if|ilike|immediate|immutable|implicit|in|including|increment|index|indexes|inet|inherit|inherits|initially|inline|inner|inout|input|insensitive|insert|instead|int|int2|int2vector|int4|int8|integer|internal|intersect|interval|into|invoker|is|isnull|isolation|join|key|label|language|language_handler|large|last|lc_collate|lc_ctype|leading|least|left|level|like|limit|line|listen|load|local|localtime|localtimestamp|location|lock|lseg|macaddr|mapping|match|maxvalue|minute|minvalue|mode|money|month|move|name|names|national|natural|nchar|next|no|none|not|nothing|notify|notnull|nowait|null|nullif|nulls|numeric|object|of|off|offset|oid|oids|oidvector|on|only|opaque|operator|option|options|or|order|out|outer|over|overlaps|overlay|owned|owner|parser|partial|partition|passing|password|path|pg_attribute|pg_auth_members|pg_authid|pg_class|pg_database|pg_node_tree|pg_proc|pg_type|placing|plans|point|polygon|position|preceding|precision|prepare|prepared|preserve|primary|prior|privileges|procedural|procedure|quote|range|read|real|reassign|recheck|record|recursive|ref|refcursor|references|regclass|regconfig|regdictionary|regoper|regoperator|regproc|regprocedure|regtype|reindex|relative|release|reltime|rename|repeatable|replace|replica|reset|restart|restrict|returning|returns|revoke|right|role|rollback|row|rows|rule|savepoint|schema|scroll|search|second|security|select|sequence|sequences|serializable|server|session|session_user|set|setof|share|show|similar|simple|smallint|smgr|some|stable|standalone|start|statement|statistics|stdin|stdout|storage|strict|strip|substring|symmetric|sysid|system|table|tables|tablespace|temp|template|temporary|text|then|tid|time|timestamp|timestamptz|timetz|tinterval|to|trailing|transaction|treat|trigger|trim|true|truncate|trusted|tsquery|tsvector|txid_snapshot|type|unbounded|uncommitted|unencrypted|union|unique|unknown|unlisten|unlogged|until|update|user|using|uuid|vacuum|valid|validate|validator|value|values|varbit|varchar|variadic|varying|verbose|version|view|void|volatile|when|where|whitespace|window|with|without|work|wrapper|write|xid|xml|xmlattributes|xmlconcat|xmlelement|xmlexists|xmlforest|xmlparse|xmlpi|xmlroot|xmlserialize|year|yes|zone",t="RI_FKey_cascade_del|RI_FKey_cascade_upd|RI_FKey_check_ins|RI_FKey_check_upd|RI_FKey_noaction_del|RI_FKey_noaction_upd|RI_FKey_restrict_del|RI_FKey_restrict_upd|RI_FKey_setdefault_del|RI_FKey_setdefault_upd|RI_FKey_setnull_del|RI_FKey_setnull_upd|abbrev|abs|abstime|abstimeeq|abstimege|abstimegt|abstimein|abstimele|abstimelt|abstimene|abstimeout|abstimerecv|abstimesend|aclcontains|aclexplode|aclinsert|aclitemeq|aclitemin|aclitemout|aclremove|acos|age|any_in|any_out|anyarray_in|anyarray_out|anyarray_recv|anyarray_send|anyelement_in|anyelement_out|anyenum_in|anyenum_out|anynonarray_in|anynonarray_out|anytextcat|area|areajoinsel|areasel|array_agg|array_agg_finalfn|array_agg_transfn|array_append|array_cat|array_dims|array_eq|array_fill|array_ge|array_gt|array_in|array_larger|array_le|array_length|array_lower|array_lt|array_ndims|array_ne|array_out|array_prepend|array_recv|array_send|array_smaller|array_to_string|array_upper|arraycontained|arraycontains|arrayoverlap|ascii|ascii_to_mic|ascii_to_utf8|asin|atan|atan2|avg|big5_to_euc_tw|big5_to_mic|big5_to_utf8|bit_and|bit_in|bit_length|bit_or|bit_out|bit_recv|bit_send|bitand|bitcat|bitcmp|biteq|bitge|bitgt|bitle|bitlt|bitne|bitnot|bitor|bitshiftleft|bitshiftright|bittypmodin|bittypmodout|bitxor|bool|bool_and|bool_or|booland_statefunc|booleq|boolge|boolgt|boolin|boolle|boollt|boolne|boolor_statefunc|boolout|boolrecv|boolsend|box|box_above|box_above_eq|box_add|box_below|box_below_eq|box_center|box_contain|box_contain_pt|box_contained|box_distance|box_div|box_eq|box_ge|box_gt|box_in|box_intersect|box_le|box_left|box_lt|box_mul|box_out|box_overabove|box_overbelow|box_overlap|box_overleft|box_overright|box_recv|box_right|box_same|box_send|box_sub|bpchar_larger|bpchar_pattern_ge|bpchar_pattern_gt|bpchar_pattern_le|bpchar_pattern_lt|bpchar_smaller|bpcharcmp|bpchareq|bpcharge|bpchargt|bpchariclike|bpcharicnlike|bpcharicregexeq|bpcharicregexne|bpcharin|bpcharle|bpcharlike|bpcharlt|bpcharne|bpcharnlike|bpcharout|bpcharrecv|bpcharregexeq|bpcharregexne|bpcharsend|bpchartypmodin|bpchartypmodout|broadcast|btabstimecmp|btarraycmp|btbeginscan|btboolcmp|btbpchar_pattern_cmp|btbuild|btbuildempty|btbulkdelete|btcharcmp|btcostestimate|btendscan|btfloat48cmp|btfloat4cmp|btfloat84cmp|btfloat8cmp|btgetbitmap|btgettuple|btinsert|btint24cmp|btint28cmp|btint2cmp|btint42cmp|btint48cmp|btint4cmp|btint82cmp|btint84cmp|btint8cmp|btmarkpos|btnamecmp|btoidcmp|btoidvectorcmp|btoptions|btrecordcmp|btreltimecmp|btrescan|btrestrpos|btrim|bttext_pattern_cmp|bttextcmp|bttidcmp|bttintervalcmp|btvacuumcleanup|byteacat|byteacmp|byteaeq|byteage|byteagt|byteain|byteale|bytealike|bytealt|byteane|byteanlike|byteaout|bytearecv|byteasend|cash_cmp|cash_div_cash|cash_div_flt4|cash_div_flt8|cash_div_int2|cash_div_int4|cash_eq|cash_ge|cash_gt|cash_in|cash_le|cash_lt|cash_mi|cash_mul_flt4|cash_mul_flt8|cash_mul_int2|cash_mul_int4|cash_ne|cash_out|cash_pl|cash_recv|cash_send|cash_words|cashlarger|cashsmaller|cbrt|ceil|ceiling|center|char|char_length|character_length|chareq|charge|chargt|charin|charle|charlt|charne|charout|charrecv|charsend|chr|cideq|cidin|cidout|cidr|cidr_in|cidr_out|cidr_recv|cidr_send|cidrecv|cidsend|circle|circle_above|circle_add_pt|circle_below|circle_center|circle_contain|circle_contain_pt|circle_contained|circle_distance|circle_div_pt|circle_eq|circle_ge|circle_gt|circle_in|circle_le|circle_left|circle_lt|circle_mul_pt|circle_ne|circle_out|circle_overabove|circle_overbelow|circle_overlap|circle_overleft|circle_overright|circle_recv|circle_right|circle_same|circle_send|circle_sub_pt|clock_timestamp|close_lb|close_ls|close_lseg|close_pb|close_pl|close_ps|close_sb|close_sl|col_description|concat|concat_ws|contjoinsel|contsel|convert|convert_from|convert_to|corr|cos|cot|count|covar_pop|covar_samp|cstring_in|cstring_out|cstring_recv|cstring_send|cume_dist|current_database|current_query|current_schema|current_schemas|current_setting|current_user|currtid|currtid2|currval|cursor_to_xml|cursor_to_xmlschema|database_to_xml|database_to_xml_and_xmlschema|database_to_xmlschema|date|date_cmp|date_cmp_timestamp|date_cmp_timestamptz|date_eq|date_eq_timestamp|date_eq_timestamptz|date_ge|date_ge_timestamp|date_ge_timestamptz|date_gt|date_gt_timestamp|date_gt_timestamptz|date_in|date_larger|date_le|date_le_timestamp|date_le_timestamptz|date_lt|date_lt_timestamp|date_lt_timestamptz|date_mi|date_mi_interval|date_mii|date_ne|date_ne_timestamp|date_ne_timestamptz|date_out|date_part|date_pl_interval|date_pli|date_recv|date_send|date_smaller|date_trunc|datetime_pl|datetimetz_pl|dcbrt|decode|degrees|dense_rank|dexp|diagonal|diameter|dispell_init|dispell_lexize|dist_cpoly|dist_lb|dist_pb|dist_pc|dist_pl|dist_ppath|dist_ps|dist_sb|dist_sl|div|dlog1|dlog10|domain_in|domain_recv|dpow|dround|dsimple_init|dsimple_lexize|dsnowball_init|dsnowball_lexize|dsqrt|dsynonym_init|dsynonym_lexize|dtrunc|encode|enum_cmp|enum_eq|enum_first|enum_ge|enum_gt|enum_in|enum_larger|enum_last|enum_le|enum_lt|enum_ne|enum_out|enum_range|enum_recv|enum_send|enum_smaller|eqjoinsel|eqsel|euc_cn_to_mic|euc_cn_to_utf8|euc_jis_2004_to_shift_jis_2004|euc_jis_2004_to_utf8|euc_jp_to_mic|euc_jp_to_sjis|euc_jp_to_utf8|euc_kr_to_mic|euc_kr_to_utf8|euc_tw_to_big5|euc_tw_to_mic|euc_tw_to_utf8|every|exp|factorial|family|fdw_handler_in|fdw_handler_out|first_value|float4|float48div|float48eq|float48ge|float48gt|float48le|float48lt|float48mi|float48mul|float48ne|float48pl|float4_accum|float4abs|float4div|float4eq|float4ge|float4gt|float4in|float4larger|float4le|float4lt|float4mi|float4mul|float4ne|float4out|float4pl|float4recv|float4send|float4smaller|float4um|float4up|float8|float84div|float84eq|float84ge|float84gt|float84le|float84lt|float84mi|float84mul|float84ne|float84pl|float8_accum|float8_avg|float8_corr|float8_covar_pop|float8_covar_samp|float8_regr_accum|float8_regr_avgx|float8_regr_avgy|float8_regr_intercept|float8_regr_r2|float8_regr_slope|float8_regr_sxx|float8_regr_sxy|float8_regr_syy|float8_stddev_pop|float8_stddev_samp|float8_var_pop|float8_var_samp|float8abs|float8div|float8eq|float8ge|float8gt|float8in|float8larger|float8le|float8lt|float8mi|float8mul|float8ne|float8out|float8pl|float8recv|float8send|float8smaller|float8um|float8up|floor|flt4_mul_cash|flt8_mul_cash|fmgr_c_validator|fmgr_internal_validator|fmgr_sql_validator|format|format_type|gb18030_to_utf8|gbk_to_utf8|generate_series|generate_subscripts|get_bit|get_byte|get_current_ts_config|getdatabaseencoding|getpgusername|gin_cmp_prefix|gin_cmp_tslexeme|gin_extract_tsquery|gin_extract_tsvector|gin_tsquery_consistent|ginarrayconsistent|ginarrayextract|ginbeginscan|ginbuild|ginbuildempty|ginbulkdelete|gincostestimate|ginendscan|gingetbitmap|gininsert|ginmarkpos|ginoptions|ginqueryarrayextract|ginrescan|ginrestrpos|ginvacuumcleanup|gist_box_compress|gist_box_consistent|gist_box_decompress|gist_box_penalty|gist_box_picksplit|gist_box_same|gist_box_union|gist_circle_compress|gist_circle_consistent|gist_point_compress|gist_point_consistent|gist_point_distance|gist_poly_compress|gist_poly_consistent|gistbeginscan|gistbuild|gistbuildempty|gistbulkdelete|gistcostestimate|gistendscan|gistgetbitmap|gistgettuple|gistinsert|gistmarkpos|gistoptions|gistrescan|gistrestrpos|gistvacuumcleanup|gtsquery_compress|gtsquery_consistent|gtsquery_decompress|gtsquery_penalty|gtsquery_picksplit|gtsquery_same|gtsquery_union|gtsvector_compress|gtsvector_consistent|gtsvector_decompress|gtsvector_penalty|gtsvector_picksplit|gtsvector_same|gtsvector_union|gtsvectorin|gtsvectorout|has_any_column_privilege|has_column_privilege|has_database_privilege|has_foreign_data_wrapper_privilege|has_function_privilege|has_language_privilege|has_schema_privilege|has_sequence_privilege|has_server_privilege|has_table_privilege|has_tablespace_privilege|hash_aclitem|hash_array|hash_numeric|hashbeginscan|hashbpchar|hashbuild|hashbuildempty|hashbulkdelete|hashchar|hashcostestimate|hashendscan|hashenum|hashfloat4|hashfloat8|hashgetbitmap|hashgettuple|hashinet|hashinsert|hashint2|hashint2vector|hashint4|hashint8|hashmacaddr|hashmarkpos|hashname|hashoid|hashoidvector|hashoptions|hashrescan|hashrestrpos|hashtext|hashvacuumcleanup|hashvarlena|height|host|hostmask|iclikejoinsel|iclikesel|icnlikejoinsel|icnlikesel|icregexeqjoinsel|icregexeqsel|icregexnejoinsel|icregexnesel|inet_client_addr|inet_client_port|inet_in|inet_out|inet_recv|inet_send|inet_server_addr|inet_server_port|inetand|inetmi|inetmi_int8|inetnot|inetor|inetpl|initcap|int2|int24div|int24eq|int24ge|int24gt|int24le|int24lt|int24mi|int24mul|int24ne|int24pl|int28div|int28eq|int28ge|int28gt|int28le|int28lt|int28mi|int28mul|int28ne|int28pl|int2_accum|int2_avg_accum|int2_mul_cash|int2_sum|int2abs|int2and|int2div|int2eq|int2ge|int2gt|int2in|int2larger|int2le|int2lt|int2mi|int2mod|int2mul|int2ne|int2not|int2or|int2out|int2pl|int2recv|int2send|int2shl|int2shr|int2smaller|int2um|int2up|int2vectoreq|int2vectorin|int2vectorout|int2vectorrecv|int2vectorsend|int2xor|int4|int42div|int42eq|int42ge|int42gt|int42le|int42lt|int42mi|int42mul|int42ne|int42pl|int48div|int48eq|int48ge|int48gt|int48le|int48lt|int48mi|int48mul|int48ne|int48pl|int4_accum|int4_avg_accum|int4_mul_cash|int4_sum|int4abs|int4and|int4div|int4eq|int4ge|int4gt|int4in|int4inc|int4larger|int4le|int4lt|int4mi|int4mod|int4mul|int4ne|int4not|int4or|int4out|int4pl|int4recv|int4send|int4shl|int4shr|int4smaller|int4um|int4up|int4xor|int8|int82div|int82eq|int82ge|int82gt|int82le|int82lt|int82mi|int82mul|int82ne|int82pl|int84div|int84eq|int84ge|int84gt|int84le|int84lt|int84mi|int84mul|int84ne|int84pl|int8_accum|int8_avg|int8_avg_accum|int8_sum|int8abs|int8and|int8div|int8eq|int8ge|int8gt|int8in|int8inc|int8inc_any|int8inc_float8_float8|int8larger|int8le|int8lt|int8mi|int8mod|int8mul|int8ne|int8not|int8or|int8out|int8pl|int8pl_inet|int8recv|int8send|int8shl|int8shr|int8smaller|int8um|int8up|int8xor|integer_pl_date|inter_lb|inter_sb|inter_sl|internal_in|internal_out|interval_accum|interval_avg|interval_cmp|interval_div|interval_eq|interval_ge|interval_gt|interval_hash|interval_in|interval_larger|interval_le|interval_lt|interval_mi|interval_mul|interval_ne|interval_out|interval_pl|interval_pl_date|interval_pl_time|interval_pl_timestamp|interval_pl_timestamptz|interval_pl_timetz|interval_recv|interval_send|interval_smaller|interval_um|intervaltypmodin|intervaltypmodout|intinterval|isclosed|isfinite|ishorizontal|iso8859_1_to_utf8|iso8859_to_utf8|iso_to_koi8r|iso_to_mic|iso_to_win1251|iso_to_win866|isopen|isparallel|isperp|isvertical|johab_to_utf8|justify_days|justify_hours|justify_interval|koi8r_to_iso|koi8r_to_mic|koi8r_to_utf8|koi8r_to_win1251|koi8r_to_win866|koi8u_to_utf8|lag|language_handler_in|language_handler_out|last_value|lastval|latin1_to_mic|latin2_to_mic|latin2_to_win1250|latin3_to_mic|latin4_to_mic|lead|left|length|like|like_escape|likejoinsel|likesel|line|line_distance|line_eq|line_horizontal|line_in|line_interpt|line_intersect|line_out|line_parallel|line_perp|line_recv|line_send|line_vertical|ln|lo_close|lo_creat|lo_create|lo_export|lo_import|lo_lseek|lo_open|lo_tell|lo_truncate|lo_unlink|log|loread|lower|lowrite|lpad|lseg|lseg_center|lseg_distance|lseg_eq|lseg_ge|lseg_gt|lseg_horizontal|lseg_in|lseg_interpt|lseg_intersect|lseg_le|lseg_length|lseg_lt|lseg_ne|lseg_out|lseg_parallel|lseg_perp|lseg_recv|lseg_send|lseg_vertical|ltrim|macaddr_cmp|macaddr_eq|macaddr_ge|macaddr_gt|macaddr_in|macaddr_le|macaddr_lt|macaddr_ne|macaddr_out|macaddr_recv|macaddr_send|makeaclitem|masklen|max|md5|mic_to_ascii|mic_to_big5|mic_to_euc_cn|mic_to_euc_jp|mic_to_euc_kr|mic_to_euc_tw|mic_to_iso|mic_to_koi8r|mic_to_latin1|mic_to_latin2|mic_to_latin3|mic_to_latin4|mic_to_sjis|mic_to_win1250|mic_to_win1251|mic_to_win866|min|mktinterval|mod|money|mul_d_interval|name|nameeq|namege|namegt|nameiclike|nameicnlike|nameicregexeq|nameicregexne|namein|namele|namelike|namelt|namene|namenlike|nameout|namerecv|nameregexeq|nameregexne|namesend|neqjoinsel|neqsel|netmask|network|network_cmp|network_eq|network_ge|network_gt|network_le|network_lt|network_ne|network_sub|network_subeq|network_sup|network_supeq|nextval|nlikejoinsel|nlikesel|notlike|now|npoints|nth_value|ntile|numeric_abs|numeric_accum|numeric_add|numeric_avg|numeric_avg_accum|numeric_cmp|numeric_div|numeric_div_trunc|numeric_eq|numeric_exp|numeric_fac|numeric_ge|numeric_gt|numeric_in|numeric_inc|numeric_larger|numeric_le|numeric_ln|numeric_log|numeric_lt|numeric_mod|numeric_mul|numeric_ne|numeric_out|numeric_power|numeric_recv|numeric_send|numeric_smaller|numeric_sqrt|numeric_stddev_pop|numeric_stddev_samp|numeric_sub|numeric_uminus|numeric_uplus|numeric_var_pop|numeric_var_samp|numerictypmodin|numerictypmodout|numnode|obj_description|octet_length|oid|oideq|oidge|oidgt|oidin|oidlarger|oidle|oidlt|oidne|oidout|oidrecv|oidsend|oidsmaller|oidvectoreq|oidvectorge|oidvectorgt|oidvectorin|oidvectorle|oidvectorlt|oidvectorne|oidvectorout|oidvectorrecv|oidvectorsend|oidvectortypes|on_pb|on_pl|on_ppath|on_ps|on_sb|on_sl|opaque_in|opaque_out|overlaps|overlay|path|path_add|path_add_pt|path_center|path_contain_pt|path_distance|path_div_pt|path_in|path_inter|path_length|path_mul_pt|path_n_eq|path_n_ge|path_n_gt|path_n_le|path_n_lt|path_npoints|path_out|path_recv|path_send|path_sub_pt|pclose|percent_rank|pg_advisory_lock|pg_advisory_lock_shared|pg_advisory_unlock|pg_advisory_unlock_all|pg_advisory_unlock_shared|pg_advisory_xact_lock|pg_advisory_xact_lock_shared|pg_available_extension_versions|pg_available_extensions|pg_backend_pid|pg_cancel_backend|pg_char_to_encoding|pg_client_encoding|pg_collation_is_visible|pg_column_size|pg_conf_load_time|pg_conversion_is_visible|pg_create_restore_point|pg_current_xlog_insert_location|pg_current_xlog_location|pg_cursor|pg_database_size|pg_describe_object|pg_encoding_max_length|pg_encoding_to_char|pg_extension_config_dump|pg_extension_update_paths|pg_function_is_visible|pg_get_constraintdef|pg_get_expr|pg_get_function_arguments|pg_get_function_identity_arguments|pg_get_function_result|pg_get_functiondef|pg_get_indexdef|pg_get_keywords|pg_get_ruledef|pg_get_serial_sequence|pg_get_triggerdef|pg_get_userbyid|pg_get_viewdef|pg_has_role|pg_indexes_size|pg_is_in_recovery|pg_is_other_temp_schema|pg_is_xlog_replay_paused|pg_last_xact_replay_timestamp|pg_last_xlog_receive_location|pg_last_xlog_replay_location|pg_listening_channels|pg_lock_status|pg_ls_dir|pg_my_temp_schema|pg_node_tree_in|pg_node_tree_out|pg_node_tree_recv|pg_node_tree_send|pg_notify|pg_opclass_is_visible|pg_operator_is_visible|pg_options_to_table|pg_postmaster_start_time|pg_prepared_statement|pg_prepared_xact|pg_read_binary_file|pg_read_file|pg_relation_filenode|pg_relation_filepath|pg_relation_size|pg_reload_conf|pg_rotate_logfile|pg_sequence_parameters|pg_show_all_settings|pg_size_pretty|pg_sleep|pg_start_backup|pg_stat_clear_snapshot|pg_stat_file|pg_stat_get_activity|pg_stat_get_analyze_count|pg_stat_get_autoanalyze_count|pg_stat_get_autovacuum_count|pg_stat_get_backend_activity|pg_stat_get_backend_activity_start|pg_stat_get_backend_client_addr|pg_stat_get_backend_client_port|pg_stat_get_backend_dbid|pg_stat_get_backend_idset|pg_stat_get_backend_pid|pg_stat_get_backend_start|pg_stat_get_backend_userid|pg_stat_get_backend_waiting|pg_stat_get_backend_xact_start|pg_stat_get_bgwriter_buf_written_checkpoints|pg_stat_get_bgwriter_buf_written_clean|pg_stat_get_bgwriter_maxwritten_clean|pg_stat_get_bgwriter_requested_checkpoints|pg_stat_get_bgwriter_stat_reset_time|pg_stat_get_bgwriter_timed_checkpoints|pg_stat_get_blocks_fetched|pg_stat_get_blocks_hit|pg_stat_get_buf_alloc|pg_stat_get_buf_fsync_backend|pg_stat_get_buf_written_backend|pg_stat_get_db_blocks_fetched|pg_stat_get_db_blocks_hit|pg_stat_get_db_conflict_all|pg_stat_get_db_conflict_bufferpin|pg_stat_get_db_conflict_lock|pg_stat_get_db_conflict_snapshot|pg_stat_get_db_conflict_startup_deadlock|pg_stat_get_db_conflict_tablespace|pg_stat_get_db_numbackends|pg_stat_get_db_stat_reset_time|pg_stat_get_db_tuples_deleted|pg_stat_get_db_tuples_fetched|pg_stat_get_db_tuples_inserted|pg_stat_get_db_tuples_returned|pg_stat_get_db_tuples_updated|pg_stat_get_db_xact_commit|pg_stat_get_db_xact_rollback|pg_stat_get_dead_tuples|pg_stat_get_function_calls|pg_stat_get_function_self_time|pg_stat_get_function_time|pg_stat_get_last_analyze_time|pg_stat_get_last_autoanalyze_time|pg_stat_get_last_autovacuum_time|pg_stat_get_last_vacuum_time|pg_stat_get_live_tuples|pg_stat_get_numscans|pg_stat_get_tuples_deleted|pg_stat_get_tuples_fetched|pg_stat_get_tuples_hot_updated|pg_stat_get_tuples_inserted|pg_stat_get_tuples_returned|pg_stat_get_tuples_updated|pg_stat_get_vacuum_count|pg_stat_get_wal_senders|pg_stat_get_xact_blocks_fetched|pg_stat_get_xact_blocks_hit|pg_stat_get_xact_function_calls|pg_stat_get_xact_function_self_time|pg_stat_get_xact_function_time|pg_stat_get_xact_numscans|pg_stat_get_xact_tuples_deleted|pg_stat_get_xact_tuples_fetched|pg_stat_get_xact_tuples_hot_updated|pg_stat_get_xact_tuples_inserted|pg_stat_get_xact_tuples_returned|pg_stat_get_xact_tuples_updated|pg_stat_reset|pg_stat_reset_shared|pg_stat_reset_single_function_counters|pg_stat_reset_single_table_counters|pg_stop_backup|pg_switch_xlog|pg_table_is_visible|pg_table_size|pg_tablespace_databases|pg_tablespace_size|pg_terminate_backend|pg_timezone_abbrevs|pg_timezone_names|pg_total_relation_size|pg_try_advisory_lock|pg_try_advisory_lock_shared|pg_try_advisory_xact_lock|pg_try_advisory_xact_lock_shared|pg_ts_config_is_visible|pg_ts_dict_is_visible|pg_ts_parser_is_visible|pg_ts_template_is_visible|pg_type_is_visible|pg_typeof|pg_xlog_replay_pause|pg_xlog_replay_resume|pg_xlogfile_name|pg_xlogfile_name_offset|pi|plainto_tsquery|plpgsql_call_handler|plpgsql_inline_handler|plpgsql_validator|point|point_above|point_add|point_below|point_distance|point_div|point_eq|point_horiz|point_in|point_left|point_mul|point_ne|point_out|point_recv|point_right|point_send|point_sub|point_vert|poly_above|poly_below|poly_center|poly_contain|poly_contain_pt|poly_contained|poly_distance|poly_in|poly_left|poly_npoints|poly_out|poly_overabove|poly_overbelow|poly_overlap|poly_overleft|poly_overright|poly_recv|poly_right|poly_same|poly_send|polygon|popen|position|positionjoinsel|positionsel|postgresql_fdw_validator|pow|power|prsd_end|prsd_headline|prsd_lextype|prsd_nexttoken|prsd_start|pt_contained_circle|pt_contained_poly|query_to_xml|query_to_xml_and_xmlschema|query_to_xmlschema|querytree|quote_ident|quote_literal|quote_nullable|radians|radius|random|rank|record_eq|record_ge|record_gt|record_in|record_le|record_lt|record_ne|record_out|record_recv|record_send|regclass|regclassin|regclassout|regclassrecv|regclasssend|regconfigin|regconfigout|regconfigrecv|regconfigsend|regdictionaryin|regdictionaryout|regdictionaryrecv|regdictionarysend|regexeqjoinsel|regexeqsel|regexnejoinsel|regexnesel|regexp_matches|regexp_replace|regexp_split_to_array|regexp_split_to_table|regoperatorin|regoperatorout|regoperatorrecv|regoperatorsend|regoperin|regoperout|regoperrecv|regopersend|regprocedurein|regprocedureout|regprocedurerecv|regproceduresend|regprocin|regprocout|regprocrecv|regprocsend|regr_avgx|regr_avgy|regr_count|regr_intercept|regr_r2|regr_slope|regr_sxx|regr_sxy|regr_syy|regtypein|regtypeout|regtyperecv|regtypesend|reltime|reltimeeq|reltimege|reltimegt|reltimein|reltimele|reltimelt|reltimene|reltimeout|reltimerecv|reltimesend|repeat|replace|reverse|right|round|row_number|rpad|rtrim|scalargtjoinsel|scalargtsel|scalarltjoinsel|scalarltsel|schema_to_xml|schema_to_xml_and_xmlschema|schema_to_xmlschema|session_user|set_bit|set_byte|set_config|set_masklen|setseed|setval|setweight|shell_in|shell_out|shift_jis_2004_to_euc_jis_2004|shift_jis_2004_to_utf8|shobj_description|sign|similar_escape|sin|sjis_to_euc_jp|sjis_to_mic|sjis_to_utf8|slope|smgreq|smgrin|smgrne|smgrout|split_part|sqrt|statement_timestamp|stddev|stddev_pop|stddev_samp|string_agg|string_agg_finalfn|string_agg_transfn|string_to_array|strip|strpos|substr|substring|sum|suppress_redundant_updates_trigger|table_to_xml|table_to_xml_and_xmlschema|table_to_xmlschema|tan|text|text_ge|text_gt|text_larger|text_le|text_lt|text_pattern_ge|text_pattern_gt|text_pattern_le|text_pattern_lt|text_smaller|textanycat|textcat|texteq|texticlike|texticnlike|texticregexeq|texticregexne|textin|textlen|textlike|textne|textnlike|textout|textrecv|textregexeq|textregexne|textsend|thesaurus_init|thesaurus_lexize|tideq|tidge|tidgt|tidin|tidlarger|tidle|tidlt|tidne|tidout|tidrecv|tidsend|tidsmaller|time_cmp|time_eq|time_ge|time_gt|time_hash|time_in|time_larger|time_le|time_lt|time_mi_interval|time_mi_time|time_ne|time_out|time_pl_interval|time_recv|time_send|time_smaller|timedate_pl|timemi|timenow|timeofday|timepl|timestamp_cmp|timestamp_cmp_date|timestamp_cmp_timestamptz|timestamp_eq|timestamp_eq_date|timestamp_eq_timestamptz|timestamp_ge|timestamp_ge_date|timestamp_ge_timestamptz|timestamp_gt|timestamp_gt_date|timestamp_gt_timestamptz|timestamp_hash|timestamp_in|timestamp_larger|timestamp_le|timestamp_le_date|timestamp_le_timestamptz|timestamp_lt|timestamp_lt_date|timestamp_lt_timestamptz|timestamp_mi|timestamp_mi_interval|timestamp_ne|timestamp_ne_date|timestamp_ne_timestamptz|timestamp_out|timestamp_pl_interval|timestamp_recv|timestamp_send|timestamp_smaller|timestamptypmodin|timestamptypmodout|timestamptz_cmp|timestamptz_cmp_date|timestamptz_cmp_timestamp|timestamptz_eq|timestamptz_eq_date|timestamptz_eq_timestamp|timestamptz_ge|timestamptz_ge_date|timestamptz_ge_timestamp|timestamptz_gt|timestamptz_gt_date|timestamptz_gt_timestamp|timestamptz_in|timestamptz_larger|timestamptz_le|timestamptz_le_date|timestamptz_le_timestamp|timestamptz_lt|timestamptz_lt_date|timestamptz_lt_timestamp|timestamptz_mi|timestamptz_mi_interval|timestamptz_ne|timestamptz_ne_date|timestamptz_ne_timestamp|timestamptz_out|timestamptz_pl_interval|timestamptz_recv|timestamptz_send|timestamptz_smaller|timestamptztypmodin|timestamptztypmodout|timetypmodin|timetypmodout|timetz_cmp|timetz_eq|timetz_ge|timetz_gt|timetz_hash|timetz_in|timetz_larger|timetz_le|timetz_lt|timetz_mi_interval|timetz_ne|timetz_out|timetz_pl_interval|timetz_recv|timetz_send|timetz_smaller|timetzdate_pl|timetztypmodin|timetztypmodout|timezone|tinterval|tintervalct|tintervalend|tintervaleq|tintervalge|tintervalgt|tintervalin|tintervalle|tintervalleneq|tintervallenge|tintervallengt|tintervallenle|tintervallenlt|tintervallenne|tintervallt|tintervalne|tintervalout|tintervalov|tintervalrecv|tintervalrel|tintervalsame|tintervalsend|tintervalstart|to_ascii|to_char|to_date|to_hex|to_number|to_timestamp|to_tsquery|to_tsvector|transaction_timestamp|translate|trigger_in|trigger_out|trunc|ts_debug|ts_headline|ts_lexize|ts_match_qv|ts_match_tq|ts_match_tt|ts_match_vq|ts_parse|ts_rank|ts_rank_cd|ts_rewrite|ts_stat|ts_token_type|ts_typanalyze|tsmatchjoinsel|tsmatchsel|tsq_mcontained|tsq_mcontains|tsquery_and|tsquery_cmp|tsquery_eq|tsquery_ge|tsquery_gt|tsquery_le|tsquery_lt|tsquery_ne|tsquery_not|tsquery_or|tsqueryin|tsqueryout|tsqueryrecv|tsquerysend|tsvector_cmp|tsvector_concat|tsvector_eq|tsvector_ge|tsvector_gt|tsvector_le|tsvector_lt|tsvector_ne|tsvector_update_trigger|tsvector_update_trigger_column|tsvectorin|tsvectorout|tsvectorrecv|tsvectorsend|txid_current|txid_current_snapshot|txid_snapshot_in|txid_snapshot_out|txid_snapshot_recv|txid_snapshot_send|txid_snapshot_xip|txid_snapshot_xmax|txid_snapshot_xmin|txid_visible_in_snapshot|uhc_to_utf8|unique_key_recheck|unknownin|unknownout|unknownrecv|unknownsend|unnest|upper|utf8_to_ascii|utf8_to_big5|utf8_to_euc_cn|utf8_to_euc_jis_2004|utf8_to_euc_jp|utf8_to_euc_kr|utf8_to_euc_tw|utf8_to_gb18030|utf8_to_gbk|utf8_to_iso8859|utf8_to_iso8859_1|utf8_to_johab|utf8_to_koi8r|utf8_to_koi8u|utf8_to_shift_jis_2004|utf8_to_sjis|utf8_to_uhc|utf8_to_win|uuid_cmp|uuid_eq|uuid_ge|uuid_gt|uuid_hash|uuid_in|uuid_le|uuid_lt|uuid_ne|uuid_out|uuid_recv|uuid_send|var_pop|var_samp|varbit_in|varbit_out|varbit_recv|varbit_send|varbitcmp|varbiteq|varbitge|varbitgt|varbitle|varbitlt|varbitne|varbittypmodin|varbittypmodout|varcharin|varcharout|varcharrecv|varcharsend|varchartypmodin|varchartypmodout|variance|version|void_in|void_out|void_recv|void_send|width|width_bucket|win1250_to_latin2|win1250_to_mic|win1251_to_iso|win1251_to_koi8r|win1251_to_mic|win1251_to_win866|win866_to_iso|win866_to_koi8r|win866_to_mic|win866_to_win1251|win_to_utf8|xideq|xideqint4|xidin|xidout|xidrecv|xidsend|xml|xml_in|xml_is_well_formed|xml_is_well_formed_content|xml_is_well_formed_document|xml_out|xml_recv|xml_send|xmlagg|xmlcomment|xmlconcat2|xmlexists|xmlvalidate|xpath|xpath_exists",n=this.createKeywordMapper({"support.function":t,keyword:e},"identifier",!0),r=[{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"variable.language",regex:'".*?"'},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:n,regex:"[a-zA-Z_][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|!!|!~|!~\\*|!~~|!~~\\*|#|##|#<|#<=|#<>|#=|#>|#>=|%|\\&|\\&\\&|\\&<|\\&<\\||\\&>|\\*|\\+|\\-|/|<|<#>|<\\->|<<|<<=|<<\\||<=|<>|<\\?>|<@|<\\^|=|>|>=|>>|>>=|>\\^|\\?#|\\?\\-|\\?\\-\\||\\?\\||\\?\\|\\||@|@\\-@|@>|@@|@@@|\\^|\\||\\|\\&>|\\|/|\\|>>|\\|\\||\\|\\|/|~|~\\*|~<=~|~<~|~=|~>=~|~>~|~~|~~\\*"},{token:"paren.lparen",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"text",regex:"\\s+"}];this.$rules={start:[{token:"comment",regex:"--.*$"},s.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"keyword.statementBegin",regex:"^[a-zA-Z]+",next:"statement"},{token:"support.buildin",regex:"^\\\\[\\S]+.*$"}],statement:[{token:"comment",regex:"--.*$"},{token:"comment",regex:"\\/\\*",next:"commentStatement"},{token:"statementEnd",regex:";",next:"start"},{token:"string",regex:"\\$perl\\$",next:"perl-start"},{token:"string",regex:"\\$python\\$",next:"python-start"},{token:"string",regex:"\\$[\\w_0-9]*\\$$",next:"dollarSql"},{token:"string",regex:"\\$[\\w_0-9]*\\$",next:"dollarStatementString"}].concat(r),dollarSql:[{token:"comment",regex:"--.*$"},{token:"comment",regex:"\\/\\*",next:"commentDollarSql"},{token:"string",regex:"^\\$[\\w_0-9]*\\$",next:"statement"},{token:"string",regex:"\\$[\\w_0-9]*\\$",next:"dollarSqlString"}].concat(r),comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],commentStatement:[{token:"comment",regex:".*?\\*\\/",next:"statement"},{token:"comment",regex:".+"}],commentDollarSql:[{token:"comment",regex:".*?\\*\\/",next:"dollarSql"},{token:"comment",regex:".+"}],dollarStatementString:[{token:"string",regex:".*?\\$[\\w_0-9]*\\$",next:"statement"},{token:"string",regex:".+"}],dollarSqlString:[{token:"string",regex:".*?\\$[\\w_0-9]*\\$",next:"dollarSql"},{token:"string",regex:".+"}]},this.embedRules(s,"doc-",[s.getEndRule("start")]),this.embedRules(u,"perl-",[{token:"string",regex:"\\$perl\\$",next:"statement"}]),this.embedRules(a,"python-",[{token:"string",regex:"\\$python\\$",next:"statement"}])};r.inherits(f,o),t.PgsqlHighlightRules=f}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/perl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars",t="ARGV|ENV|INC|SIG",n="getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|getpeername|setpriority|getprotoent|setprotoent|getpriority|endprotoent|getservent|setservent|endservent|sethostent|socketpair|getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|map|die|uc|lc|do",r=this.createKeywordMapper({keyword:e,"constant.language":t,"support.function":n},"identifier");this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0x[0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\.\\.\\.|\\|\\|=|>>=|<<=|<=>|&&=|=>|!~|\\^=|&=|\\|=|\\.=|x=|%=|\\/=|\\*=|\\-=|\\+=|=~|\\*\\*|\\-\\-|\\.\\.|\\|\\||&&|\\+\\+|\\->|!=|==|>=|<=|>>|<<|,|=|\\?\\:|\\^|\\||x|%|\\/|\\*|<|&|\\\\|~|!|>|\\.|\\-|\\+|\\-C|\\-b|\\-S|\\-u|\\-t|\\-p|\\-l|\\-d|\\-f|\\-g|\\-s|\\-z|\\-k|\\-e|\\-O|\\-T|\\-B|\\-M|\\-A|\\-X|\\-W|\\-c|\\-R|\\-o|\\-x|\\-w|\\-r|\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.PerlHighlightRules=s}),ace.define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield",t="True|False|None|NotImplemented|Ellipsis|__debug__",n="abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern",r=this.createKeywordMapper({"invalid.deprecated":"debugger","support.function":n,"constant.language":t,keyword:e},"identifier"),i="(?:r|u|ur|R|U|UR|Ur|uR)?",s="(?:(?:[1-9]\\d*)|(?:0))",o="(?:0[oO]?[0-7]+)",u="(?:0[xX][\\dA-Fa-f]+)",a="(?:0[bB][01]+)",f="(?:"+s+"|"+o+"|"+u+"|"+a+")",l="(?:[eE][+-]?\\d+)",c="(?:\\.\\d+)",h="(?:\\d+)",p="(?:(?:"+h+"?"+c+")|(?:"+h+"\\.))",d="(?:(?:"+p+"|"+h+")"+l+")",v="(?:"+d+"|"+p+")";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:i+'"{3}(?:[^\\\\]|\\\\.)*?"{3}'},{token:"string",regex:i+'"{3}.*$',next:"qqstring"},{token:"string",regex:i+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:i+"'{3}(?:[^\\\\]|\\\\.)*?'{3}"},{token:"string",regex:i+"'{3}.*$",next:"qstring"},{token:"string",regex:i+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:"(?:"+v+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:v},{token:"constant.numeric",regex:f+"[lL]\\b"},{token:"constant.numeric",regex:f+"\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?"{3}',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?'{3}",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.PythonHighlightRules=s}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-php.js b/common/static/js/vendor/ace/mode-php.js new file mode 100644 index 0000000000..0dac744b58 --- /dev/null +++ b/common/static/js/vendor/ace/mode-php.js @@ -0,0 +1 @@ +ace.define("ace/mode/php",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/php_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/unicode"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./php_highlight_rules").PhpHighlightRules,u=e("./php_highlight_rules").PhpLangHighlightRules,a=e("./matching_brace_outdent").MatchingBraceOutdent,f=e("../range").Range,l=e("../worker/worker_client").WorkerClient,c=e("./behaviour/cstyle").CstyleBehaviour,h=e("./folding/cstyle").FoldMode,p=e("../unicode"),d=function(e){var t=e&&e.inline,n=t?u:o;this.$tokenizer=new s((new n).getRules()),this.$outdent=new a,this.$behaviour=new c,this.foldingRules=new h};r.inherits(d,i),function(){this.tokenRe=new RegExp("^["+p.packages.L+p.packages.Mn+p.packages.Mc+p.packages.Nd+p.packages.Pc+"_]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+p.packages.L+p.packages.Mn+p.packages.Mc+p.packages.Nd+p.packages.Pc+"_]|s])+","g"),this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)#/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new f(0,0,0,0);for(var o=n;o<=r;o++){var a=t.getLine(o),l=a.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"#")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="php-start"){var u=t.match(/^.*[\{\(\[\:]\s*$/);u&&(r+=n)}else if(e=="php-doc-start"){if(o!="php-doc-start")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new l(["ace"],"ace/mode/php_worker","PhpWorker");return t.attachToDocument(e.getDocument()),t.on("error",function(t){e.setAnnotations(t.data)}),t.on("ok",function(){e.clearAnnotations()}),t}}.call(d.prototype),t.Mode=d}),ace.define("ace/mode/php_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules","ace/mode/html_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./doc_comment_highlight_rules").DocCommentHighlightRules,o=e("./text_highlight_rules").TextHighlightRules,u=e("./html_highlight_rules").HtmlHighlightRules,a=function(){var e=s,t=i.arrayToMap("abs|acos|acosh|addcslashes|addslashes|aggregate|aggregate_info|aggregate_methods|aggregate_methods_by_list|aggregate_methods_by_regexp|aggregate_properties|aggregate_properties_by_list|aggregate_properties_by_regexp|aggregation_info|amqpconnection|amqpexchange|amqpqueue|apache_child_terminate|apache_get_modules|apache_get_version|apache_getenv|apache_lookup_uri|apache_note|apache_request_headers|apache_reset_timeout|apache_response_headers|apache_setenv|apc_add|apc_bin_dump|apc_bin_dumpfile|apc_bin_load|apc_bin_loadfile|apc_cache_info|apc_cas|apc_clear_cache|apc_compile_file|apc_dec|apc_define_constants|apc_delete|apc_delete_file|apc_exists|apc_fetch|apc_inc|apc_load_constants|apc_sma_info|apc_store|apciterator|apd_breakpoint|apd_callstack|apd_clunk|apd_continue|apd_croak|apd_dump_function_table|apd_dump_persistent_resources|apd_dump_regular_resources|apd_echo|apd_get_active_symbols|apd_set_pprof_trace|apd_set_session|apd_set_session_trace|apd_set_session_trace_socket|appenditerator|array|array_change_key_case|array_chunk|array_combine|array_count_values|array_diff|array_diff_assoc|array_diff_key|array_diff_uassoc|array_diff_ukey|array_fill|array_fill_keys|array_filter|array_flip|array_intersect|array_intersect_assoc|array_intersect_key|array_intersect_uassoc|array_intersect_ukey|array_key_exists|array_keys|array_map|array_merge|array_merge_recursive|array_multisort|array_pad|array_pop|array_product|array_push|array_rand|array_reduce|array_replace|array_replace_recursive|array_reverse|array_search|array_shift|array_slice|array_splice|array_sum|array_udiff|array_udiff_assoc|array_udiff_uassoc|array_uintersect|array_uintersect_assoc|array_uintersect_uassoc|array_unique|array_unshift|array_values|array_walk|array_walk_recursive|arrayaccess|arrayiterator|arrayobject|arsort|asin|asinh|asort|assert|assert_options|atan|atan2|atanh|audioproperties|badfunctioncallexception|badmethodcallexception|base64_decode|base64_encode|base_convert|basename|bbcode_add_element|bbcode_add_smiley|bbcode_create|bbcode_destroy|bbcode_parse|bbcode_set_arg_parser|bbcode_set_flags|bcadd|bccomp|bcdiv|bcmod|bcmul|bcompiler_load|bcompiler_load_exe|bcompiler_parse_class|bcompiler_read|bcompiler_write_class|bcompiler_write_constant|bcompiler_write_exe_footer|bcompiler_write_file|bcompiler_write_footer|bcompiler_write_function|bcompiler_write_functions_from_file|bcompiler_write_header|bcompiler_write_included_filename|bcpow|bcpowmod|bcscale|bcsqrt|bcsub|bin2hex|bind_textdomain_codeset|bindec|bindtextdomain|bson_decode|bson_encode|bumpValue|bzclose|bzcompress|bzdecompress|bzerrno|bzerror|bzerrstr|bzflush|bzopen|bzread|bzwrite|cachingiterator|cairo|cairo_create|cairo_font_face_get_type|cairo_font_face_status|cairo_font_options_create|cairo_font_options_equal|cairo_font_options_get_antialias|cairo_font_options_get_hint_metrics|cairo_font_options_get_hint_style|cairo_font_options_get_subpixel_order|cairo_font_options_hash|cairo_font_options_merge|cairo_font_options_set_antialias|cairo_font_options_set_hint_metrics|cairo_font_options_set_hint_style|cairo_font_options_set_subpixel_order|cairo_font_options_status|cairo_format_stride_for_width|cairo_image_surface_create|cairo_image_surface_create_for_data|cairo_image_surface_create_from_png|cairo_image_surface_get_data|cairo_image_surface_get_format|cairo_image_surface_get_height|cairo_image_surface_get_stride|cairo_image_surface_get_width|cairo_matrix_create_scale|cairo_matrix_create_translate|cairo_matrix_invert|cairo_matrix_multiply|cairo_matrix_rotate|cairo_matrix_transform_distance|cairo_matrix_transform_point|cairo_matrix_translate|cairo_pattern_add_color_stop_rgb|cairo_pattern_add_color_stop_rgba|cairo_pattern_create_for_surface|cairo_pattern_create_linear|cairo_pattern_create_radial|cairo_pattern_create_rgb|cairo_pattern_create_rgba|cairo_pattern_get_color_stop_count|cairo_pattern_get_color_stop_rgba|cairo_pattern_get_extend|cairo_pattern_get_filter|cairo_pattern_get_linear_points|cairo_pattern_get_matrix|cairo_pattern_get_radial_circles|cairo_pattern_get_rgba|cairo_pattern_get_surface|cairo_pattern_get_type|cairo_pattern_set_extend|cairo_pattern_set_filter|cairo_pattern_set_matrix|cairo_pattern_status|cairo_pdf_surface_create|cairo_pdf_surface_set_size|cairo_ps_get_levels|cairo_ps_level_to_string|cairo_ps_surface_create|cairo_ps_surface_dsc_begin_page_setup|cairo_ps_surface_dsc_begin_setup|cairo_ps_surface_dsc_comment|cairo_ps_surface_get_eps|cairo_ps_surface_restrict_to_level|cairo_ps_surface_set_eps|cairo_ps_surface_set_size|cairo_scaled_font_create|cairo_scaled_font_extents|cairo_scaled_font_get_ctm|cairo_scaled_font_get_font_face|cairo_scaled_font_get_font_matrix|cairo_scaled_font_get_font_options|cairo_scaled_font_get_scale_matrix|cairo_scaled_font_get_type|cairo_scaled_font_glyph_extents|cairo_scaled_font_status|cairo_scaled_font_text_extents|cairo_surface_copy_page|cairo_surface_create_similar|cairo_surface_finish|cairo_surface_flush|cairo_surface_get_content|cairo_surface_get_device_offset|cairo_surface_get_font_options|cairo_surface_get_type|cairo_surface_mark_dirty|cairo_surface_mark_dirty_rectangle|cairo_surface_set_device_offset|cairo_surface_set_fallback_resolution|cairo_surface_show_page|cairo_surface_status|cairo_surface_write_to_png|cairo_svg_surface_create|cairo_svg_surface_restrict_to_version|cairo_svg_version_to_string|cairoantialias|cairocontent|cairocontext|cairoexception|cairoextend|cairofillrule|cairofilter|cairofontface|cairofontoptions|cairofontslant|cairofonttype|cairofontweight|cairoformat|cairogradientpattern|cairohintmetrics|cairohintstyle|cairoimagesurface|cairolineargradient|cairolinecap|cairolinejoin|cairomatrix|cairooperator|cairopath|cairopattern|cairopatterntype|cairopdfsurface|cairopslevel|cairopssurface|cairoradialgradient|cairoscaledfont|cairosolidpattern|cairostatus|cairosubpixelorder|cairosurface|cairosurfacepattern|cairosurfacetype|cairosvgsurface|cairosvgversion|cairotoyfontface|cal_days_in_month|cal_from_jd|cal_info|cal_to_jd|calcul_hmac|calculhmac|call_user_func|call_user_func_array|call_user_method|call_user_method_array|callbackfilteriterator|ceil|chdb|chdb_create|chdir|checkdate|checkdnsrr|chgrp|chmod|chop|chown|chr|chroot|chunk_split|class_alias|class_exists|class_implements|class_parents|classkit_import|classkit_method_add|classkit_method_copy|classkit_method_redefine|classkit_method_remove|classkit_method_rename|clearstatcache|clone|closedir|closelog|collator|com|com_addref|com_create_guid|com_event_sink|com_get|com_get_active_object|com_invoke|com_isenum|com_load|com_load_typelib|com_message_pump|com_print_typeinfo|com_propget|com_propput|com_propset|com_release|com_set|compact|connection_aborted|connection_status|connection_timeout|constant|construct|construct|construct|convert_cyr_string|convert_uudecode|convert_uuencode|copy|cos|cosh|count|count_chars|countable|counter_bump|counter_bump_value|counter_create|counter_get|counter_get_meta|counter_get_named|counter_get_value|counter_reset|counter_reset_value|crack_check|crack_closedict|crack_getlastmessage|crack_opendict|crc32|create_function|crypt|ctype_alnum|ctype_alpha|ctype_cntrl|ctype_digit|ctype_graph|ctype_lower|ctype_print|ctype_punct|ctype_space|ctype_upper|ctype_xdigit|cubrid_affected_rows|cubrid_bind|cubrid_client_encoding|cubrid_close|cubrid_close_prepare|cubrid_close_request|cubrid_col_get|cubrid_col_size|cubrid_column_names|cubrid_column_types|cubrid_commit|cubrid_connect|cubrid_connect_with_url|cubrid_current_oid|cubrid_data_seek|cubrid_db_name|cubrid_disconnect|cubrid_drop|cubrid_errno|cubrid_error|cubrid_error_code|cubrid_error_code_facility|cubrid_error_msg|cubrid_execute|cubrid_fetch|cubrid_fetch_array|cubrid_fetch_assoc|cubrid_fetch_field|cubrid_fetch_lengths|cubrid_fetch_object|cubrid_fetch_row|cubrid_field_flags|cubrid_field_len|cubrid_field_name|cubrid_field_seek|cubrid_field_table|cubrid_field_type|cubrid_free_result|cubrid_get|cubrid_get_autocommit|cubrid_get_charset|cubrid_get_class_name|cubrid_get_client_info|cubrid_get_db_parameter|cubrid_get_server_info|cubrid_insert_id|cubrid_is_instance|cubrid_list_dbs|cubrid_load_from_glo|cubrid_lob_close|cubrid_lob_export|cubrid_lob_get|cubrid_lob_send|cubrid_lob_size|cubrid_lock_read|cubrid_lock_write|cubrid_move_cursor|cubrid_new_glo|cubrid_next_result|cubrid_num_cols|cubrid_num_fields|cubrid_num_rows|cubrid_ping|cubrid_prepare|cubrid_put|cubrid_query|cubrid_real_escape_string|cubrid_result|cubrid_rollback|cubrid_save_to_glo|cubrid_schema|cubrid_send_glo|cubrid_seq_drop|cubrid_seq_insert|cubrid_seq_put|cubrid_set_add|cubrid_set_autocommit|cubrid_set_db_parameter|cubrid_set_drop|cubrid_unbuffered_query|cubrid_version|curl_close|curl_copy_handle|curl_errno|curl_error|curl_exec|curl_getinfo|curl_init|curl_multi_add_handle|curl_multi_close|curl_multi_exec|curl_multi_getcontent|curl_multi_info_read|curl_multi_init|curl_multi_remove_handle|curl_multi_select|curl_setopt|curl_setopt_array|curl_version|current|cyrus_authenticate|cyrus_bind|cyrus_close|cyrus_connect|cyrus_query|cyrus_unbind|date|date_add|date_create|date_create_from_format|date_date_set|date_default_timezone_get|date_default_timezone_set|date_diff|date_format|date_get_last_errors|date_interval_create_from_date_string|date_interval_format|date_isodate_set|date_modify|date_offset_get|date_parse|date_parse_from_format|date_sub|date_sun_info|date_sunrise|date_sunset|date_time_set|date_timestamp_get|date_timestamp_set|date_timezone_get|date_timezone_set|dateinterval|dateperiod|datetime|datetimezone|db2_autocommit|db2_bind_param|db2_client_info|db2_close|db2_column_privileges|db2_columns|db2_commit|db2_conn_error|db2_conn_errormsg|db2_connect|db2_cursor_type|db2_escape_string|db2_exec|db2_execute|db2_fetch_array|db2_fetch_assoc|db2_fetch_both|db2_fetch_object|db2_fetch_row|db2_field_display_size|db2_field_name|db2_field_num|db2_field_precision|db2_field_scale|db2_field_type|db2_field_width|db2_foreign_keys|db2_free_result|db2_free_stmt|db2_get_option|db2_last_insert_id|db2_lob_read|db2_next_result|db2_num_fields|db2_num_rows|db2_pclose|db2_pconnect|db2_prepare|db2_primary_keys|db2_procedure_columns|db2_procedures|db2_result|db2_rollback|db2_server_info|db2_set_option|db2_special_columns|db2_statistics|db2_stmt_error|db2_stmt_errormsg|db2_table_privileges|db2_tables|dba_close|dba_delete|dba_exists|dba_fetch|dba_firstkey|dba_handlers|dba_insert|dba_key_split|dba_list|dba_nextkey|dba_open|dba_optimize|dba_popen|dba_replace|dba_sync|dbase_add_record|dbase_close|dbase_create|dbase_delete_record|dbase_get_header_info|dbase_get_record|dbase_get_record_with_names|dbase_numfields|dbase_numrecords|dbase_open|dbase_pack|dbase_replace_record|dbplus_add|dbplus_aql|dbplus_chdir|dbplus_close|dbplus_curr|dbplus_errcode|dbplus_errno|dbplus_find|dbplus_first|dbplus_flush|dbplus_freealllocks|dbplus_freelock|dbplus_freerlocks|dbplus_getlock|dbplus_getunique|dbplus_info|dbplus_last|dbplus_lockrel|dbplus_next|dbplus_open|dbplus_prev|dbplus_rchperm|dbplus_rcreate|dbplus_rcrtexact|dbplus_rcrtlike|dbplus_resolve|dbplus_restorepos|dbplus_rkeys|dbplus_ropen|dbplus_rquery|dbplus_rrename|dbplus_rsecindex|dbplus_runlink|dbplus_rzap|dbplus_savepos|dbplus_setindex|dbplus_setindexbynumber|dbplus_sql|dbplus_tcl|dbplus_tremove|dbplus_undo|dbplus_undoprepare|dbplus_unlockrel|dbplus_unselect|dbplus_update|dbplus_xlockrel|dbplus_xunlockrel|dbx_close|dbx_compare|dbx_connect|dbx_error|dbx_escape_string|dbx_fetch_row|dbx_query|dbx_sort|dcgettext|dcngettext|deaggregate|debug_backtrace|debug_print_backtrace|debug_zval_dump|decbin|dechex|decoct|define|define_syslog_variables|defined|deg2rad|delete|dgettext|die|dio_close|dio_fcntl|dio_open|dio_read|dio_seek|dio_stat|dio_tcsetattr|dio_truncate|dio_write|dir|directoryiterator|dirname|disk_free_space|disk_total_space|diskfreespace|dl|dngettext|dns_check_record|dns_get_mx|dns_get_record|dom_import_simplexml|domainexception|domattr|domattribute_name|domattribute_set_value|domattribute_specified|domattribute_value|domcharacterdata|domcomment|domdocument|domdocument_add_root|domdocument_create_attribute|domdocument_create_cdata_section|domdocument_create_comment|domdocument_create_element|domdocument_create_element_ns|domdocument_create_entity_reference|domdocument_create_processing_instruction|domdocument_create_text_node|domdocument_doctype|domdocument_document_element|domdocument_dump_file|domdocument_dump_mem|domdocument_get_element_by_id|domdocument_get_elements_by_tagname|domdocument_html_dump_mem|domdocument_xinclude|domdocumentfragment|domdocumenttype|domdocumenttype_entities|domdocumenttype_internal_subset|domdocumenttype_name|domdocumenttype_notations|domdocumenttype_public_id|domdocumenttype_system_id|domelement|domelement_get_attribute|domelement_get_attribute_node|domelement_get_elements_by_tagname|domelement_has_attribute|domelement_remove_attribute|domelement_set_attribute|domelement_set_attribute_node|domelement_tagname|domentity|domentityreference|domexception|domimplementation|domnamednodemap|domnode|domnode_add_namespace|domnode_append_child|domnode_append_sibling|domnode_attributes|domnode_child_nodes|domnode_clone_node|domnode_dump_node|domnode_first_child|domnode_get_content|domnode_has_attributes|domnode_has_child_nodes|domnode_insert_before|domnode_is_blank_node|domnode_last_child|domnode_next_sibling|domnode_node_name|domnode_node_type|domnode_node_value|domnode_owner_document|domnode_parent_node|domnode_prefix|domnode_previous_sibling|domnode_remove_child|domnode_replace_child|domnode_replace_node|domnode_set_content|domnode_set_name|domnode_set_namespace|domnode_unlink_node|domnodelist|domnotation|domprocessinginstruction|domprocessinginstruction_data|domprocessinginstruction_target|domtext|domxml_new_doc|domxml_open_file|domxml_open_mem|domxml_version|domxml_xmltree|domxml_xslt_stylesheet|domxml_xslt_stylesheet_doc|domxml_xslt_stylesheet_file|domxml_xslt_version|domxpath|domxsltstylesheet_process|domxsltstylesheet_result_dump_file|domxsltstylesheet_result_dump_mem|dotnet|dotnet_load|doubleval|each|easter_date|easter_days|echo|empty|emptyiterator|enchant_broker_describe|enchant_broker_dict_exists|enchant_broker_free|enchant_broker_free_dict|enchant_broker_get_error|enchant_broker_init|enchant_broker_list_dicts|enchant_broker_request_dict|enchant_broker_request_pwl_dict|enchant_broker_set_ordering|enchant_dict_add_to_personal|enchant_dict_add_to_session|enchant_dict_check|enchant_dict_describe|enchant_dict_get_error|enchant_dict_is_in_session|enchant_dict_quick_check|enchant_dict_store_replacement|enchant_dict_suggest|end|ereg|ereg_replace|eregi|eregi_replace|error_get_last|error_log|error_reporting|errorexception|escapeshellarg|escapeshellcmd|eval|event_add|event_base_free|event_base_loop|event_base_loopbreak|event_base_loopexit|event_base_new|event_base_priority_init|event_base_set|event_buffer_base_set|event_buffer_disable|event_buffer_enable|event_buffer_fd_set|event_buffer_free|event_buffer_new|event_buffer_priority_set|event_buffer_read|event_buffer_set_callback|event_buffer_timeout_set|event_buffer_watermark_set|event_buffer_write|event_del|event_free|event_new|event_set|exception|exec|exif_imagetype|exif_read_data|exif_tagname|exif_thumbnail|exit|exp|expect_expectl|expect_popen|explode|expm1|export|export|extension_loaded|extract|ezmlm_hash|fam_cancel_monitor|fam_close|fam_monitor_collection|fam_monitor_directory|fam_monitor_file|fam_next_event|fam_open|fam_pending|fam_resume_monitor|fam_suspend_monitor|fbsql_affected_rows|fbsql_autocommit|fbsql_blob_size|fbsql_change_user|fbsql_clob_size|fbsql_close|fbsql_commit|fbsql_connect|fbsql_create_blob|fbsql_create_clob|fbsql_create_db|fbsql_data_seek|fbsql_database|fbsql_database_password|fbsql_db_query|fbsql_db_status|fbsql_drop_db|fbsql_errno|fbsql_error|fbsql_fetch_array|fbsql_fetch_assoc|fbsql_fetch_field|fbsql_fetch_lengths|fbsql_fetch_object|fbsql_fetch_row|fbsql_field_flags|fbsql_field_len|fbsql_field_name|fbsql_field_seek|fbsql_field_table|fbsql_field_type|fbsql_free_result|fbsql_get_autostart_info|fbsql_hostname|fbsql_insert_id|fbsql_list_dbs|fbsql_list_fields|fbsql_list_tables|fbsql_next_result|fbsql_num_fields|fbsql_num_rows|fbsql_password|fbsql_pconnect|fbsql_query|fbsql_read_blob|fbsql_read_clob|fbsql_result|fbsql_rollback|fbsql_rows_fetched|fbsql_select_db|fbsql_set_characterset|fbsql_set_lob_mode|fbsql_set_password|fbsql_set_transaction|fbsql_start_db|fbsql_stop_db|fbsql_table_name|fbsql_tablename|fbsql_username|fbsql_warnings|fclose|fdf_add_doc_javascript|fdf_add_template|fdf_close|fdf_create|fdf_enum_values|fdf_errno|fdf_error|fdf_get_ap|fdf_get_attachment|fdf_get_encoding|fdf_get_file|fdf_get_flags|fdf_get_opt|fdf_get_status|fdf_get_value|fdf_get_version|fdf_header|fdf_next_field_name|fdf_open|fdf_open_string|fdf_remove_item|fdf_save|fdf_save_string|fdf_set_ap|fdf_set_encoding|fdf_set_file|fdf_set_flags|fdf_set_javascript_action|fdf_set_on_import_javascript|fdf_set_opt|fdf_set_status|fdf_set_submit_form_action|fdf_set_target_frame|fdf_set_value|fdf_set_version|feof|fflush|fgetc|fgetcsv|fgets|fgetss|file|file_exists|file_get_contents|file_put_contents|fileatime|filectime|filegroup|fileinode|filemtime|fileowner|fileperms|filepro|filepro_fieldcount|filepro_fieldname|filepro_fieldtype|filepro_fieldwidth|filepro_retrieve|filepro_rowcount|filesize|filesystemiterator|filetype|filter_has_var|filter_id|filter_input|filter_input_array|filter_list|filter_var|filter_var_array|filteriterator|finfo_buffer|finfo_close|finfo_file|finfo_open|finfo_set_flags|floatval|flock|floor|flush|fmod|fnmatch|fopen|forward_static_call|forward_static_call_array|fpassthru|fprintf|fputcsv|fputs|fread|frenchtojd|fribidi_log2vis|fscanf|fseek|fsockopen|fstat|ftell|ftok|ftp_alloc|ftp_cdup|ftp_chdir|ftp_chmod|ftp_close|ftp_connect|ftp_delete|ftp_exec|ftp_fget|ftp_fput|ftp_get|ftp_get_option|ftp_login|ftp_mdtm|ftp_mkdir|ftp_nb_continue|ftp_nb_fget|ftp_nb_fput|ftp_nb_get|ftp_nb_put|ftp_nlist|ftp_pasv|ftp_put|ftp_pwd|ftp_quit|ftp_raw|ftp_rawlist|ftp_rename|ftp_rmdir|ftp_set_option|ftp_site|ftp_size|ftp_ssl_connect|ftp_systype|ftruncate|func_get_arg|func_get_args|func_num_args|function_exists|fwrite|gc_collect_cycles|gc_disable|gc_enable|gc_enabled|gd_info|gearmanclient|gearmanjob|gearmantask|gearmanworker|geoip_continent_code_by_name|geoip_country_code3_by_name|geoip_country_code_by_name|geoip_country_name_by_name|geoip_database_info|geoip_db_avail|geoip_db_filename|geoip_db_get_all_info|geoip_id_by_name|geoip_isp_by_name|geoip_org_by_name|geoip_record_by_name|geoip_region_by_name|geoip_region_name_by_code|geoip_time_zone_by_country_and_region|getMeta|getNamed|getValue|get_browser|get_called_class|get_cfg_var|get_class|get_class_methods|get_class_vars|get_current_user|get_declared_classes|get_declared_interfaces|get_defined_constants|get_defined_functions|get_defined_vars|get_extension_funcs|get_headers|get_html_translation_table|get_include_path|get_included_files|get_loaded_extensions|get_magic_quotes_gpc|get_magic_quotes_runtime|get_meta_tags|get_object_vars|get_parent_class|get_required_files|get_resource_type|getallheaders|getconstant|getconstants|getconstructor|getcwd|getdate|getdefaultproperties|getdoccomment|getendline|getenv|getextension|getextensionname|getfilename|gethostbyaddr|gethostbyname|gethostbynamel|gethostname|getimagesize|getinterfacenames|getinterfaces|getlastmod|getmethod|getmethods|getmodifiers|getmxrr|getmygid|getmyinode|getmypid|getmyuid|getname|getnamespacename|getopt|getparentclass|getproperties|getproperty|getprotobyname|getprotobynumber|getrandmax|getrusage|getservbyname|getservbyport|getshortname|getstartline|getstaticproperties|getstaticpropertyvalue|gettext|gettimeofday|gettype|glob|globiterator|gmagick|gmagickdraw|gmagickpixel|gmdate|gmmktime|gmp_abs|gmp_add|gmp_and|gmp_clrbit|gmp_cmp|gmp_com|gmp_div|gmp_div_q|gmp_div_qr|gmp_div_r|gmp_divexact|gmp_fact|gmp_gcd|gmp_gcdext|gmp_hamdist|gmp_init|gmp_intval|gmp_invert|gmp_jacobi|gmp_legendre|gmp_mod|gmp_mul|gmp_neg|gmp_nextprime|gmp_or|gmp_perfect_square|gmp_popcount|gmp_pow|gmp_powm|gmp_prob_prime|gmp_random|gmp_scan0|gmp_scan1|gmp_setbit|gmp_sign|gmp_sqrt|gmp_sqrtrem|gmp_strval|gmp_sub|gmp_testbit|gmp_xor|gmstrftime|gnupg_adddecryptkey|gnupg_addencryptkey|gnupg_addsignkey|gnupg_cleardecryptkeys|gnupg_clearencryptkeys|gnupg_clearsignkeys|gnupg_decrypt|gnupg_decryptverify|gnupg_encrypt|gnupg_encryptsign|gnupg_export|gnupg_geterror|gnupg_getprotocol|gnupg_import|gnupg_init|gnupg_keyinfo|gnupg_setarmor|gnupg_seterrormode|gnupg_setsignmode|gnupg_sign|gnupg_verify|gopher_parsedir|grapheme_extract|grapheme_stripos|grapheme_stristr|grapheme_strlen|grapheme_strpos|grapheme_strripos|grapheme_strrpos|grapheme_strstr|grapheme_substr|gregoriantojd|gupnp_context_get_host_ip|gupnp_context_get_port|gupnp_context_get_subscription_timeout|gupnp_context_host_path|gupnp_context_new|gupnp_context_set_subscription_timeout|gupnp_context_timeout_add|gupnp_context_unhost_path|gupnp_control_point_browse_start|gupnp_control_point_browse_stop|gupnp_control_point_callback_set|gupnp_control_point_new|gupnp_device_action_callback_set|gupnp_device_info_get|gupnp_device_info_get_service|gupnp_root_device_get_available|gupnp_root_device_get_relative_location|gupnp_root_device_new|gupnp_root_device_set_available|gupnp_root_device_start|gupnp_root_device_stop|gupnp_service_action_get|gupnp_service_action_return|gupnp_service_action_return_error|gupnp_service_action_set|gupnp_service_freeze_notify|gupnp_service_info_get|gupnp_service_info_get_introspection|gupnp_service_introspection_get_state_variable|gupnp_service_notify|gupnp_service_proxy_action_get|gupnp_service_proxy_action_set|gupnp_service_proxy_add_notify|gupnp_service_proxy_callback_set|gupnp_service_proxy_get_subscribed|gupnp_service_proxy_remove_notify|gupnp_service_proxy_set_subscribed|gupnp_service_thaw_notify|gzclose|gzcompress|gzdecode|gzdeflate|gzencode|gzeof|gzfile|gzgetc|gzgets|gzgetss|gzinflate|gzopen|gzpassthru|gzputs|gzread|gzrewind|gzseek|gztell|gzuncompress|gzwrite|halt_compiler|haruannotation|haruannotation_setborderstyle|haruannotation_sethighlightmode|haruannotation_seticon|haruannotation_setopened|harudestination|harudestination_setfit|harudestination_setfitb|harudestination_setfitbh|harudestination_setfitbv|harudestination_setfith|harudestination_setfitr|harudestination_setfitv|harudestination_setxyz|harudoc|harudoc_addpage|harudoc_addpagelabel|harudoc_construct|harudoc_createoutline|harudoc_getcurrentencoder|harudoc_getcurrentpage|harudoc_getencoder|harudoc_getfont|harudoc_getinfoattr|harudoc_getpagelayout|harudoc_getpagemode|harudoc_getstreamsize|harudoc_insertpage|harudoc_loadjpeg|harudoc_loadpng|harudoc_loadraw|harudoc_loadttc|harudoc_loadttf|harudoc_loadtype1|harudoc_output|harudoc_readfromstream|harudoc_reseterror|harudoc_resetstream|harudoc_save|harudoc_savetostream|harudoc_setcompressionmode|harudoc_setcurrentencoder|harudoc_setencryptionmode|harudoc_setinfoattr|harudoc_setinfodateattr|harudoc_setopenaction|harudoc_setpagelayout|harudoc_setpagemode|harudoc_setpagesconfiguration|harudoc_setpassword|harudoc_setpermission|harudoc_usecnsencodings|harudoc_usecnsfonts|harudoc_usecntencodings|harudoc_usecntfonts|harudoc_usejpencodings|harudoc_usejpfonts|harudoc_usekrencodings|harudoc_usekrfonts|haruencoder|haruencoder_getbytetype|haruencoder_gettype|haruencoder_getunicode|haruencoder_getwritingmode|haruexception|harufont|harufont_getascent|harufont_getcapheight|harufont_getdescent|harufont_getencodingname|harufont_getfontname|harufont_gettextwidth|harufont_getunicodewidth|harufont_getxheight|harufont_measuretext|haruimage|haruimage_getbitspercomponent|haruimage_getcolorspace|haruimage_getheight|haruimage_getsize|haruimage_getwidth|haruimage_setcolormask|haruimage_setmaskimage|haruoutline|haruoutline_setdestination|haruoutline_setopened|harupage|harupage_arc|harupage_begintext|harupage_circle|harupage_closepath|harupage_concat|harupage_createdestination|harupage_createlinkannotation|harupage_createtextannotation|harupage_createurlannotation|harupage_curveto|harupage_curveto2|harupage_curveto3|harupage_drawimage|harupage_ellipse|harupage_endpath|harupage_endtext|harupage_eofill|harupage_eofillstroke|harupage_fill|harupage_fillstroke|harupage_getcharspace|harupage_getcmykfill|harupage_getcmykstroke|harupage_getcurrentfont|harupage_getcurrentfontsize|harupage_getcurrentpos|harupage_getcurrenttextpos|harupage_getdash|harupage_getfillingcolorspace|harupage_getflatness|harupage_getgmode|harupage_getgrayfill|harupage_getgraystroke|harupage_getheight|harupage_gethorizontalscaling|harupage_getlinecap|harupage_getlinejoin|harupage_getlinewidth|harupage_getmiterlimit|harupage_getrgbfill|harupage_getrgbstroke|harupage_getstrokingcolorspace|harupage_gettextleading|harupage_gettextmatrix|harupage_gettextrenderingmode|harupage_gettextrise|harupage_gettextwidth|harupage_gettransmatrix|harupage_getwidth|harupage_getwordspace|harupage_lineto|harupage_measuretext|harupage_movetextpos|harupage_moveto|harupage_movetonextline|harupage_rectangle|harupage_setcharspace|harupage_setcmykfill|harupage_setcmykstroke|harupage_setdash|harupage_setflatness|harupage_setfontandsize|harupage_setgrayfill|harupage_setgraystroke|harupage_setheight|harupage_sethorizontalscaling|harupage_setlinecap|harupage_setlinejoin|harupage_setlinewidth|harupage_setmiterlimit|harupage_setrgbfill|harupage_setrgbstroke|harupage_setrotate|harupage_setsize|harupage_setslideshow|harupage_settextleading|harupage_settextmatrix|harupage_settextrenderingmode|harupage_settextrise|harupage_setwidth|harupage_setwordspace|harupage_showtext|harupage_showtextnextline|harupage_stroke|harupage_textout|harupage_textrect|hasconstant|hash|hash_algos|hash_copy|hash_file|hash_final|hash_hmac|hash_hmac_file|hash_init|hash_update|hash_update_file|hash_update_stream|hasmethod|hasproperty|header|header_register_callback|header_remove|headers_list|headers_sent|hebrev|hebrevc|hex2bin|hexdec|highlight_file|highlight_string|html_entity_decode|htmlentities|htmlspecialchars|htmlspecialchars_decode|http_build_cookie|http_build_query|http_build_str|http_build_url|http_cache_etag|http_cache_last_modified|http_chunked_decode|http_date|http_deflate|http_get|http_get_request_body|http_get_request_body_stream|http_get_request_headers|http_head|http_inflate|http_match_etag|http_match_modified|http_match_request_header|http_negotiate_charset|http_negotiate_content_type|http_negotiate_language|http_parse_cookie|http_parse_headers|http_parse_message|http_parse_params|http_persistent_handles_clean|http_persistent_handles_count|http_persistent_handles_ident|http_post_data|http_post_fields|http_put_data|http_put_file|http_put_stream|http_redirect|http_request|http_request_body_encode|http_request_method_exists|http_request_method_name|http_request_method_register|http_request_method_unregister|http_response_code|http_send_content_disposition|http_send_content_type|http_send_data|http_send_file|http_send_last_modified|http_send_status|http_send_stream|http_support|http_throttle|httpdeflatestream|httpdeflatestream_construct|httpdeflatestream_factory|httpdeflatestream_finish|httpdeflatestream_flush|httpdeflatestream_update|httpinflatestream|httpinflatestream_construct|httpinflatestream_factory|httpinflatestream_finish|httpinflatestream_flush|httpinflatestream_update|httpmessage|httpmessage_addheaders|httpmessage_construct|httpmessage_detach|httpmessage_factory|httpmessage_fromenv|httpmessage_fromstring|httpmessage_getbody|httpmessage_getheader|httpmessage_getheaders|httpmessage_gethttpversion|httpmessage_getparentmessage|httpmessage_getrequestmethod|httpmessage_getrequesturl|httpmessage_getresponsecode|httpmessage_getresponsestatus|httpmessage_gettype|httpmessage_guesscontenttype|httpmessage_prepend|httpmessage_reverse|httpmessage_send|httpmessage_setbody|httpmessage_setheaders|httpmessage_sethttpversion|httpmessage_setrequestmethod|httpmessage_setrequesturl|httpmessage_setresponsecode|httpmessage_setresponsestatus|httpmessage_settype|httpmessage_tomessagetypeobject|httpmessage_tostring|httpquerystring|httpquerystring_construct|httpquerystring_get|httpquerystring_mod|httpquerystring_set|httpquerystring_singleton|httpquerystring_toarray|httpquerystring_tostring|httpquerystring_xlate|httprequest|httprequest_addcookies|httprequest_addheaders|httprequest_addpostfields|httprequest_addpostfile|httprequest_addputdata|httprequest_addquerydata|httprequest_addrawpostdata|httprequest_addssloptions|httprequest_clearhistory|httprequest_construct|httprequest_enablecookies|httprequest_getcontenttype|httprequest_getcookies|httprequest_getheaders|httprequest_gethistory|httprequest_getmethod|httprequest_getoptions|httprequest_getpostfields|httprequest_getpostfiles|httprequest_getputdata|httprequest_getputfile|httprequest_getquerydata|httprequest_getrawpostdata|httprequest_getrawrequestmessage|httprequest_getrawresponsemessage|httprequest_getrequestmessage|httprequest_getresponsebody|httprequest_getresponsecode|httprequest_getresponsecookies|httprequest_getresponsedata|httprequest_getresponseheader|httprequest_getresponseinfo|httprequest_getresponsemessage|httprequest_getresponsestatus|httprequest_getssloptions|httprequest_geturl|httprequest_resetcookies|httprequest_send|httprequest_setcontenttype|httprequest_setcookies|httprequest_setheaders|httprequest_setmethod|httprequest_setoptions|httprequest_setpostfields|httprequest_setpostfiles|httprequest_setputdata|httprequest_setputfile|httprequest_setquerydata|httprequest_setrawpostdata|httprequest_setssloptions|httprequest_seturl|httprequestpool|httprequestpool_attach|httprequestpool_construct|httprequestpool_destruct|httprequestpool_detach|httprequestpool_getattachedrequests|httprequestpool_getfinishedrequests|httprequestpool_reset|httprequestpool_send|httprequestpool_socketperform|httprequestpool_socketselect|httpresponse|httpresponse_capture|httpresponse_getbuffersize|httpresponse_getcache|httpresponse_getcachecontrol|httpresponse_getcontentdisposition|httpresponse_getcontenttype|httpresponse_getdata|httpresponse_getetag|httpresponse_getfile|httpresponse_getgzip|httpresponse_getheader|httpresponse_getlastmodified|httpresponse_getrequestbody|httpresponse_getrequestbodystream|httpresponse_getrequestheaders|httpresponse_getstream|httpresponse_getthrottledelay|httpresponse_guesscontenttype|httpresponse_redirect|httpresponse_send|httpresponse_setbuffersize|httpresponse_setcache|httpresponse_setcachecontrol|httpresponse_setcontentdisposition|httpresponse_setcontenttype|httpresponse_setdata|httpresponse_setetag|httpresponse_setfile|httpresponse_setgzip|httpresponse_setheader|httpresponse_setlastmodified|httpresponse_setstream|httpresponse_setthrottledelay|httpresponse_status|hw_array2objrec|hw_changeobject|hw_children|hw_childrenobj|hw_close|hw_connect|hw_connection_info|hw_cp|hw_deleteobject|hw_docbyanchor|hw_docbyanchorobj|hw_document_attributes|hw_document_bodytag|hw_document_content|hw_document_setcontent|hw_document_size|hw_dummy|hw_edittext|hw_error|hw_errormsg|hw_free_document|hw_getanchors|hw_getanchorsobj|hw_getandlock|hw_getchildcoll|hw_getchildcollobj|hw_getchilddoccoll|hw_getchilddoccollobj|hw_getobject|hw_getobjectbyquery|hw_getobjectbyquerycoll|hw_getobjectbyquerycollobj|hw_getobjectbyqueryobj|hw_getparents|hw_getparentsobj|hw_getrellink|hw_getremote|hw_getremotechildren|hw_getsrcbydestobj|hw_gettext|hw_getusername|hw_identify|hw_incollections|hw_info|hw_inscoll|hw_insdoc|hw_insertanchors|hw_insertdocument|hw_insertobject|hw_mapid|hw_modifyobject|hw_mv|hw_new_document|hw_objrec2array|hw_output_document|hw_pconnect|hw_pipedocument|hw_root|hw_setlinkroot|hw_stat|hw_unlock|hw_who|hwapi_attribute|hwapi_attribute_key|hwapi_attribute_langdepvalue|hwapi_attribute_value|hwapi_attribute_values|hwapi_checkin|hwapi_checkout|hwapi_children|hwapi_content|hwapi_content_mimetype|hwapi_content_read|hwapi_copy|hwapi_dbstat|hwapi_dcstat|hwapi_dstanchors|hwapi_dstofsrcanchor|hwapi_error_count|hwapi_error_reason|hwapi_find|hwapi_ftstat|hwapi_hgcsp|hwapi_hwstat|hwapi_identify|hwapi_info|hwapi_insert|hwapi_insertanchor|hwapi_insertcollection|hwapi_insertdocument|hwapi_link|hwapi_lock|hwapi_move|hwapi_new_content|hwapi_object|hwapi_object_assign|hwapi_object_attreditable|hwapi_object_count|hwapi_object_insert|hwapi_object_new|hwapi_object_remove|hwapi_object_title|hwapi_object_value|hwapi_objectbyanchor|hwapi_parents|hwapi_reason_description|hwapi_reason_type|hwapi_remove|hwapi_replace|hwapi_setcommittedversion|hwapi_srcanchors|hwapi_srcsofdst|hwapi_unlock|hwapi_user|hwapi_userlist|hypot|ibase_add_user|ibase_affected_rows|ibase_backup|ibase_blob_add|ibase_blob_cancel|ibase_blob_close|ibase_blob_create|ibase_blob_echo|ibase_blob_get|ibase_blob_import|ibase_blob_info|ibase_blob_open|ibase_close|ibase_commit|ibase_commit_ret|ibase_connect|ibase_db_info|ibase_delete_user|ibase_drop_db|ibase_errcode|ibase_errmsg|ibase_execute|ibase_fetch_assoc|ibase_fetch_object|ibase_fetch_row|ibase_field_info|ibase_free_event_handler|ibase_free_query|ibase_free_result|ibase_gen_id|ibase_maintain_db|ibase_modify_user|ibase_name_result|ibase_num_fields|ibase_num_params|ibase_param_info|ibase_pconnect|ibase_prepare|ibase_query|ibase_restore|ibase_rollback|ibase_rollback_ret|ibase_server_info|ibase_service_attach|ibase_service_detach|ibase_set_event_handler|ibase_timefmt|ibase_trans|ibase_wait_event|iconv|iconv_get_encoding|iconv_mime_decode|iconv_mime_decode_headers|iconv_mime_encode|iconv_set_encoding|iconv_strlen|iconv_strpos|iconv_strrpos|iconv_substr|id3_get_frame_long_name|id3_get_frame_short_name|id3_get_genre_id|id3_get_genre_list|id3_get_genre_name|id3_get_tag|id3_get_version|id3_remove_tag|id3_set_tag|id3v2attachedpictureframe|id3v2frame|id3v2tag|idate|idn_to_ascii|idn_to_unicode|idn_to_utf8|ifx_affected_rows|ifx_blobinfile_mode|ifx_byteasvarchar|ifx_close|ifx_connect|ifx_copy_blob|ifx_create_blob|ifx_create_char|ifx_do|ifx_error|ifx_errormsg|ifx_fetch_row|ifx_fieldproperties|ifx_fieldtypes|ifx_free_blob|ifx_free_char|ifx_free_result|ifx_get_blob|ifx_get_char|ifx_getsqlca|ifx_htmltbl_result|ifx_nullformat|ifx_num_fields|ifx_num_rows|ifx_pconnect|ifx_prepare|ifx_query|ifx_textasvarchar|ifx_update_blob|ifx_update_char|ifxus_close_slob|ifxus_create_slob|ifxus_free_slob|ifxus_open_slob|ifxus_read_slob|ifxus_seek_slob|ifxus_tell_slob|ifxus_write_slob|ignore_user_abort|iis_add_server|iis_get_dir_security|iis_get_script_map|iis_get_server_by_comment|iis_get_server_by_path|iis_get_server_rights|iis_get_service_state|iis_remove_server|iis_set_app_settings|iis_set_dir_security|iis_set_script_map|iis_set_server_rights|iis_start_server|iis_start_service|iis_stop_server|iis_stop_service|image2wbmp|image_type_to_extension|image_type_to_mime_type|imagealphablending|imageantialias|imagearc|imagechar|imagecharup|imagecolorallocate|imagecolorallocatealpha|imagecolorat|imagecolorclosest|imagecolorclosestalpha|imagecolorclosesthwb|imagecolordeallocate|imagecolorexact|imagecolorexactalpha|imagecolormatch|imagecolorresolve|imagecolorresolvealpha|imagecolorset|imagecolorsforindex|imagecolorstotal|imagecolortransparent|imageconvolution|imagecopy|imagecopymerge|imagecopymergegray|imagecopyresampled|imagecopyresized|imagecreate|imagecreatefromgd|imagecreatefromgd2|imagecreatefromgd2part|imagecreatefromgif|imagecreatefromjpeg|imagecreatefrompng|imagecreatefromstring|imagecreatefromwbmp|imagecreatefromxbm|imagecreatefromxpm|imagecreatetruecolor|imagedashedline|imagedestroy|imageellipse|imagefill|imagefilledarc|imagefilledellipse|imagefilledpolygon|imagefilledrectangle|imagefilltoborder|imagefilter|imagefontheight|imagefontwidth|imageftbbox|imagefttext|imagegammacorrect|imagegd|imagegd2|imagegif|imagegrabscreen|imagegrabwindow|imageinterlace|imageistruecolor|imagejpeg|imagelayereffect|imageline|imageloadfont|imagepalettecopy|imagepng|imagepolygon|imagepsbbox|imagepsencodefont|imagepsextendfont|imagepsfreefont|imagepsloadfont|imagepsslantfont|imagepstext|imagerectangle|imagerotate|imagesavealpha|imagesetbrush|imagesetpixel|imagesetstyle|imagesetthickness|imagesettile|imagestring|imagestringup|imagesx|imagesy|imagetruecolortopalette|imagettfbbox|imagettftext|imagetypes|imagewbmp|imagexbm|imagick|imagick_adaptiveblurimage|imagick_adaptiveresizeimage|imagick_adaptivesharpenimage|imagick_adaptivethresholdimage|imagick_addimage|imagick_addnoiseimage|imagick_affinetransformimage|imagick_animateimages|imagick_annotateimage|imagick_appendimages|imagick_averageimages|imagick_blackthresholdimage|imagick_blurimage|imagick_borderimage|imagick_charcoalimage|imagick_chopimage|imagick_clear|imagick_clipimage|imagick_clippathimage|imagick_clone|imagick_clutimage|imagick_coalesceimages|imagick_colorfloodfillimage|imagick_colorizeimage|imagick_combineimages|imagick_commentimage|imagick_compareimagechannels|imagick_compareimagelayers|imagick_compareimages|imagick_compositeimage|imagick_construct|imagick_contrastimage|imagick_contraststretchimage|imagick_convolveimage|imagick_cropimage|imagick_cropthumbnailimage|imagick_current|imagick_cyclecolormapimage|imagick_decipherimage|imagick_deconstructimages|imagick_deleteimageartifact|imagick_despeckleimage|imagick_destroy|imagick_displayimage|imagick_displayimages|imagick_distortimage|imagick_drawimage|imagick_edgeimage|imagick_embossimage|imagick_encipherimage|imagick_enhanceimage|imagick_equalizeimage|imagick_evaluateimage|imagick_extentimage|imagick_flattenimages|imagick_flipimage|imagick_floodfillpaintimage|imagick_flopimage|imagick_frameimage|imagick_fximage|imagick_gammaimage|imagick_gaussianblurimage|imagick_getcolorspace|imagick_getcompression|imagick_getcompressionquality|imagick_getcopyright|imagick_getfilename|imagick_getfont|imagick_getformat|imagick_getgravity|imagick_gethomeurl|imagick_getimage|imagick_getimagealphachannel|imagick_getimageartifact|imagick_getimagebackgroundcolor|imagick_getimageblob|imagick_getimageblueprimary|imagick_getimagebordercolor|imagick_getimagechanneldepth|imagick_getimagechanneldistortion|imagick_getimagechanneldistortions|imagick_getimagechannelextrema|imagick_getimagechannelmean|imagick_getimagechannelrange|imagick_getimagechannelstatistics|imagick_getimageclipmask|imagick_getimagecolormapcolor|imagick_getimagecolors|imagick_getimagecolorspace|imagick_getimagecompose|imagick_getimagecompression|imagick_getimagecompressionquality|imagick_getimagedelay|imagick_getimagedepth|imagick_getimagedispose|imagick_getimagedistortion|imagick_getimageextrema|imagick_getimagefilename|imagick_getimageformat|imagick_getimagegamma|imagick_getimagegeometry|imagick_getimagegravity|imagick_getimagegreenprimary|imagick_getimageheight|imagick_getimagehistogram|imagick_getimageindex|imagick_getimageinterlacescheme|imagick_getimageinterpolatemethod|imagick_getimageiterations|imagick_getimagelength|imagick_getimagemagicklicense|imagick_getimagematte|imagick_getimagemattecolor|imagick_getimageorientation|imagick_getimagepage|imagick_getimagepixelcolor|imagick_getimageprofile|imagick_getimageprofiles|imagick_getimageproperties|imagick_getimageproperty|imagick_getimageredprimary|imagick_getimageregion|imagick_getimagerenderingintent|imagick_getimageresolution|imagick_getimagesblob|imagick_getimagescene|imagick_getimagesignature|imagick_getimagesize|imagick_getimagetickspersecond|imagick_getimagetotalinkdensity|imagick_getimagetype|imagick_getimageunits|imagick_getimagevirtualpixelmethod|imagick_getimagewhitepoint|imagick_getimagewidth|imagick_getinterlacescheme|imagick_getiteratorindex|imagick_getnumberimages|imagick_getoption|imagick_getpackagename|imagick_getpage|imagick_getpixeliterator|imagick_getpixelregioniterator|imagick_getpointsize|imagick_getquantumdepth|imagick_getquantumrange|imagick_getreleasedate|imagick_getresource|imagick_getresourcelimit|imagick_getsamplingfactors|imagick_getsize|imagick_getsizeoffset|imagick_getversion|imagick_hasnextimage|imagick_haspreviousimage|imagick_identifyimage|imagick_implodeimage|imagick_labelimage|imagick_levelimage|imagick_linearstretchimage|imagick_liquidrescaleimage|imagick_magnifyimage|imagick_mapimage|imagick_mattefloodfillimage|imagick_medianfilterimage|imagick_mergeimagelayers|imagick_minifyimage|imagick_modulateimage|imagick_montageimage|imagick_morphimages|imagick_mosaicimages|imagick_motionblurimage|imagick_negateimage|imagick_newimage|imagick_newpseudoimage|imagick_nextimage|imagick_normalizeimage|imagick_oilpaintimage|imagick_opaquepaintimage|imagick_optimizeimagelayers|imagick_orderedposterizeimage|imagick_paintfloodfillimage|imagick_paintopaqueimage|imagick_painttransparentimage|imagick_pingimage|imagick_pingimageblob|imagick_pingimagefile|imagick_polaroidimage|imagick_posterizeimage|imagick_previewimages|imagick_previousimage|imagick_profileimage|imagick_quantizeimage|imagick_quantizeimages|imagick_queryfontmetrics|imagick_queryfonts|imagick_queryformats|imagick_radialblurimage|imagick_raiseimage|imagick_randomthresholdimage|imagick_readimage|imagick_readimageblob|imagick_readimagefile|imagick_recolorimage|imagick_reducenoiseimage|imagick_removeimage|imagick_removeimageprofile|imagick_render|imagick_resampleimage|imagick_resetimagepage|imagick_resizeimage|imagick_rollimage|imagick_rotateimage|imagick_roundcorners|imagick_sampleimage|imagick_scaleimage|imagick_separateimagechannel|imagick_sepiatoneimage|imagick_setbackgroundcolor|imagick_setcolorspace|imagick_setcompression|imagick_setcompressionquality|imagick_setfilename|imagick_setfirstiterator|imagick_setfont|imagick_setformat|imagick_setgravity|imagick_setimage|imagick_setimagealphachannel|imagick_setimageartifact|imagick_setimagebackgroundcolor|imagick_setimagebias|imagick_setimageblueprimary|imagick_setimagebordercolor|imagick_setimagechanneldepth|imagick_setimageclipmask|imagick_setimagecolormapcolor|imagick_setimagecolorspace|imagick_setimagecompose|imagick_setimagecompression|imagick_setimagecompressionquality|imagick_setimagedelay|imagick_setimagedepth|imagick_setimagedispose|imagick_setimageextent|imagick_setimagefilename|imagick_setimageformat|imagick_setimagegamma|imagick_setimagegravity|imagick_setimagegreenprimary|imagick_setimageindex|imagick_setimageinterlacescheme|imagick_setimageinterpolatemethod|imagick_setimageiterations|imagick_setimagematte|imagick_setimagemattecolor|imagick_setimageopacity|imagick_setimageorientation|imagick_setimagepage|imagick_setimageprofile|imagick_setimageproperty|imagick_setimageredprimary|imagick_setimagerenderingintent|imagick_setimageresolution|imagick_setimagescene|imagick_setimagetickspersecond|imagick_setimagetype|imagick_setimageunits|imagick_setimagevirtualpixelmethod|imagick_setimagewhitepoint|imagick_setinterlacescheme|imagick_setiteratorindex|imagick_setlastiterator|imagick_setoption|imagick_setpage|imagick_setpointsize|imagick_setresolution|imagick_setresourcelimit|imagick_setsamplingfactors|imagick_setsize|imagick_setsizeoffset|imagick_settype|imagick_shadeimage|imagick_shadowimage|imagick_sharpenimage|imagick_shaveimage|imagick_shearimage|imagick_sigmoidalcontrastimage|imagick_sketchimage|imagick_solarizeimage|imagick_spliceimage|imagick_spreadimage|imagick_steganoimage|imagick_stereoimage|imagick_stripimage|imagick_swirlimage|imagick_textureimage|imagick_thresholdimage|imagick_thumbnailimage|imagick_tintimage|imagick_transformimage|imagick_transparentpaintimage|imagick_transposeimage|imagick_transverseimage|imagick_trimimage|imagick_uniqueimagecolors|imagick_unsharpmaskimage|imagick_valid|imagick_vignetteimage|imagick_waveimage|imagick_whitethresholdimage|imagick_writeimage|imagick_writeimagefile|imagick_writeimages|imagick_writeimagesfile|imagickdraw|imagickdraw_affine|imagickdraw_annotation|imagickdraw_arc|imagickdraw_bezier|imagickdraw_circle|imagickdraw_clear|imagickdraw_clone|imagickdraw_color|imagickdraw_comment|imagickdraw_composite|imagickdraw_construct|imagickdraw_destroy|imagickdraw_ellipse|imagickdraw_getclippath|imagickdraw_getcliprule|imagickdraw_getclipunits|imagickdraw_getfillcolor|imagickdraw_getfillopacity|imagickdraw_getfillrule|imagickdraw_getfont|imagickdraw_getfontfamily|imagickdraw_getfontsize|imagickdraw_getfontstyle|imagickdraw_getfontweight|imagickdraw_getgravity|imagickdraw_getstrokeantialias|imagickdraw_getstrokecolor|imagickdraw_getstrokedasharray|imagickdraw_getstrokedashoffset|imagickdraw_getstrokelinecap|imagickdraw_getstrokelinejoin|imagickdraw_getstrokemiterlimit|imagickdraw_getstrokeopacity|imagickdraw_getstrokewidth|imagickdraw_gettextalignment|imagickdraw_gettextantialias|imagickdraw_gettextdecoration|imagickdraw_gettextencoding|imagickdraw_gettextundercolor|imagickdraw_getvectorgraphics|imagickdraw_line|imagickdraw_matte|imagickdraw_pathclose|imagickdraw_pathcurvetoabsolute|imagickdraw_pathcurvetoquadraticbezierabsolute|imagickdraw_pathcurvetoquadraticbezierrelative|imagickdraw_pathcurvetoquadraticbeziersmoothabsolute|imagickdraw_pathcurvetoquadraticbeziersmoothrelative|imagickdraw_pathcurvetorelative|imagickdraw_pathcurvetosmoothabsolute|imagickdraw_pathcurvetosmoothrelative|imagickdraw_pathellipticarcabsolute|imagickdraw_pathellipticarcrelative|imagickdraw_pathfinish|imagickdraw_pathlinetoabsolute|imagickdraw_pathlinetohorizontalabsolute|imagickdraw_pathlinetohorizontalrelative|imagickdraw_pathlinetorelative|imagickdraw_pathlinetoverticalabsolute|imagickdraw_pathlinetoverticalrelative|imagickdraw_pathmovetoabsolute|imagickdraw_pathmovetorelative|imagickdraw_pathstart|imagickdraw_point|imagickdraw_polygon|imagickdraw_polyline|imagickdraw_pop|imagickdraw_popclippath|imagickdraw_popdefs|imagickdraw_poppattern|imagickdraw_push|imagickdraw_pushclippath|imagickdraw_pushdefs|imagickdraw_pushpattern|imagickdraw_rectangle|imagickdraw_render|imagickdraw_rotate|imagickdraw_roundrectangle|imagickdraw_scale|imagickdraw_setclippath|imagickdraw_setcliprule|imagickdraw_setclipunits|imagickdraw_setfillalpha|imagickdraw_setfillcolor|imagickdraw_setfillopacity|imagickdraw_setfillpatternurl|imagickdraw_setfillrule|imagickdraw_setfont|imagickdraw_setfontfamily|imagickdraw_setfontsize|imagickdraw_setfontstretch|imagickdraw_setfontstyle|imagickdraw_setfontweight|imagickdraw_setgravity|imagickdraw_setstrokealpha|imagickdraw_setstrokeantialias|imagickdraw_setstrokecolor|imagickdraw_setstrokedasharray|imagickdraw_setstrokedashoffset|imagickdraw_setstrokelinecap|imagickdraw_setstrokelinejoin|imagickdraw_setstrokemiterlimit|imagickdraw_setstrokeopacity|imagickdraw_setstrokepatternurl|imagickdraw_setstrokewidth|imagickdraw_settextalignment|imagickdraw_settextantialias|imagickdraw_settextdecoration|imagickdraw_settextencoding|imagickdraw_settextundercolor|imagickdraw_setvectorgraphics|imagickdraw_setviewbox|imagickdraw_skewx|imagickdraw_skewy|imagickdraw_translate|imagickpixel|imagickpixel_clear|imagickpixel_construct|imagickpixel_destroy|imagickpixel_getcolor|imagickpixel_getcolorasstring|imagickpixel_getcolorcount|imagickpixel_getcolorvalue|imagickpixel_gethsl|imagickpixel_issimilar|imagickpixel_setcolor|imagickpixel_setcolorvalue|imagickpixel_sethsl|imagickpixeliterator|imagickpixeliterator_clear|imagickpixeliterator_construct|imagickpixeliterator_destroy|imagickpixeliterator_getcurrentiteratorrow|imagickpixeliterator_getiteratorrow|imagickpixeliterator_getnextiteratorrow|imagickpixeliterator_getpreviousiteratorrow|imagickpixeliterator_newpixeliterator|imagickpixeliterator_newpixelregioniterator|imagickpixeliterator_resetiterator|imagickpixeliterator_setiteratorfirstrow|imagickpixeliterator_setiteratorlastrow|imagickpixeliterator_setiteratorrow|imagickpixeliterator_synciterator|imap_8bit|imap_alerts|imap_append|imap_base64|imap_binary|imap_body|imap_bodystruct|imap_check|imap_clearflag_full|imap_close|imap_create|imap_createmailbox|imap_delete|imap_deletemailbox|imap_errors|imap_expunge|imap_fetch_overview|imap_fetchbody|imap_fetchheader|imap_fetchmime|imap_fetchstructure|imap_fetchtext|imap_gc|imap_get_quota|imap_get_quotaroot|imap_getacl|imap_getmailboxes|imap_getsubscribed|imap_header|imap_headerinfo|imap_headers|imap_last_error|imap_list|imap_listmailbox|imap_listscan|imap_listsubscribed|imap_lsub|imap_mail|imap_mail_compose|imap_mail_copy|imap_mail_move|imap_mailboxmsginfo|imap_mime_header_decode|imap_msgno|imap_num_msg|imap_num_recent|imap_open|imap_ping|imap_qprint|imap_rename|imap_renamemailbox|imap_reopen|imap_rfc822_parse_adrlist|imap_rfc822_parse_headers|imap_rfc822_write_address|imap_savebody|imap_scan|imap_scanmailbox|imap_search|imap_set_quota|imap_setacl|imap_setflag_full|imap_sort|imap_status|imap_subscribe|imap_thread|imap_timeout|imap_uid|imap_undelete|imap_unsubscribe|imap_utf7_decode|imap_utf7_encode|imap_utf8|implementsinterface|implode|import_request_variables|in_array|include|include_once|inclued_get_data|inet_ntop|inet_pton|infiniteiterator|ingres_autocommit|ingres_autocommit_state|ingres_charset|ingres_close|ingres_commit|ingres_connect|ingres_cursor|ingres_errno|ingres_error|ingres_errsqlstate|ingres_escape_string|ingres_execute|ingres_fetch_array|ingres_fetch_assoc|ingres_fetch_object|ingres_fetch_proc_return|ingres_fetch_row|ingres_field_length|ingres_field_name|ingres_field_nullable|ingres_field_precision|ingres_field_scale|ingres_field_type|ingres_free_result|ingres_next_error|ingres_num_fields|ingres_num_rows|ingres_pconnect|ingres_prepare|ingres_query|ingres_result_seek|ingres_rollback|ingres_set_environment|ingres_unbuffered_query|ini_alter|ini_get|ini_get_all|ini_restore|ini_set|innamespace|inotify_add_watch|inotify_init|inotify_queue_len|inotify_read|inotify_rm_watch|interface_exists|intl_error_name|intl_get_error_code|intl_get_error_message|intl_is_failure|intldateformatter|intval|invalidargumentexception|invoke|invokeargs|ip2long|iptcembed|iptcparse|is_a|is_array|is_bool|is_callable|is_dir|is_double|is_executable|is_file|is_finite|is_float|is_infinite|is_int|is_integer|is_link|is_long|is_nan|is_null|is_numeric|is_object|is_readable|is_real|is_resource|is_scalar|is_soap_fault|is_string|is_subclass_of|is_uploaded_file|is_writable|is_writeable|isabstract|iscloneable|isdisabled|isfinal|isinstance|isinstantiable|isinterface|isinternal|isiterateable|isset|issubclassof|isuserdefined|iterator|iterator_apply|iterator_count|iterator_to_array|iteratoraggregate|iteratoriterator|java_last_exception_clear|java_last_exception_get|jddayofweek|jdmonthname|jdtofrench|jdtogregorian|jdtojewish|jdtojulian|jdtounix|jewishtojd|join|jpeg2wbmp|json_decode|json_encode|json_last_error|jsonserializable|judy|judy_type|judy_version|juliantojd|kadm5_chpass_principal|kadm5_create_principal|kadm5_delete_principal|kadm5_destroy|kadm5_flush|kadm5_get_policies|kadm5_get_principal|kadm5_get_principals|kadm5_init_with_password|kadm5_modify_principal|key|krsort|ksort|lcfirst|lcg_value|lchgrp|lchown|ldap_8859_to_t61|ldap_add|ldap_bind|ldap_close|ldap_compare|ldap_connect|ldap_count_entries|ldap_delete|ldap_dn2ufn|ldap_err2str|ldap_errno|ldap_error|ldap_explode_dn|ldap_first_attribute|ldap_first_entry|ldap_first_reference|ldap_free_result|ldap_get_attributes|ldap_get_dn|ldap_get_entries|ldap_get_option|ldap_get_values|ldap_get_values_len|ldap_list|ldap_mod_add|ldap_mod_del|ldap_mod_replace|ldap_modify|ldap_next_attribute|ldap_next_entry|ldap_next_reference|ldap_parse_reference|ldap_parse_result|ldap_read|ldap_rename|ldap_sasl_bind|ldap_search|ldap_set_option|ldap_set_rebind_proc|ldap_sort|ldap_start_tls|ldap_t61_to_8859|ldap_unbind|lengthexception|levenshtein|libxml_clear_errors|libxml_disable_entity_loader|libxml_get_errors|libxml_get_last_error|libxml_set_streams_context|libxml_use_internal_errors|libxmlerror|limititerator|link|linkinfo|list|locale|localeconv|localtime|log|log10|log1p|logicexception|long2ip|lstat|ltrim|lzf_compress|lzf_decompress|lzf_optimized_for|m_checkstatus|m_completeauthorizations|m_connect|m_connectionerror|m_deletetrans|m_destroyconn|m_destroyengine|m_getcell|m_getcellbynum|m_getcommadelimited|m_getheader|m_initconn|m_initengine|m_iscommadelimited|m_maxconntimeout|m_monitor|m_numcolumns|m_numrows|m_parsecommadelimited|m_responsekeys|m_responseparam|m_returnstatus|m_setblocking|m_setdropfile|m_setip|m_setssl|m_setssl_cafile|m_setssl_files|m_settimeout|m_sslcert_gen_hash|m_transactionssent|m_transinqueue|m_transkeyval|m_transnew|m_transsend|m_uwait|m_validateidentifier|m_verifyconnection|m_verifysslcert|magic_quotes_runtime|mail|mailparse_determine_best_xfer_encoding|mailparse_msg_create|mailparse_msg_extract_part|mailparse_msg_extract_part_file|mailparse_msg_extract_whole_part_file|mailparse_msg_free|mailparse_msg_get_part|mailparse_msg_get_part_data|mailparse_msg_get_structure|mailparse_msg_parse|mailparse_msg_parse_file|mailparse_rfc822_parse_addresses|mailparse_stream_encode|mailparse_uudecode_all|main|max|maxdb_affected_rows|maxdb_autocommit|maxdb_bind_param|maxdb_bind_result|maxdb_change_user|maxdb_character_set_name|maxdb_client_encoding|maxdb_close|maxdb_close_long_data|maxdb_commit|maxdb_connect|maxdb_connect_errno|maxdb_connect_error|maxdb_data_seek|maxdb_debug|maxdb_disable_reads_from_master|maxdb_disable_rpl_parse|maxdb_dump_debug_info|maxdb_embedded_connect|maxdb_enable_reads_from_master|maxdb_enable_rpl_parse|maxdb_errno|maxdb_error|maxdb_escape_string|maxdb_execute|maxdb_fetch|maxdb_fetch_array|maxdb_fetch_assoc|maxdb_fetch_field|maxdb_fetch_field_direct|maxdb_fetch_fields|maxdb_fetch_lengths|maxdb_fetch_object|maxdb_fetch_row|maxdb_field_count|maxdb_field_seek|maxdb_field_tell|maxdb_free_result|maxdb_get_client_info|maxdb_get_client_version|maxdb_get_host_info|maxdb_get_metadata|maxdb_get_proto_info|maxdb_get_server_info|maxdb_get_server_version|maxdb_info|maxdb_init|maxdb_insert_id|maxdb_kill|maxdb_master_query|maxdb_more_results|maxdb_multi_query|maxdb_next_result|maxdb_num_fields|maxdb_num_rows|maxdb_options|maxdb_param_count|maxdb_ping|maxdb_prepare|maxdb_query|maxdb_real_connect|maxdb_real_escape_string|maxdb_real_query|maxdb_report|maxdb_rollback|maxdb_rpl_parse_enabled|maxdb_rpl_probe|maxdb_rpl_query_type|maxdb_select_db|maxdb_send_long_data|maxdb_send_query|maxdb_server_end|maxdb_server_init|maxdb_set_opt|maxdb_sqlstate|maxdb_ssl_set|maxdb_stat|maxdb_stmt_affected_rows|maxdb_stmt_bind_param|maxdb_stmt_bind_result|maxdb_stmt_close|maxdb_stmt_close_long_data|maxdb_stmt_data_seek|maxdb_stmt_errno|maxdb_stmt_error|maxdb_stmt_execute|maxdb_stmt_fetch|maxdb_stmt_free_result|maxdb_stmt_init|maxdb_stmt_num_rows|maxdb_stmt_param_count|maxdb_stmt_prepare|maxdb_stmt_reset|maxdb_stmt_result_metadata|maxdb_stmt_send_long_data|maxdb_stmt_sqlstate|maxdb_stmt_store_result|maxdb_store_result|maxdb_thread_id|maxdb_thread_safe|maxdb_use_result|maxdb_warning_count|mb_check_encoding|mb_convert_case|mb_convert_encoding|mb_convert_kana|mb_convert_variables|mb_decode_mimeheader|mb_decode_numericentity|mb_detect_encoding|mb_detect_order|mb_encode_mimeheader|mb_encode_numericentity|mb_encoding_aliases|mb_ereg|mb_ereg_match|mb_ereg_replace|mb_ereg_search|mb_ereg_search_getpos|mb_ereg_search_getregs|mb_ereg_search_init|mb_ereg_search_pos|mb_ereg_search_regs|mb_ereg_search_setpos|mb_eregi|mb_eregi_replace|mb_get_info|mb_http_input|mb_http_output|mb_internal_encoding|mb_language|mb_list_encodings|mb_output_handler|mb_parse_str|mb_preferred_mime_name|mb_regex_encoding|mb_regex_set_options|mb_send_mail|mb_split|mb_strcut|mb_strimwidth|mb_stripos|mb_stristr|mb_strlen|mb_strpos|mb_strrchr|mb_strrichr|mb_strripos|mb_strrpos|mb_strstr|mb_strtolower|mb_strtoupper|mb_strwidth|mb_substitute_character|mb_substr|mb_substr_count|mcrypt_cbc|mcrypt_cfb|mcrypt_create_iv|mcrypt_decrypt|mcrypt_ecb|mcrypt_enc_get_algorithms_name|mcrypt_enc_get_block_size|mcrypt_enc_get_iv_size|mcrypt_enc_get_key_size|mcrypt_enc_get_modes_name|mcrypt_enc_get_supported_key_sizes|mcrypt_enc_is_block_algorithm|mcrypt_enc_is_block_algorithm_mode|mcrypt_enc_is_block_mode|mcrypt_enc_self_test|mcrypt_encrypt|mcrypt_generic|mcrypt_generic_deinit|mcrypt_generic_end|mcrypt_generic_init|mcrypt_get_block_size|mcrypt_get_cipher_name|mcrypt_get_iv_size|mcrypt_get_key_size|mcrypt_list_algorithms|mcrypt_list_modes|mcrypt_module_close|mcrypt_module_get_algo_block_size|mcrypt_module_get_algo_key_size|mcrypt_module_get_supported_key_sizes|mcrypt_module_is_block_algorithm|mcrypt_module_is_block_algorithm_mode|mcrypt_module_is_block_mode|mcrypt_module_open|mcrypt_module_self_test|mcrypt_ofb|md5|md5_file|mdecrypt_generic|memcache|memcache_debug|memcached|memory_get_peak_usage|memory_get_usage|messageformatter|metaphone|method_exists|mhash|mhash_count|mhash_get_block_size|mhash_get_hash_name|mhash_keygen_s2k|microtime|mime_content_type|min|ming_keypress|ming_setcubicthreshold|ming_setscale|ming_setswfcompression|ming_useconstants|ming_useswfversion|mkdir|mktime|money_format|mongo|mongobindata|mongocode|mongocollection|mongoconnectionexception|mongocursor|mongocursorexception|mongocursortimeoutexception|mongodate|mongodb|mongodbref|mongoexception|mongogridfs|mongogridfscursor|mongogridfsexception|mongogridfsfile|mongoid|mongoint32|mongoint64|mongomaxkey|mongominkey|mongoregex|mongotimestamp|move_uploaded_file|mpegfile|mqseries_back|mqseries_begin|mqseries_close|mqseries_cmit|mqseries_conn|mqseries_connx|mqseries_disc|mqseries_get|mqseries_inq|mqseries_open|mqseries_put|mqseries_put1|mqseries_set|mqseries_strerror|msession_connect|msession_count|msession_create|msession_destroy|msession_disconnect|msession_find|msession_get|msession_get_array|msession_get_data|msession_inc|msession_list|msession_listvar|msession_lock|msession_plugin|msession_randstr|msession_set|msession_set_array|msession_set_data|msession_timeout|msession_uniq|msession_unlock|msg_get_queue|msg_queue_exists|msg_receive|msg_remove_queue|msg_send|msg_set_queue|msg_stat_queue|msql|msql_affected_rows|msql_close|msql_connect|msql_create_db|msql_createdb|msql_data_seek|msql_db_query|msql_dbname|msql_drop_db|msql_error|msql_fetch_array|msql_fetch_field|msql_fetch_object|msql_fetch_row|msql_field_flags|msql_field_len|msql_field_name|msql_field_seek|msql_field_table|msql_field_type|msql_fieldflags|msql_fieldlen|msql_fieldname|msql_fieldtable|msql_fieldtype|msql_free_result|msql_list_dbs|msql_list_fields|msql_list_tables|msql_num_fields|msql_num_rows|msql_numfields|msql_numrows|msql_pconnect|msql_query|msql_regcase|msql_result|msql_select_db|msql_tablename|mssql_bind|mssql_close|mssql_connect|mssql_data_seek|mssql_execute|mssql_fetch_array|mssql_fetch_assoc|mssql_fetch_batch|mssql_fetch_field|mssql_fetch_object|mssql_fetch_row|mssql_field_length|mssql_field_name|mssql_field_seek|mssql_field_type|mssql_free_result|mssql_free_statement|mssql_get_last_message|mssql_guid_string|mssql_init|mssql_min_error_severity|mssql_min_message_severity|mssql_next_result|mssql_num_fields|mssql_num_rows|mssql_pconnect|mssql_query|mssql_result|mssql_rows_affected|mssql_select_db|mt_getrandmax|mt_rand|mt_srand|multipleiterator|mysql_affected_rows|mysql_client_encoding|mysql_close|mysql_connect|mysql_create_db|mysql_data_seek|mysql_db_name|mysql_db_query|mysql_drop_db|mysql_errno|mysql_error|mysql_escape_string|mysql_fetch_array|mysql_fetch_assoc|mysql_fetch_field|mysql_fetch_lengths|mysql_fetch_object|mysql_fetch_row|mysql_field_flags|mysql_field_len|mysql_field_name|mysql_field_seek|mysql_field_table|mysql_field_type|mysql_free_result|mysql_get_client_info|mysql_get_host_info|mysql_get_proto_info|mysql_get_server_info|mysql_info|mysql_insert_id|mysql_list_dbs|mysql_list_fields|mysql_list_processes|mysql_list_tables|mysql_num_fields|mysql_num_rows|mysql_pconnect|mysql_ping|mysql_query|mysql_real_escape_string|mysql_result|mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_bind_param|mysqli_bind_result|mysqli_client_encoding|mysqli_connect|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_escape_string|mysqli_execute|mysqli_fetch|mysqli_get_metadata|mysqli_master_query|mysqli_param_count|mysqli_report|mysqli_result|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_send_long_data|mysqli_send_query|mysqli_set_opt|mysqli_slave_query|mysqli_stmt|mysqli_warning|mysqlnd_ms_get_stats|mysqlnd_ms_query_is_select|mysqlnd_ms_set_user_pick_server|mysqlnd_qc_change_handler|mysqlnd_qc_clear_cache|mysqlnd_qc_get_cache_info|mysqlnd_qc_get_core_stats|mysqlnd_qc_get_handler|mysqlnd_qc_get_query_trace_log|mysqlnd_qc_set_user_handlers|natcasesort|natsort|ncurses_addch|ncurses_addchnstr|ncurses_addchstr|ncurses_addnstr|ncurses_addstr|ncurses_assume_default_colors|ncurses_attroff|ncurses_attron|ncurses_attrset|ncurses_baudrate|ncurses_beep|ncurses_bkgd|ncurses_bkgdset|ncurses_border|ncurses_bottom_panel|ncurses_can_change_color|ncurses_cbreak|ncurses_clear|ncurses_clrtobot|ncurses_clrtoeol|ncurses_color_content|ncurses_color_set|ncurses_curs_set|ncurses_def_prog_mode|ncurses_def_shell_mode|ncurses_define_key|ncurses_del_panel|ncurses_delay_output|ncurses_delch|ncurses_deleteln|ncurses_delwin|ncurses_doupdate|ncurses_echo|ncurses_echochar|ncurses_end|ncurses_erase|ncurses_erasechar|ncurses_filter|ncurses_flash|ncurses_flushinp|ncurses_getch|ncurses_getmaxyx|ncurses_getmouse|ncurses_getyx|ncurses_halfdelay|ncurses_has_colors|ncurses_has_ic|ncurses_has_il|ncurses_has_key|ncurses_hide_panel|ncurses_hline|ncurses_inch|ncurses_init|ncurses_init_color|ncurses_init_pair|ncurses_insch|ncurses_insdelln|ncurses_insertln|ncurses_insstr|ncurses_instr|ncurses_isendwin|ncurses_keyok|ncurses_keypad|ncurses_killchar|ncurses_longname|ncurses_meta|ncurses_mouse_trafo|ncurses_mouseinterval|ncurses_mousemask|ncurses_move|ncurses_move_panel|ncurses_mvaddch|ncurses_mvaddchnstr|ncurses_mvaddchstr|ncurses_mvaddnstr|ncurses_mvaddstr|ncurses_mvcur|ncurses_mvdelch|ncurses_mvgetch|ncurses_mvhline|ncurses_mvinch|ncurses_mvvline|ncurses_mvwaddstr|ncurses_napms|ncurses_new_panel|ncurses_newpad|ncurses_newwin|ncurses_nl|ncurses_nocbreak|ncurses_noecho|ncurses_nonl|ncurses_noqiflush|ncurses_noraw|ncurses_pair_content|ncurses_panel_above|ncurses_panel_below|ncurses_panel_window|ncurses_pnoutrefresh|ncurses_prefresh|ncurses_putp|ncurses_qiflush|ncurses_raw|ncurses_refresh|ncurses_replace_panel|ncurses_reset_prog_mode|ncurses_reset_shell_mode|ncurses_resetty|ncurses_savetty|ncurses_scr_dump|ncurses_scr_init|ncurses_scr_restore|ncurses_scr_set|ncurses_scrl|ncurses_show_panel|ncurses_slk_attr|ncurses_slk_attroff|ncurses_slk_attron|ncurses_slk_attrset|ncurses_slk_clear|ncurses_slk_color|ncurses_slk_init|ncurses_slk_noutrefresh|ncurses_slk_refresh|ncurses_slk_restore|ncurses_slk_set|ncurses_slk_touch|ncurses_standend|ncurses_standout|ncurses_start_color|ncurses_termattrs|ncurses_termname|ncurses_timeout|ncurses_top_panel|ncurses_typeahead|ncurses_ungetch|ncurses_ungetmouse|ncurses_update_panels|ncurses_use_default_colors|ncurses_use_env|ncurses_use_extended_names|ncurses_vidattr|ncurses_vline|ncurses_waddch|ncurses_waddstr|ncurses_wattroff|ncurses_wattron|ncurses_wattrset|ncurses_wborder|ncurses_wclear|ncurses_wcolor_set|ncurses_werase|ncurses_wgetch|ncurses_whline|ncurses_wmouse_trafo|ncurses_wmove|ncurses_wnoutrefresh|ncurses_wrefresh|ncurses_wstandend|ncurses_wstandout|ncurses_wvline|newinstance|newinstanceargs|newt_bell|newt_button|newt_button_bar|newt_centered_window|newt_checkbox|newt_checkbox_get_value|newt_checkbox_set_flags|newt_checkbox_set_value|newt_checkbox_tree|newt_checkbox_tree_add_item|newt_checkbox_tree_find_item|newt_checkbox_tree_get_current|newt_checkbox_tree_get_entry_value|newt_checkbox_tree_get_multi_selection|newt_checkbox_tree_get_selection|newt_checkbox_tree_multi|newt_checkbox_tree_set_current|newt_checkbox_tree_set_entry|newt_checkbox_tree_set_entry_value|newt_checkbox_tree_set_width|newt_clear_key_buffer|newt_cls|newt_compact_button|newt_component_add_callback|newt_component_takes_focus|newt_create_grid|newt_cursor_off|newt_cursor_on|newt_delay|newt_draw_form|newt_draw_root_text|newt_entry|newt_entry_get_value|newt_entry_set|newt_entry_set_filter|newt_entry_set_flags|newt_finished|newt_form|newt_form_add_component|newt_form_add_components|newt_form_add_hot_key|newt_form_destroy|newt_form_get_current|newt_form_run|newt_form_set_background|newt_form_set_height|newt_form_set_size|newt_form_set_timer|newt_form_set_width|newt_form_watch_fd|newt_get_screen_size|newt_grid_add_components_to_form|newt_grid_basic_window|newt_grid_free|newt_grid_get_size|newt_grid_h_close_stacked|newt_grid_h_stacked|newt_grid_place|newt_grid_set_field|newt_grid_simple_window|newt_grid_v_close_stacked|newt_grid_v_stacked|newt_grid_wrapped_window|newt_grid_wrapped_window_at|newt_init|newt_label|newt_label_set_text|newt_listbox|newt_listbox_append_entry|newt_listbox_clear|newt_listbox_clear_selection|newt_listbox_delete_entry|newt_listbox_get_current|newt_listbox_get_selection|newt_listbox_insert_entry|newt_listbox_item_count|newt_listbox_select_item|newt_listbox_set_current|newt_listbox_set_current_by_key|newt_listbox_set_data|newt_listbox_set_entry|newt_listbox_set_width|newt_listitem|newt_listitem_get_data|newt_listitem_set|newt_open_window|newt_pop_help_line|newt_pop_window|newt_push_help_line|newt_radio_get_current|newt_radiobutton|newt_redraw_help_line|newt_reflow_text|newt_refresh|newt_resize_screen|newt_resume|newt_run_form|newt_scale|newt_scale_set|newt_scrollbar_set|newt_set_help_callback|newt_set_suspend_callback|newt_suspend|newt_textbox|newt_textbox_get_num_lines|newt_textbox_reflowed|newt_textbox_set_height|newt_textbox_set_text|newt_vertical_scrollbar|newt_wait_for_key|newt_win_choice|newt_win_entries|newt_win_menu|newt_win_message|newt_win_messagev|newt_win_ternary|next|ngettext|nl2br|nl_langinfo|norewinditerator|normalizer|notes_body|notes_copy_db|notes_create_db|notes_create_note|notes_drop_db|notes_find_note|notes_header_info|notes_list_msgs|notes_mark_read|notes_mark_unread|notes_nav_create|notes_search|notes_unread|notes_version|nsapi_request_headers|nsapi_response_headers|nsapi_virtual|nthmac|number_format|numberformatter|oauth|oauth_get_sbs|oauth_urlencode|oauthexception|oauthprovider|ob_clean|ob_deflatehandler|ob_end_clean|ob_end_flush|ob_etaghandler|ob_flush|ob_get_clean|ob_get_contents|ob_get_flush|ob_get_length|ob_get_level|ob_get_status|ob_gzhandler|ob_iconv_handler|ob_implicit_flush|ob_inflatehandler|ob_list_handlers|ob_start|ob_tidyhandler|oci_bind_array_by_name|oci_bind_by_name|oci_cancel|oci_client_version|oci_close|oci_collection_append|oci_collection_assign|oci_collection_element_assign|oci_collection_element_get|oci_collection_free|oci_collection_max|oci_collection_size|oci_collection_trim|oci_commit|oci_connect|oci_define_by_name|oci_error|oci_execute|oci_fetch|oci_fetch_all|oci_fetch_array|oci_fetch_assoc|oci_fetch_object|oci_fetch_row|oci_field_is_null|oci_field_name|oci_field_precision|oci_field_scale|oci_field_size|oci_field_type|oci_field_type_raw|oci_free_statement|oci_internal_debug|oci_lob_append|oci_lob_close|oci_lob_copy|oci_lob_eof|oci_lob_erase|oci_lob_export|oci_lob_flush|oci_lob_free|oci_lob_getbuffering|oci_lob_import|oci_lob_is_equal|oci_lob_load|oci_lob_read|oci_lob_rewind|oci_lob_save|oci_lob_savefile|oci_lob_seek|oci_lob_setbuffering|oci_lob_size|oci_lob_tell|oci_lob_truncate|oci_lob_write|oci_lob_writetemporary|oci_lob_writetofile|oci_new_collection|oci_new_connect|oci_new_cursor|oci_new_descriptor|oci_num_fields|oci_num_rows|oci_parse|oci_password_change|oci_pconnect|oci_result|oci_rollback|oci_server_version|oci_set_action|oci_set_client_identifier|oci_set_client_info|oci_set_edition|oci_set_module_name|oci_set_prefetch|oci_statement_type|ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|ociloadlob|ocilogoff|ocilogon|ocinewcollection|ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|ocirollback|ocirowcount|ocisavelob|ocisavelobfile|ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|octdec|odbc_autocommit|odbc_binmode|odbc_close|odbc_close_all|odbc_columnprivileges|odbc_columns|odbc_commit|odbc_connect|odbc_cursor|odbc_data_source|odbc_do|odbc_error|odbc_errormsg|odbc_exec|odbc_execute|odbc_fetch_array|odbc_fetch_into|odbc_fetch_object|odbc_fetch_row|odbc_field_len|odbc_field_name|odbc_field_num|odbc_field_precision|odbc_field_scale|odbc_field_type|odbc_foreignkeys|odbc_free_result|odbc_gettypeinfo|odbc_longreadlen|odbc_next_result|odbc_num_fields|odbc_num_rows|odbc_pconnect|odbc_prepare|odbc_primarykeys|odbc_procedurecolumns|odbc_procedures|odbc_result|odbc_result_all|odbc_rollback|odbc_setoption|odbc_specialcolumns|odbc_statistics|odbc_tableprivileges|odbc_tables|openal_buffer_create|openal_buffer_data|openal_buffer_destroy|openal_buffer_get|openal_buffer_loadwav|openal_context_create|openal_context_current|openal_context_destroy|openal_context_process|openal_context_suspend|openal_device_close|openal_device_open|openal_listener_get|openal_listener_set|openal_source_create|openal_source_destroy|openal_source_get|openal_source_pause|openal_source_play|openal_source_rewind|openal_source_set|openal_source_stop|openal_stream|opendir|openlog|openssl_cipher_iv_length|openssl_csr_export|openssl_csr_export_to_file|openssl_csr_get_public_key|openssl_csr_get_subject|openssl_csr_new|openssl_csr_sign|openssl_decrypt|openssl_dh_compute_key|openssl_digest|openssl_encrypt|openssl_error_string|openssl_free_key|openssl_get_cipher_methods|openssl_get_md_methods|openssl_get_privatekey|openssl_get_publickey|openssl_open|openssl_pkcs12_export|openssl_pkcs12_export_to_file|openssl_pkcs12_read|openssl_pkcs7_decrypt|openssl_pkcs7_encrypt|openssl_pkcs7_sign|openssl_pkcs7_verify|openssl_pkey_export|openssl_pkey_export_to_file|openssl_pkey_free|openssl_pkey_get_details|openssl_pkey_get_private|openssl_pkey_get_public|openssl_pkey_new|openssl_private_decrypt|openssl_private_encrypt|openssl_public_decrypt|openssl_public_encrypt|openssl_random_pseudo_bytes|openssl_seal|openssl_sign|openssl_verify|openssl_x509_check_private_key|openssl_x509_checkpurpose|openssl_x509_export|openssl_x509_export_to_file|openssl_x509_free|openssl_x509_parse|openssl_x509_read|ord|outeriterator|outofboundsexception|outofrangeexception|output_add_rewrite_var|output_reset_rewrite_vars|overflowexception|overload|override_function|ovrimos_close|ovrimos_commit|ovrimos_connect|ovrimos_cursor|ovrimos_exec|ovrimos_execute|ovrimos_fetch_into|ovrimos_fetch_row|ovrimos_field_len|ovrimos_field_name|ovrimos_field_num|ovrimos_field_type|ovrimos_free_result|ovrimos_longreadlen|ovrimos_num_fields|ovrimos_num_rows|ovrimos_prepare|ovrimos_result|ovrimos_result_all|ovrimos_rollback|pack|parentiterator|parse_ini_file|parse_ini_string|parse_str|parse_url|parsekit_compile_file|parsekit_compile_string|parsekit_func_arginfo|passthru|pathinfo|pclose|pcntl_alarm|pcntl_exec|pcntl_fork|pcntl_getpriority|pcntl_setpriority|pcntl_signal|pcntl_signal_dispatch|pcntl_sigprocmask|pcntl_sigtimedwait|pcntl_sigwaitinfo|pcntl_wait|pcntl_waitpid|pcntl_wexitstatus|pcntl_wifexited|pcntl_wifsignaled|pcntl_wifstopped|pcntl_wstopsig|pcntl_wtermsig|pdf_activate_item|pdf_add_annotation|pdf_add_bookmark|pdf_add_launchlink|pdf_add_locallink|pdf_add_nameddest|pdf_add_note|pdf_add_outline|pdf_add_pdflink|pdf_add_table_cell|pdf_add_textflow|pdf_add_thumbnail|pdf_add_weblink|pdf_arc|pdf_arcn|pdf_attach_file|pdf_begin_document|pdf_begin_font|pdf_begin_glyph|pdf_begin_item|pdf_begin_layer|pdf_begin_page|pdf_begin_page_ext|pdf_begin_pattern|pdf_begin_template|pdf_begin_template_ext|pdf_circle|pdf_clip|pdf_close|pdf_close_image|pdf_close_pdi|pdf_close_pdi_page|pdf_closepath|pdf_closepath_fill_stroke|pdf_closepath_stroke|pdf_concat|pdf_continue_text|pdf_create_3dview|pdf_create_action|pdf_create_annotation|pdf_create_bookmark|pdf_create_field|pdf_create_fieldgroup|pdf_create_gstate|pdf_create_pvf|pdf_create_textflow|pdf_curveto|pdf_define_layer|pdf_delete|pdf_delete_pvf|pdf_delete_table|pdf_delete_textflow|pdf_encoding_set_char|pdf_end_document|pdf_end_font|pdf_end_glyph|pdf_end_item|pdf_end_layer|pdf_end_page|pdf_end_page_ext|pdf_end_pattern|pdf_end_template|pdf_endpath|pdf_fill|pdf_fill_imageblock|pdf_fill_pdfblock|pdf_fill_stroke|pdf_fill_textblock|pdf_findfont|pdf_fit_image|pdf_fit_pdi_page|pdf_fit_table|pdf_fit_textflow|pdf_fit_textline|pdf_get_apiname|pdf_get_buffer|pdf_get_errmsg|pdf_get_errnum|pdf_get_font|pdf_get_fontname|pdf_get_fontsize|pdf_get_image_height|pdf_get_image_width|pdf_get_majorversion|pdf_get_minorversion|pdf_get_parameter|pdf_get_pdi_parameter|pdf_get_pdi_value|pdf_get_value|pdf_info_font|pdf_info_matchbox|pdf_info_table|pdf_info_textflow|pdf_info_textline|pdf_initgraphics|pdf_lineto|pdf_load_3ddata|pdf_load_font|pdf_load_iccprofile|pdf_load_image|pdf_makespotcolor|pdf_moveto|pdf_new|pdf_open_ccitt|pdf_open_file|pdf_open_gif|pdf_open_image|pdf_open_image_file|pdf_open_jpeg|pdf_open_memory_image|pdf_open_pdi|pdf_open_pdi_document|pdf_open_pdi_page|pdf_open_tiff|pdf_pcos_get_number|pdf_pcos_get_stream|pdf_pcos_get_string|pdf_place_image|pdf_place_pdi_page|pdf_process_pdi|pdf_rect|pdf_restore|pdf_resume_page|pdf_rotate|pdf_save|pdf_scale|pdf_set_border_color|pdf_set_border_dash|pdf_set_border_style|pdf_set_char_spacing|pdf_set_duration|pdf_set_gstate|pdf_set_horiz_scaling|pdf_set_info|pdf_set_info_author|pdf_set_info_creator|pdf_set_info_keywords|pdf_set_info_subject|pdf_set_info_title|pdf_set_layer_dependency|pdf_set_leading|pdf_set_parameter|pdf_set_text_matrix|pdf_set_text_pos|pdf_set_text_rendering|pdf_set_text_rise|pdf_set_value|pdf_set_word_spacing|pdf_setcolor|pdf_setdash|pdf_setdashpattern|pdf_setflat|pdf_setfont|pdf_setgray|pdf_setgray_fill|pdf_setgray_stroke|pdf_setlinecap|pdf_setlinejoin|pdf_setlinewidth|pdf_setmatrix|pdf_setmiterlimit|pdf_setpolydash|pdf_setrgbcolor|pdf_setrgbcolor_fill|pdf_setrgbcolor_stroke|pdf_shading|pdf_shading_pattern|pdf_shfill|pdf_show|pdf_show_boxed|pdf_show_xy|pdf_skew|pdf_stringwidth|pdf_stroke|pdf_suspend_page|pdf_translate|pdf_utf16_to_utf8|pdf_utf32_to_utf16|pdf_utf8_to_utf16|pdo|pdo_cubrid_schema|pdo_pgsqllobcreate|pdo_pgsqllobopen|pdo_pgsqllobunlink|pdo_sqlitecreateaggregate|pdo_sqlitecreatefunction|pdoexception|pdostatement|pfsockopen|pg_affected_rows|pg_cancel_query|pg_client_encoding|pg_close|pg_connect|pg_connection_busy|pg_connection_reset|pg_connection_status|pg_convert|pg_copy_from|pg_copy_to|pg_dbname|pg_delete|pg_end_copy|pg_escape_bytea|pg_escape_string|pg_execute|pg_fetch_all|pg_fetch_all_columns|pg_fetch_array|pg_fetch_assoc|pg_fetch_object|pg_fetch_result|pg_fetch_row|pg_field_is_null|pg_field_name|pg_field_num|pg_field_prtlen|pg_field_size|pg_field_table|pg_field_type|pg_field_type_oid|pg_free_result|pg_get_notify|pg_get_pid|pg_get_result|pg_host|pg_insert|pg_last_error|pg_last_notice|pg_last_oid|pg_lo_close|pg_lo_create|pg_lo_export|pg_lo_import|pg_lo_open|pg_lo_read|pg_lo_read_all|pg_lo_seek|pg_lo_tell|pg_lo_unlink|pg_lo_write|pg_meta_data|pg_num_fields|pg_num_rows|pg_options|pg_parameter_status|pg_pconnect|pg_ping|pg_port|pg_prepare|pg_put_line|pg_query|pg_query_params|pg_result_error|pg_result_error_field|pg_result_seek|pg_result_status|pg_select|pg_send_execute|pg_send_prepare|pg_send_query|pg_send_query_params|pg_set_client_encoding|pg_set_error_verbosity|pg_trace|pg_transaction_status|pg_tty|pg_unescape_bytea|pg_untrace|pg_update|pg_version|php_check_syntax|php_ini_loaded_file|php_ini_scanned_files|php_logo_guid|php_sapi_name|php_strip_whitespace|php_uname|phpcredits|phpinfo|phpversion|pi|png2wbmp|popen|pos|posix_access|posix_ctermid|posix_errno|posix_get_last_error|posix_getcwd|posix_getegid|posix_geteuid|posix_getgid|posix_getgrgid|posix_getgrnam|posix_getgroups|posix_getlogin|posix_getpgid|posix_getpgrp|posix_getpid|posix_getppid|posix_getpwnam|posix_getpwuid|posix_getrlimit|posix_getsid|posix_getuid|posix_initgroups|posix_isatty|posix_kill|posix_mkfifo|posix_mknod|posix_setegid|posix_seteuid|posix_setgid|posix_setpgid|posix_setsid|posix_setuid|posix_strerror|posix_times|posix_ttyname|posix_uname|pow|preg_filter|preg_grep|preg_last_error|preg_match|preg_match_all|preg_quote|preg_replace|preg_replace_callback|preg_split|prev|print|print_r|printer_abort|printer_close|printer_create_brush|printer_create_dc|printer_create_font|printer_create_pen|printer_delete_brush|printer_delete_dc|printer_delete_font|printer_delete_pen|printer_draw_bmp|printer_draw_chord|printer_draw_elipse|printer_draw_line|printer_draw_pie|printer_draw_rectangle|printer_draw_roundrect|printer_draw_text|printer_end_doc|printer_end_page|printer_get_option|printer_list|printer_logical_fontheight|printer_open|printer_select_brush|printer_select_font|printer_select_pen|printer_set_option|printer_start_doc|printer_start_page|printer_write|printf|proc_close|proc_get_status|proc_nice|proc_open|proc_terminate|property_exists|ps_add_bookmark|ps_add_launchlink|ps_add_locallink|ps_add_note|ps_add_pdflink|ps_add_weblink|ps_arc|ps_arcn|ps_begin_page|ps_begin_pattern|ps_begin_template|ps_circle|ps_clip|ps_close|ps_close_image|ps_closepath|ps_closepath_stroke|ps_continue_text|ps_curveto|ps_delete|ps_end_page|ps_end_pattern|ps_end_template|ps_fill|ps_fill_stroke|ps_findfont|ps_get_buffer|ps_get_parameter|ps_get_value|ps_hyphenate|ps_include_file|ps_lineto|ps_makespotcolor|ps_moveto|ps_new|ps_open_file|ps_open_image|ps_open_image_file|ps_open_memory_image|ps_place_image|ps_rect|ps_restore|ps_rotate|ps_save|ps_scale|ps_set_border_color|ps_set_border_dash|ps_set_border_style|ps_set_info|ps_set_parameter|ps_set_text_pos|ps_set_value|ps_setcolor|ps_setdash|ps_setflat|ps_setfont|ps_setgray|ps_setlinecap|ps_setlinejoin|ps_setlinewidth|ps_setmiterlimit|ps_setoverprintmode|ps_setpolydash|ps_shading|ps_shading_pattern|ps_shfill|ps_show|ps_show2|ps_show_boxed|ps_show_xy|ps_show_xy2|ps_string_geometry|ps_stringwidth|ps_stroke|ps_symbol|ps_symbol_name|ps_symbol_width|ps_translate|pspell_add_to_personal|pspell_add_to_session|pspell_check|pspell_clear_session|pspell_config_create|pspell_config_data_dir|pspell_config_dict_dir|pspell_config_ignore|pspell_config_mode|pspell_config_personal|pspell_config_repl|pspell_config_runtogether|pspell_config_save_repl|pspell_new|pspell_new_config|pspell_new_personal|pspell_save_wordlist|pspell_store_replacement|pspell_suggest|putenv|px_close|px_create_fp|px_date2string|px_delete|px_delete_record|px_get_field|px_get_info|px_get_parameter|px_get_record|px_get_schema|px_get_value|px_insert_record|px_new|px_numfields|px_numrecords|px_open_fp|px_put_record|px_retrieve_record|px_set_blob_file|px_set_parameter|px_set_tablename|px_set_targetencoding|px_set_value|px_timestamp2string|px_update_record|qdom_error|qdom_tree|quoted_printable_decode|quoted_printable_encode|quotemeta|rad2deg|radius_acct_open|radius_add_server|radius_auth_open|radius_close|radius_config|radius_create_request|radius_cvt_addr|radius_cvt_int|radius_cvt_string|radius_demangle|radius_demangle_mppe_key|radius_get_attr|radius_get_vendor_attr|radius_put_addr|radius_put_attr|radius_put_int|radius_put_string|radius_put_vendor_addr|radius_put_vendor_attr|radius_put_vendor_int|radius_put_vendor_string|radius_request_authenticator|radius_send_request|radius_server_secret|radius_strerror|rand|range|rangeexception|rar_wrapper_cache_stats|rararchive|rarentry|rarexception|rawurldecode|rawurlencode|read_exif_data|readdir|readfile|readgzfile|readline|readline_add_history|readline_callback_handler_install|readline_callback_handler_remove|readline_callback_read_char|readline_clear_history|readline_completion_function|readline_info|readline_list_history|readline_on_new_line|readline_read_history|readline_redisplay|readline_write_history|readlink|realpath|realpath_cache_get|realpath_cache_size|recode|recode_file|recode_string|recursivearrayiterator|recursivecachingiterator|recursivecallbackfilteriterator|recursivedirectoryiterator|recursivefilteriterator|recursiveiterator|recursiveiteratoriterator|recursiveregexiterator|recursivetreeiterator|reflection|reflectionclass|reflectionexception|reflectionextension|reflectionfunction|reflectionfunctionabstract|reflectionmethod|reflectionobject|reflectionparameter|reflectionproperty|reflector|regexiterator|register_shutdown_function|register_tick_function|rename|rename_function|require|require_once|reset|resetValue|resourcebundle|restore_error_handler|restore_exception_handler|restore_include_path|return|rewind|rewinddir|rmdir|round|rpm_close|rpm_get_tag|rpm_is_valid|rpm_open|rpm_version|rrd_create|rrd_error|rrd_fetch|rrd_first|rrd_graph|rrd_info|rrd_last|rrd_lastupdate|rrd_restore|rrd_tune|rrd_update|rrd_xport|rrdcreator|rrdgraph|rrdupdater|rsort|rtrim|runkit_class_adopt|runkit_class_emancipate|runkit_constant_add|runkit_constant_redefine|runkit_constant_remove|runkit_function_add|runkit_function_copy|runkit_function_redefine|runkit_function_remove|runkit_function_rename|runkit_import|runkit_lint|runkit_lint_file|runkit_method_add|runkit_method_copy|runkit_method_redefine|runkit_method_remove|runkit_method_rename|runkit_return_value_used|runkit_sandbox_output_handler|runkit_superglobals|runtimeexception|samconnection_commit|samconnection_connect|samconnection_constructor|samconnection_disconnect|samconnection_errno|samconnection_error|samconnection_isconnected|samconnection_peek|samconnection_peekall|samconnection_receive|samconnection_remove|samconnection_rollback|samconnection_send|samconnection_setDebug|samconnection_subscribe|samconnection_unsubscribe|sammessage_body|sammessage_constructor|sammessage_header|sca_createdataobject|sca_getservice|sca_localproxy_createdataobject|sca_soapproxy_createdataobject|scandir|sdo_das_changesummary_beginlogging|sdo_das_changesummary_endlogging|sdo_das_changesummary_getchangeddataobjects|sdo_das_changesummary_getchangetype|sdo_das_changesummary_getoldcontainer|sdo_das_changesummary_getoldvalues|sdo_das_changesummary_islogging|sdo_das_datafactory_addpropertytotype|sdo_das_datafactory_addtype|sdo_das_datafactory_getdatafactory|sdo_das_dataobject_getchangesummary|sdo_das_relational_applychanges|sdo_das_relational_construct|sdo_das_relational_createrootdataobject|sdo_das_relational_executepreparedquery|sdo_das_relational_executequery|sdo_das_setting_getlistindex|sdo_das_setting_getpropertyindex|sdo_das_setting_getpropertyname|sdo_das_setting_getvalue|sdo_das_setting_isset|sdo_das_xml_addtypes|sdo_das_xml_create|sdo_das_xml_createdataobject|sdo_das_xml_createdocument|sdo_das_xml_document_getrootdataobject|sdo_das_xml_document_getrootelementname|sdo_das_xml_document_getrootelementuri|sdo_das_xml_document_setencoding|sdo_das_xml_document_setxmldeclaration|sdo_das_xml_document_setxmlversion|sdo_das_xml_loadfile|sdo_das_xml_loadstring|sdo_das_xml_savefile|sdo_das_xml_savestring|sdo_datafactory_create|sdo_dataobject_clear|sdo_dataobject_createdataobject|sdo_dataobject_getcontainer|sdo_dataobject_getsequence|sdo_dataobject_gettypename|sdo_dataobject_gettypenamespaceuri|sdo_exception_getcause|sdo_list_insert|sdo_model_property_getcontainingtype|sdo_model_property_getdefault|sdo_model_property_getname|sdo_model_property_gettype|sdo_model_property_iscontainment|sdo_model_property_ismany|sdo_model_reflectiondataobject_construct|sdo_model_reflectiondataobject_export|sdo_model_reflectiondataobject_getcontainmentproperty|sdo_model_reflectiondataobject_getinstanceproperties|sdo_model_reflectiondataobject_gettype|sdo_model_type_getbasetype|sdo_model_type_getname|sdo_model_type_getnamespaceuri|sdo_model_type_getproperties|sdo_model_type_getproperty|sdo_model_type_isabstracttype|sdo_model_type_isdatatype|sdo_model_type_isinstance|sdo_model_type_isopentype|sdo_model_type_issequencedtype|sdo_sequence_getproperty|sdo_sequence_insert|sdo_sequence_move|seekableiterator|sem_acquire|sem_get|sem_release|sem_remove|serializable|serialize|session_cache_expire|session_cache_limiter|session_commit|session_decode|session_destroy|session_encode|session_get_cookie_params|session_id|session_is_registered|session_module_name|session_name|session_pgsql_add_error|session_pgsql_get_error|session_pgsql_get_field|session_pgsql_reset|session_pgsql_set_field|session_pgsql_status|session_regenerate_id|session_register|session_save_path|session_set_cookie_params|session_set_save_handler|session_start|session_unregister|session_unset|session_write_close|setCounterClass|set_error_handler|set_exception_handler|set_file_buffer|set_include_path|set_magic_quotes_runtime|set_socket_blocking|set_time_limit|setcookie|setlocale|setproctitle|setrawcookie|setstaticpropertyvalue|setthreadtitle|settype|sha1|sha1_file|shell_exec|shm_attach|shm_detach|shm_get_var|shm_has_var|shm_put_var|shm_remove|shm_remove_var|shmop_close|shmop_delete|shmop_open|shmop_read|shmop_size|shmop_write|show_source|shuffle|signeurlpaiement|similar_text|simplexml_import_dom|simplexml_load_file|simplexml_load_string|simplexmlelement|simplexmliterator|sin|sinh|sizeof|sleep|snmp|snmp2_get|snmp2_getnext|snmp2_real_walk|snmp2_set|snmp2_walk|snmp3_get|snmp3_getnext|snmp3_real_walk|snmp3_set|snmp3_walk|snmp_get_quick_print|snmp_get_valueretrieval|snmp_read_mib|snmp_set_enum_print|snmp_set_oid_numeric_print|snmp_set_oid_output_format|snmp_set_quick_print|snmp_set_valueretrieval|snmpget|snmpgetnext|snmprealwalk|snmpset|snmpwalk|snmpwalkoid|soapclient|soapfault|soapheader|soapparam|soapserver|soapvar|socket_accept|socket_bind|socket_clear_error|socket_close|socket_connect|socket_create|socket_create_listen|socket_create_pair|socket_get_option|socket_get_status|socket_getpeername|socket_getsockname|socket_last_error|socket_listen|socket_read|socket_recv|socket_recvfrom|socket_select|socket_send|socket_sendto|socket_set_block|socket_set_blocking|socket_set_nonblock|socket_set_option|socket_set_timeout|socket_shutdown|socket_strerror|socket_write|solr_get_version|solrclient|solrclientexception|solrdocument|solrdocumentfield|solrexception|solrgenericresponse|solrillegalargumentexception|solrillegaloperationexception|solrinputdocument|solrmodifiableparams|solrobject|solrparams|solrpingresponse|solrquery|solrqueryresponse|solrresponse|solrupdateresponse|solrutils|sort|soundex|sphinxclient|spl_autoload|spl_autoload_call|spl_autoload_extensions|spl_autoload_functions|spl_autoload_register|spl_autoload_unregister|spl_classes|spl_object_hash|splbool|spldoublylinkedlist|splenum|splfileinfo|splfileobject|splfixedarray|splfloat|splheap|splint|split|spliti|splmaxheap|splminheap|splobjectstorage|splobserver|splpriorityqueue|splqueue|splstack|splstring|splsubject|spltempfileobject|spoofchecker|sprintf|sql_regcase|sqlite3|sqlite3result|sqlite3stmt|sqlite_array_query|sqlite_busy_timeout|sqlite_changes|sqlite_close|sqlite_column|sqlite_create_aggregate|sqlite_create_function|sqlite_current|sqlite_error_string|sqlite_escape_string|sqlite_exec|sqlite_factory|sqlite_fetch_all|sqlite_fetch_array|sqlite_fetch_column_types|sqlite_fetch_object|sqlite_fetch_single|sqlite_fetch_string|sqlite_field_name|sqlite_has_more|sqlite_has_prev|sqlite_key|sqlite_last_error|sqlite_last_insert_rowid|sqlite_libencoding|sqlite_libversion|sqlite_next|sqlite_num_fields|sqlite_num_rows|sqlite_open|sqlite_popen|sqlite_prev|sqlite_query|sqlite_rewind|sqlite_seek|sqlite_single_query|sqlite_udf_decode_binary|sqlite_udf_encode_binary|sqlite_unbuffered_query|sqlite_valid|sqrt|srand|sscanf|ssdeep_fuzzy_compare|ssdeep_fuzzy_hash|ssdeep_fuzzy_hash_filename|ssh2_auth_hostbased_file|ssh2_auth_none|ssh2_auth_password|ssh2_auth_pubkey_file|ssh2_connect|ssh2_exec|ssh2_fetch_stream|ssh2_fingerprint|ssh2_methods_negotiated|ssh2_publickey_add|ssh2_publickey_init|ssh2_publickey_list|ssh2_publickey_remove|ssh2_scp_recv|ssh2_scp_send|ssh2_sftp|ssh2_sftp_lstat|ssh2_sftp_mkdir|ssh2_sftp_readlink|ssh2_sftp_realpath|ssh2_sftp_rename|ssh2_sftp_rmdir|ssh2_sftp_stat|ssh2_sftp_symlink|ssh2_sftp_unlink|ssh2_shell|ssh2_tunnel|stat|stats_absolute_deviation|stats_cdf_beta|stats_cdf_binomial|stats_cdf_cauchy|stats_cdf_chisquare|stats_cdf_exponential|stats_cdf_f|stats_cdf_gamma|stats_cdf_laplace|stats_cdf_logistic|stats_cdf_negative_binomial|stats_cdf_noncentral_chisquare|stats_cdf_noncentral_f|stats_cdf_poisson|stats_cdf_t|stats_cdf_uniform|stats_cdf_weibull|stats_covariance|stats_den_uniform|stats_dens_beta|stats_dens_cauchy|stats_dens_chisquare|stats_dens_exponential|stats_dens_f|stats_dens_gamma|stats_dens_laplace|stats_dens_logistic|stats_dens_negative_binomial|stats_dens_normal|stats_dens_pmf_binomial|stats_dens_pmf_hypergeometric|stats_dens_pmf_poisson|stats_dens_t|stats_dens_weibull|stats_harmonic_mean|stats_kurtosis|stats_rand_gen_beta|stats_rand_gen_chisquare|stats_rand_gen_exponential|stats_rand_gen_f|stats_rand_gen_funiform|stats_rand_gen_gamma|stats_rand_gen_ibinomial|stats_rand_gen_ibinomial_negative|stats_rand_gen_int|stats_rand_gen_ipoisson|stats_rand_gen_iuniform|stats_rand_gen_noncenral_chisquare|stats_rand_gen_noncentral_f|stats_rand_gen_noncentral_t|stats_rand_gen_normal|stats_rand_gen_t|stats_rand_get_seeds|stats_rand_phrase_to_seeds|stats_rand_ranf|stats_rand_setall|stats_skew|stats_standard_deviation|stats_stat_binomial_coef|stats_stat_correlation|stats_stat_gennch|stats_stat_independent_t|stats_stat_innerproduct|stats_stat_noncentral_t|stats_stat_paired_t|stats_stat_percentile|stats_stat_powersum|stats_variance|stomp|stomp_connect_error|stomp_version|stompexception|stompframe|str_getcsv|str_ireplace|str_pad|str_repeat|str_replace|str_rot13|str_shuffle|str_split|str_word_count|strcasecmp|strchr|strcmp|strcoll|strcspn|stream_bucket_append|stream_bucket_make_writeable|stream_bucket_new|stream_bucket_prepend|stream_context_create|stream_context_get_default|stream_context_get_options|stream_context_get_params|stream_context_set_default|stream_context_set_option|stream_context_set_params|stream_copy_to_stream|stream_encoding|stream_filter_append|stream_filter_prepend|stream_filter_register|stream_filter_remove|stream_get_contents|stream_get_filters|stream_get_line|stream_get_meta_data|stream_get_transports|stream_get_wrappers|stream_is_local|stream_notification_callback|stream_register_wrapper|stream_resolve_include_path|stream_select|stream_set_blocking|stream_set_read_buffer|stream_set_timeout|stream_set_write_buffer|stream_socket_accept|stream_socket_client|stream_socket_enable_crypto|stream_socket_get_name|stream_socket_pair|stream_socket_recvfrom|stream_socket_sendto|stream_socket_server|stream_socket_shutdown|stream_supports_lock|stream_wrapper_register|stream_wrapper_restore|stream_wrapper_unregister|streamwrapper|strftime|strip_tags|stripcslashes|stripos|stripslashes|stristr|strlen|strnatcasecmp|strnatcmp|strncasecmp|strncmp|strpbrk|strpos|strptime|strrchr|strrev|strripos|strrpos|strspn|strstr|strtok|strtolower|strtotime|strtoupper|strtr|strval|substr|substr_compare|substr_count|substr_replace|svm|svmmodel|svn_add|svn_auth_get_parameter|svn_auth_set_parameter|svn_blame|svn_cat|svn_checkout|svn_cleanup|svn_client_version|svn_commit|svn_delete|svn_diff|svn_export|svn_fs_abort_txn|svn_fs_apply_text|svn_fs_begin_txn2|svn_fs_change_node_prop|svn_fs_check_path|svn_fs_contents_changed|svn_fs_copy|svn_fs_delete|svn_fs_dir_entries|svn_fs_file_contents|svn_fs_file_length|svn_fs_is_dir|svn_fs_is_file|svn_fs_make_dir|svn_fs_make_file|svn_fs_node_created_rev|svn_fs_node_prop|svn_fs_props_changed|svn_fs_revision_prop|svn_fs_revision_root|svn_fs_txn_root|svn_fs_youngest_rev|svn_import|svn_log|svn_ls|svn_mkdir|svn_repos_create|svn_repos_fs|svn_repos_fs_begin_txn_for_commit|svn_repos_fs_commit_txn|svn_repos_hotcopy|svn_repos_open|svn_repos_recover|svn_revert|svn_status|svn_update|swf_actiongeturl|swf_actiongotoframe|swf_actiongotolabel|swf_actionnextframe|swf_actionplay|swf_actionprevframe|swf_actionsettarget|swf_actionstop|swf_actiontogglequality|swf_actionwaitforframe|swf_addbuttonrecord|swf_addcolor|swf_closefile|swf_definebitmap|swf_definefont|swf_defineline|swf_definepoly|swf_definerect|swf_definetext|swf_endbutton|swf_enddoaction|swf_endshape|swf_endsymbol|swf_fontsize|swf_fontslant|swf_fonttracking|swf_getbitmapinfo|swf_getfontinfo|swf_getframe|swf_labelframe|swf_lookat|swf_modifyobject|swf_mulcolor|swf_nextid|swf_oncondition|swf_openfile|swf_ortho|swf_ortho2|swf_perspective|swf_placeobject|swf_polarview|swf_popmatrix|swf_posround|swf_pushmatrix|swf_removeobject|swf_rotate|swf_scale|swf_setfont|swf_setframe|swf_shapearc|swf_shapecurveto|swf_shapecurveto3|swf_shapefillbitmapclip|swf_shapefillbitmaptile|swf_shapefilloff|swf_shapefillsolid|swf_shapelinesolid|swf_shapelineto|swf_shapemoveto|swf_showframe|swf_startbutton|swf_startdoaction|swf_startshape|swf_startsymbol|swf_textwidth|swf_translate|swf_viewport|swfaction|swfbitmap|swfbutton|swfdisplayitem|swffill|swffont|swffontchar|swfgradient|swfmorph|swfmovie|swfprebuiltclip|swfshape|swfsound|swfsoundinstance|swfsprite|swftext|swftextfield|swfvideostream|swish_construct|swish_getmetalist|swish_getpropertylist|swish_prepare|swish_query|swishresult_getmetalist|swishresult_stem|swishresults_getparsedwords|swishresults_getremovedstopwords|swishresults_nextresult|swishresults_seekresult|swishsearch_execute|swishsearch_resetlimit|swishsearch_setlimit|swishsearch_setphrasedelimiter|swishsearch_setsort|swishsearch_setstructure|sybase_affected_rows|sybase_close|sybase_connect|sybase_data_seek|sybase_deadlock_retry_count|sybase_fetch_array|sybase_fetch_assoc|sybase_fetch_field|sybase_fetch_object|sybase_fetch_row|sybase_field_seek|sybase_free_result|sybase_get_last_message|sybase_min_client_severity|sybase_min_error_severity|sybase_min_message_severity|sybase_min_server_severity|sybase_num_fields|sybase_num_rows|sybase_pconnect|sybase_query|sybase_result|sybase_select_db|sybase_set_message_handler|sybase_unbuffered_query|symlink|sys_get_temp_dir|sys_getloadavg|syslog|system|tag|tan|tanh|tcpwrap_check|tempnam|textdomain|tidy|tidy_access_count|tidy_config_count|tidy_diagnose|tidy_error_count|tidy_get_error_buffer|tidy_get_output|tidy_load_config|tidy_reset_config|tidy_save_config|tidy_set_encoding|tidy_setopt|tidy_warning_count|tidynode|time|time_nanosleep|time_sleep_until|timezone_abbreviations_list|timezone_identifiers_list|timezone_location_get|timezone_name_from_abbr|timezone_name_get|timezone_offset_get|timezone_open|timezone_transitions_get|timezone_version_get|tmpfile|token_get_all|token_name|tokyotyrant|tokyotyrantquery|tokyotyranttable|tostring|tostring|touch|transliterator|traversable|trigger_error|trim|uasort|ucfirst|ucwords|udm_add_search_limit|udm_alloc_agent|udm_alloc_agent_array|udm_api_version|udm_cat_list|udm_cat_path|udm_check_charset|udm_check_stored|udm_clear_search_limits|udm_close_stored|udm_crc32|udm_errno|udm_error|udm_find|udm_free_agent|udm_free_ispell_data|udm_free_res|udm_get_doc_count|udm_get_res_field|udm_get_res_param|udm_hash32|udm_load_ispell_data|udm_open_stored|udm_set_agent_param|uksort|umask|underflowexception|unexpectedvalueexception|uniqid|unixtojd|unlink|unpack|unregister_tick_function|unserialize|unset|urldecode|urlencode|use_soap_error_handler|user_error|usleep|usort|utf8_decode|utf8_encode|v8js|v8jsexception|var_dump|var_export|variant|variant_abs|variant_add|variant_and|variant_cast|variant_cat|variant_cmp|variant_date_from_timestamp|variant_date_to_timestamp|variant_div|variant_eqv|variant_fix|variant_get_type|variant_idiv|variant_imp|variant_int|variant_mod|variant_mul|variant_neg|variant_not|variant_or|variant_pow|variant_round|variant_set|variant_set_type|variant_sub|variant_xor|version_compare|vfprintf|virtual|vpopmail_add_alias_domain|vpopmail_add_alias_domain_ex|vpopmail_add_domain|vpopmail_add_domain_ex|vpopmail_add_user|vpopmail_alias_add|vpopmail_alias_del|vpopmail_alias_del_domain|vpopmail_alias_get|vpopmail_alias_get_all|vpopmail_auth_user|vpopmail_del_domain|vpopmail_del_domain_ex|vpopmail_del_user|vpopmail_error|vpopmail_passwd|vpopmail_set_user_quota|vprintf|vsprintf|w32api_deftype|w32api_init_dtype|w32api_invoke_function|w32api_register_function|w32api_set_call_method|wddx_add_vars|wddx_deserialize|wddx_packet_end|wddx_packet_start|wddx_serialize_value|wddx_serialize_vars|win32_continue_service|win32_create_service|win32_delete_service|win32_get_last_control_message|win32_pause_service|win32_ps_list_procs|win32_ps_stat_mem|win32_ps_stat_proc|win32_query_service_status|win32_set_service_status|win32_start_service|win32_start_service_ctrl_dispatcher|win32_stop_service|wincache_fcache_fileinfo|wincache_fcache_meminfo|wincache_lock|wincache_ocache_fileinfo|wincache_ocache_meminfo|wincache_refresh_if_changed|wincache_rplist_fileinfo|wincache_rplist_meminfo|wincache_scache_info|wincache_scache_meminfo|wincache_ucache_add|wincache_ucache_cas|wincache_ucache_clear|wincache_ucache_dec|wincache_ucache_delete|wincache_ucache_exists|wincache_ucache_get|wincache_ucache_inc|wincache_ucache_info|wincache_ucache_meminfo|wincache_ucache_set|wincache_unlock|wordwrap|xattr_get|xattr_list|xattr_remove|xattr_set|xattr_supported|xdiff_file_bdiff|xdiff_file_bdiff_size|xdiff_file_bpatch|xdiff_file_diff|xdiff_file_diff_binary|xdiff_file_merge3|xdiff_file_patch|xdiff_file_patch_binary|xdiff_file_rabdiff|xdiff_string_bdiff|xdiff_string_bdiff_size|xdiff_string_bpatch|xdiff_string_diff|xdiff_string_diff_binary|xdiff_string_merge3|xdiff_string_patch|xdiff_string_patch_binary|xdiff_string_rabdiff|xhprof_disable|xhprof_enable|xhprof_sample_disable|xhprof_sample_enable|xml_error_string|xml_get_current_byte_index|xml_get_current_column_number|xml_get_current_line_number|xml_get_error_code|xml_parse|xml_parse_into_struct|xml_parser_create|xml_parser_create_ns|xml_parser_free|xml_parser_get_option|xml_parser_set_option|xml_set_character_data_handler|xml_set_default_handler|xml_set_element_handler|xml_set_end_namespace_decl_handler|xml_set_external_entity_ref_handler|xml_set_notation_decl_handler|xml_set_object|xml_set_processing_instruction_handler|xml_set_start_namespace_decl_handler|xml_set_unparsed_entity_decl_handler|xmlreader|xmlrpc_decode|xmlrpc_decode_request|xmlrpc_encode|xmlrpc_encode_request|xmlrpc_get_type|xmlrpc_is_fault|xmlrpc_parse_method_descriptions|xmlrpc_server_add_introspection_data|xmlrpc_server_call_method|xmlrpc_server_create|xmlrpc_server_destroy|xmlrpc_server_register_introspection_callback|xmlrpc_server_register_method|xmlrpc_set_type|xmlwriter_end_attribute|xmlwriter_end_cdata|xmlwriter_end_comment|xmlwriter_end_document|xmlwriter_end_dtd|xmlwriter_end_dtd_attlist|xmlwriter_end_dtd_element|xmlwriter_end_dtd_entity|xmlwriter_end_element|xmlwriter_end_pi|xmlwriter_flush|xmlwriter_full_end_element|xmlwriter_open_memory|xmlwriter_open_uri|xmlwriter_output_memory|xmlwriter_set_indent|xmlwriter_set_indent_string|xmlwriter_start_attribute|xmlwriter_start_attribute_ns|xmlwriter_start_cdata|xmlwriter_start_comment|xmlwriter_start_document|xmlwriter_start_dtd|xmlwriter_start_dtd_attlist|xmlwriter_start_dtd_element|xmlwriter_start_dtd_entity|xmlwriter_start_element|xmlwriter_start_element_ns|xmlwriter_start_pi|xmlwriter_text|xmlwriter_write_attribute|xmlwriter_write_attribute_ns|xmlwriter_write_cdata|xmlwriter_write_comment|xmlwriter_write_dtd|xmlwriter_write_dtd_attlist|xmlwriter_write_dtd_element|xmlwriter_write_dtd_entity|xmlwriter_write_element|xmlwriter_write_element_ns|xmlwriter_write_pi|xmlwriter_write_raw|xpath_eval|xpath_eval_expression|xpath_new_context|xpath_register_ns|xpath_register_ns_auto|xptr_eval|xptr_new_context|xslt_backend_info|xslt_backend_name|xslt_backend_version|xslt_create|xslt_errno|xslt_error|xslt_free|xslt_getopt|xslt_process|xslt_set_base|xslt_set_encoding|xslt_set_error_handler|xslt_set_log|xslt_set_object|xslt_set_sax_handler|xslt_set_sax_handlers|xslt_set_scheme_handler|xslt_set_scheme_handlers|xslt_setopt|xsltprocessor|yaml_emit|yaml_emit_file|yaml_parse|yaml_parse_file|yaml_parse_url|yaz_addinfo|yaz_ccl_conf|yaz_ccl_parse|yaz_close|yaz_connect|yaz_database|yaz_element|yaz_errno|yaz_error|yaz_es|yaz_es_result|yaz_get_option|yaz_hits|yaz_itemorder|yaz_present|yaz_range|yaz_record|yaz_scan|yaz_scan_result|yaz_schema|yaz_search|yaz_set_option|yaz_sort|yaz_syntax|yaz_wait|yp_all|yp_cat|yp_err_string|yp_errno|yp_first|yp_get_default_domain|yp_master|yp_match|yp_next|yp_order|zend_logo_guid|zend_thread_id|zend_version|zip_close|zip_entry_close|zip_entry_compressedsize|zip_entry_compressionmethod|zip_entry_filesize|zip_entry_name|zip_entry_open|zip_entry_read|zip_open|zip_read|ziparchive|ziparchive_addemptydir|ziparchive_addfile|ziparchive_addfromstring|ziparchive_close|ziparchive_deleteindex|ziparchive_deletename|ziparchive_extractto|ziparchive_getarchivecomment|ziparchive_getcommentindex|ziparchive_getcommentname|ziparchive_getfromindex|ziparchive_getfromname|ziparchive_getnameindex|ziparchive_getstatusstring|ziparchive_getstream|ziparchive_locatename|ziparchive_open|ziparchive_renameindex|ziparchive_renamename|ziparchive_setCommentName|ziparchive_setarchivecomment|ziparchive_setcommentindex|ziparchive_statindex|ziparchive_statname|ziparchive_unchangeall|ziparchive_unchangearchive|ziparchive_unchangeindex|ziparchive_unchangename|zlib_get_coding_type".split("|")),n=i.arrayToMap("abstract|and|array|as|break|case|catch|class|clone|const|continue|declare|default|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|final|for|foreach|function|global|goto|if|implements|interface|instanceof|namespace|new|or|private|protected|public|static|switch|throw|try|use|var|while|xor".split("|")),r=i.arrayToMap("die|echo|empty|exit|eval|include|include_once|isset|list|require|require_once|return|print|unset".split("|")),o=i.arrayToMap("true|false|null|__CLASS__|__DIR__|__FILE__|__LINE__|__METHOD__|__FUNCTION__|__NAMESPACE__".split("|")),u=i.arrayToMap("$GLOBALS|$_SERVER|$_GET|$_POST|$_FILES|$_REQUEST|$_SESSION|$_ENV|$_COOKIE|$php_errormsg|$HTTP_RAW_POST_DATA|$http_response_header|$argc|$argv".split("|")),a=i.arrayToMap("key_exists|cairo_matrix_create_scale|cairo_matrix_create_translate|call_user_method|call_user_method_array|com_addref|com_get|com_invoke|com_isenum|com_load|com_release|com_set|connection_timeout|cubrid_load_from_glo|cubrid_new_glo|cubrid_save_to_glo|cubrid_send_glo|define_syslog_variables|dl|ereg|ereg_replace|eregi|eregi_replace|hw_documentattributes|hw_documentbodytag|hw_documentsize|hw_outputdocument|imagedashedline|maxdb_bind_param|maxdb_bind_result|maxdb_client_encoding|maxdb_close_long_data|maxdb_execute|maxdb_fetch|maxdb_get_metadata|maxdb_param_count|maxdb_send_long_data|mcrypt_ecb|mcrypt_generic_end|mime_content_type|mysql_createdb|mysql_dbname|mysql_db_query|mysql_drop_db|mysql_dropdb|mysql_escape_string|mysql_fieldflags|mysql_fieldflags|mysql_fieldname|mysql_fieldtable|mysql_fieldtype|mysql_freeresult|mysql_listdbs|mysql_list_fields|mysql_listfields|mysql_list_tables|mysql_listtables|mysql_numfields|mysql_numrows|mysql_selectdb|mysql_tablename|mysqli_bind_param|mysqli_bind_result|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_execute|mysqli_fetch|mysqli_get_metadata|mysqli_master_query|mysqli_param_count|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_send_long_data|mysqli_send_query|mysqli_slave_query|ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|ociloadlob|ocilogoff|ocilogon|ocinewcollection|ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|ocirollback|ocirowcount|ocisavelob|ocisavelobfile|ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|PDF_add_annotation|PDF_add_bookmark|PDF_add_launchlink|PDF_add_locallink|PDF_add_note|PDF_add_outline|PDF_add_pdflink|PDF_add_weblink|PDF_attach_file|PDF_begin_page|PDF_begin_template|PDF_close_pdi|PDF_close|PDF_findfont|PDF_get_font|PDF_get_fontname|PDF_get_fontsize|PDF_get_image_height|PDF_get_image_width|PDF_get_majorversion|PDF_get_minorversion|PDF_get_pdi_parameter|PDF_get_pdi_value|PDF_open_ccitt|PDF_open_file|PDF_open_gif|PDF_open_image_file|PDF_open_image|PDF_open_jpeg|PDF_open_pdi|PDF_open_tiff|PDF_place_image|PDF_place_pdi_page|PDF_set_border_color|PDF_set_border_dash|PDF_set_border_style|PDF_set_char_spacing|PDF_set_duration|PDF_set_horiz_scaling|PDF_set_info_author|PDF_set_info_creator|PDF_set_info_keywords|PDF_set_info_subject|PDF_set_info_title|PDF_set_leading|PDF_set_text_matrix|PDF_set_text_rendering|PDF_set_text_rise|PDF_set_word_spacing|PDF_setgray_fill|PDF_setgray_stroke|PDF_setgray|PDF_setpolydash|PDF_setrgbcolor_fill|PDF_setrgbcolor_stroke|PDF_setrgbcolor|PDF_show_boxed|php_check_syntax|px_set_tablename|px_set_targetencoding|runkit_sandbox_output_handler|session_is_registered|session_register|session_unregisterset_magic_quotes_runtime|magic_quotes_runtime|set_socket_blocking|socket_set_blocking|set_socket_timeout|socket_set_timeout|split|spliti|sql_regcase".split("|")),f=i.arrayToMap("cfunction|old_function".split("|")),l=i.arrayToMap([]);this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},{token:"comment",regex:"#.*$"},e.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/][gimy]*\\s*(?=[).,;]|$)"},{token:"string",regex:'"',next:"qqstring"},{token:"string",regex:"'",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"\\b(?:DEFAULT_INCLUDE_PATH|E_(?:ALL|CO(?:MPILE_(?:ERROR|WARNING)|RE_(?:ERROR|WARNING))|ERROR|NOTICE|PARSE|STRICT|USER_(?:ERROR|NOTICE|WARNING)|WARNING)|P(?:EAR_(?:EXTENSION_DIR|INSTALL_DIR)|HP_(?:BINDIR|CONFIG_FILE_(?:PATH|SCAN_DIR)|DATADIR|E(?:OL|XTENSION_DIR)|INT_(?:MAX|SIZE)|L(?:IBDIR|OCALSTATEDIR)|O(?:S|UTPUT_HANDLER_(?:CONT|END|START))|PREFIX|S(?:API|HLIB_SUFFIX|YSCONFDIR)|VERSION))|__COMPILER_HALT_OFFSET__)\\b"},{token:"constant.language",regex:"\\b(?:A(?:B(?:DAY_(?:1|2|3|4|5|6|7)|MON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9))|LT_DIGITS|M_STR|SSERT_(?:ACTIVE|BAIL|CALLBACK|QUIET_EVAL|WARNING))|C(?:ASE_(?:LOWER|UPPER)|HAR_MAX|O(?:DESET|NNECTION_(?:ABORTED|NORMAL|TIMEOUT)|UNT_(?:NORMAL|RECURSIVE))|R(?:EDITS_(?:ALL|DOCS|FULLPAGE|G(?:ENERAL|ROUP)|MODULES|QA|SAPI)|NCYSTR|YPT_(?:BLOWFISH|EXT_DES|MD5|S(?:ALT_LENGTH|TD_DES)))|URRENCY_SYMBOL)|D(?:AY_(?:1|2|3|4|5|6|7)|ECIMAL_POINT|IRECTORY_SEPARATOR|_(?:FMT|T_FMT))|E(?:NT_(?:COMPAT|NOQUOTES|QUOTES)|RA(?:_(?:D_(?:FMT|T_FMT)|T_FMT|YEAR)|)|XTR_(?:IF_EXISTS|OVERWRITE|PREFIX_(?:ALL|I(?:F_EXISTS|NVALID)|SAME)|SKIP))|FRAC_DIGITS|GROUPING|HTML_(?:ENTITIES|SPECIALCHARS)|IN(?:FO_(?:ALL|C(?:ONFIGURATION|REDITS)|ENVIRONMENT|GENERAL|LICENSE|MODULES|VARIABLES)|I_(?:ALL|PERDIR|SYSTEM|USER)|T_(?:CURR_SYMBOL|FRAC_DIGITS))|L(?:C_(?:ALL|C(?:OLLATE|TYPE)|M(?:ESSAGES|ONETARY)|NUMERIC|TIME)|O(?:CK_(?:EX|NB|SH|UN)|G_(?:A(?:LERT|UTH(?:PRIV|))|C(?:ONS|R(?:IT|ON))|D(?:AEMON|EBUG)|E(?:MERG|RR)|INFO|KERN|L(?:OCAL(?:0|1|2|3|4|5|6|7)|PR)|MAIL|N(?:DELAY|EWS|O(?:TICE|WAIT))|ODELAY|P(?:ERROR|ID)|SYSLOG|U(?:SER|UCP)|WARNING)))|M(?:ON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9|DECIMAL_POINT|GROUPING|THOUSANDS_SEP)|_(?:1_PI|2_(?:PI|SQRTPI)|E|L(?:N(?:10|2)|OG(?:10E|2E))|PI(?:_(?:2|4)|)|SQRT(?:1_2|2)))|N(?:EGATIVE_SIGN|O(?:EXPR|STR)|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|P(?:ATH(?:INFO_(?:BASENAME|DIRNAME|EXTENSION)|_SEPARATOR)|M_STR|OSITIVE_SIGN|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|RADIXCHAR|S(?:EEK_(?:CUR|END|SET)|ORT_(?:ASC|DESC|NUMERIC|REGULAR|STRING)|TR_PAD_(?:BOTH|LEFT|RIGHT))|T(?:HOUS(?:ANDS_SEP|EP)|_FMT(?:_AMPM|))|YES(?:EXPR|STR)|STD(?:IN|OUT|ERR))\\b"},{token:function(e){return n.hasOwnProperty(e)?"keyword":o.hasOwnProperty(e)?"constant.language":u.hasOwnProperty(e)?"variable.language":l.hasOwnProperty(e)?"invalid.illegal":t.hasOwnProperty(e)?"support.function":e=="debugger"?"invalid.deprecated":e.match(/^(\$[a-zA-Z][a-zA-Z0-9_]*|self|parent)$/)?"variable":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:'\\\\(?:[nrtvef\\\\"$]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2})'},{token:"constant.language.escape",regex:/\$[\w\d]+(?:\[[\w\d]+\])?/},{token:"constant.language.escape",regex:/\$\{[^"\}]+\}?/},{token:"string",regex:'"',next:"start"},{token:"string",regex:".+?"}],qstring:[{token:"constant.language.escape",regex:"\\\\['\\\\]"},{token:"string",regex:"'",next:"start"},{token:"string",regex:".+?"}]},this.embedRules(s,"doc-",[s.getEndRule("start")])};r.inherits(a,o);var f=function(){u.call(this);for(var e in this.$rules)this.$rules[e].unshift({token:"support.php_tag",regex:"<\\?(?:php|\\=)?",next:"php-start"});this.embedRules(a,"php-"),this.$rules["php-start"].unshift({token:"support.php_tag",regex:"\\?>",next:"start"})};r.inherits(f,u),t.PhpHighlightRules=f,t.PhpLangHighlightRules=a}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-powershell.js b/common/static/js/vendor/ace/mode-powershell.js new file mode 100644 index 0000000000..0e920ae7e7 --- /dev/null +++ b/common/static/js/vendor/ace/mode-powershell.js @@ -0,0 +1 @@ +ace.define("ace/mode/powershell",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/powershell_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./powershell_highlight_rules").PowershellHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new a,this.foldingRules=new f};r.inherits(l,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[]\s*$/);o&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){return null}}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/powershell_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="function|if|else|elseif|switch|while|default|for|do|until|break|continue|foreach|return|filter|in|trap|throw|param|begin|process|end",t="Get-Alias|Import-Alias|New-Alias|Set-Alias|Get-AuthenticodeSignature|Set-AuthenticodeSignature|Set-Location|Get-ChildItem|Clear-Item|Get-Command|Measure-Command|Trace-Command|Add-Computer|Checkpoint-Computer|Remove-Computer|Restart-Computer|Restore-Computer|Stop-Computer|Reset-ComputerMachinePassword|Test-ComputerSecureChannel|Add-Content|Get-Content|Set-Content|Clear-Content|Get-Command|Invoke-Command|Enable-ComputerRestore|Disable-ComputerRestore|Get-ComputerRestorePoint|Test-Connection|ConvertFrom-CSV|ConvertTo-CSV|ConvertTo-Html|ConvertTo-Xml|ConvertFrom-SecureString|ConvertTo-SecureString|Copy-Item|Export-Counter|Get-Counter|Import-Counter|Get-Credential|Get-Culture|Get-ChildItem|Get-Date|Set-Date|Remove-Item|Compare-Object|Get-Event|Get-WinEvent|New-Event|Remove-Event|Unregister-Event|Wait-Event|Clear-EventLog|Get-Eventlog|Limit-EventLog|New-Eventlog|Remove-EventLog|Show-EventLog|Write-EventLog|Get-EventSubscriber|Register-EngineEvent|Register-ObjectEvent|Register-WmiEvent|Get-ExecutionPolicy|Set-ExecutionPolicy|Export-Alias|Export-Clixml|Export-Console|Export-Csv|ForEach-Object|Format-Custom|Format-List|Format-Table|Format-Wide|Export-FormatData|Get-FormatData|Get-Item|Get-ChildItem|Get-Help|Add-History|Clear-History|Get-History|Invoke-History|Get-Host|Read-Host|Write-Host|Get-HotFix|Import-Clixml|Import-Csv|Invoke-Command|Invoke-Expression|Get-Item|Invoke-Item|New-Item|Remove-Item|Set-Item|Clear-ItemProperty|Copy-ItemProperty|Get-ItemProperty|Move-ItemProperty|New-ItemProperty|Remove-ItemProperty|Rename-ItemProperty|Set-ItemProperty|Get-Job|Receive-Job|Remove-Job|Start-Job|Stop-Job|Wait-Job|Stop-Process|Update-List|Get-Location|Pop-Location|Push-Location|Set-Location|Send-MailMessage|Add-Member|Get-Member|Move-Item|Compare-Object|Group-Object|Measure-Object|New-Object|Select-Object|Sort-Object|Where-Object|Out-Default|Out-File|Out-GridView|Out-Host|Out-Null|Out-Printer|Out-String|Convert-Path|Join-Path|Resolve-Path|Split-Path|Test-Path|Get-Pfxcertificate|Pop-Location|Push-Location|Get-Process|Start-Process|Stop-Process|Wait-Process|Enable-PSBreakpoint|Disable-PSBreakpoint|Get-PSBreakpoint|Set-PSBreakpoint|Remove-PSBreakpoint|Get-PSDrive|New-PSDrive|Remove-PSDrive|Get-PSProvider|Set-PSdebug|Enter-PSSession|Exit-PSSession|Export-PSSession|Get-PSSession|Import-PSSession|New-PSSession|Remove-PSSession|Disable-PSSessionConfiguration|Enable-PSSessionConfiguration|Get-PSSessionConfiguration|Register-PSSessionConfiguration|Set-PSSessionConfiguration|Unregister-PSSessionConfiguration|New-PSSessionOption|Add-PsSnapIn|Get-PsSnapin|Remove-PSSnapin|Get-Random|Read-Host|Remove-Item|Rename-Item|Rename-ItemProperty|Select-Object|Select-XML|Send-MailMessage|Get-Service|New-Service|Restart-Service|Resume-Service|Set-Service|Start-Service|Stop-Service|Suspend-Service|Sort-Object|Start-Sleep|ConvertFrom-StringData|Select-String|Tee-Object|New-Timespan|Trace-Command|Get-Tracesource|Set-Tracesource|Start-Transaction|Complete-Transaction|Get-Transaction|Use-Transaction|Undo-Transaction|Start-Transcript|Stop-Transcript|Add-Type|Update-TypeData|Get-Uiculture|Get-Unique|Update-Formatdata|Update-Typedata|Clear-Variable|Get-Variable|New-Variable|Remove-Variable|Set-Variable|New-WebServiceProxy|Where-Object|Write-Debug|Write-Error|Write-Host|Write-Output|Write-Progress|Write-Verbose|Write-Warning|Set-WmiInstance|Invoke-WmiMethod|Get-WmiObject|Remove-WmiObject|Connect-WSMan|Disconnect-WSMan|Test-WSMan|Invoke-WSManAction|Disable-WSManCredSSP|Enable-WSManCredSSP|Get-WSManCredSSP|New-WSManInstance|Get-WSManInstance|Set-WSManInstance|Remove-WSManInstance|Set-WSManQuickConfig|New-WSManSessionOption",n=this.createKeywordMapper({"support.function":t,keyword:e},"identifier"),r="eq|ne|ge|gt|lt|le|like|notlike|match|notmatch|replace|contains|notcontains|ieq|ine|ige|igt|ile|ilt|ilike|inotlike|imatch|inotmatch|ireplace|icontains|inotcontains|is|isnot|as|and|or|band|bor|not";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"comment.start",regex:"<#",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"[$](?:[Tt]rue|[Ff]alse)\\b"},{token:"constant.language",regex:"[$][Nn]ull\\b"},{token:"variable.instance",regex:"[$][a-zA-Z][a-zA-Z0-9_]*\\b"},{token:n,regex:"[a-zA-Z_$][a-zA-Z0-9_$\\-]*\\b"},{token:"keyword.operator",regex:"\\-(?:"+r+")"},{token:"keyword.operator",regex:"&|\\*|\\+|\\-|\\=|\\+=|\\-="},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment.end",regex:"#>",next:"start"},{token:"doc.comment.tag",regex:"^\\.\\w+"},{token:"comment",regex:"\\w+"},{token:"comment",regex:"."}]}};r.inherits(s,i),t.PowershellHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-python.js b/common/static/js/vendor/ace/mode-python.js new file mode 100644 index 0000000000..c5ef6982f7 --- /dev/null +++ b/common/static/js/vendor/ace/mode-python.js @@ -0,0 +1 @@ +ace.define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/python_highlight_rules","ace/mode/folding/pythonic","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./python_highlight_rules").PythonHighlightRules,u=e("./folding/pythonic").FoldMode,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.foldingRules=new u("\\:")};r.inherits(f,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)#/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"#")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[\:]\s*$/);o&&(r+=n)}return r};var e={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(t,n,r){if(r!=="\r\n"&&r!=="\r"&&r!=="\n")return!1;var i=this.$tokenizer.getLineTokens(n.trim(),t).tokens;if(!i)return!1;do var s=i.pop();while(s&&(s.type=="comment"||s.type=="text"&&s.value.match(/^\s+$/)));return s?s.type=="keyword"&&e[s.value]:!1},this.autoOutdent=function(e,t,n){n+=1;var r=this.$getIndent(t.getLine(n)),i=t.getTabString();r.slice(-i.length)==i&&t.remove(new a(n,r.length-i.length,n,r.length))}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield",t="True|False|None|NotImplemented|Ellipsis|__debug__",n="abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern",r=this.createKeywordMapper({"invalid.deprecated":"debugger","support.function":n,"constant.language":t,keyword:e},"identifier"),i="(?:r|u|ur|R|U|UR|Ur|uR)?",s="(?:(?:[1-9]\\d*)|(?:0))",o="(?:0[oO]?[0-7]+)",u="(?:0[xX][\\dA-Fa-f]+)",a="(?:0[bB][01]+)",f="(?:"+s+"|"+o+"|"+u+"|"+a+")",l="(?:[eE][+-]?\\d+)",c="(?:\\.\\d+)",h="(?:\\d+)",p="(?:(?:"+h+"?"+c+")|(?:"+h+"\\.))",d="(?:(?:"+p+"|"+h+")"+l+")",v="(?:"+d+"|"+p+")";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:i+'"{3}(?:[^\\\\]|\\\\.)*?"{3}'},{token:"string",regex:i+'"{3}.*$',next:"qqstring"},{token:"string",regex:i+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:i+"'{3}(?:[^\\\\]|\\\\.)*?'{3}"},{token:"string",regex:i+"'{3}.*$",next:"qstring"},{token:"string",regex:i+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:"(?:"+v+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:v},{token:"constant.numeric",regex:f+"[lL]\\b"},{token:"constant.numeric",regex:f+"\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?"{3}',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?'{3}",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.PythonHighlightRules=s}),ace.define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=t.FoldMode=function(e){this.foldingStartMarker=new RegExp("([\\[{])(?:\\s*)$|("+e+")(?:\\s*)(?:#.*)?$")};r.inherits(s,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i)return i[1]?this.openingBracketBlock(e,i[1],n,i.index):i[2]?this.indentationBlock(e,n,i.index+i[2].length):this.indentationBlock(e,n)}}.call(s.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-r.js b/common/static/js/vendor/ace/mode-r.js new file mode 100644 index 0000000000..f4a27c9045 --- /dev/null +++ b/common/static/js/vendor/ace/mode-r.js @@ -0,0 +1 @@ +ace.define("ace/mode/r",["require","exports","module","ace/range","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/r_highlight_rules","ace/mode/matching_brace_outdent","ace/unicode"],function(e,t,n){var r=e("../range").Range,i=e("../lib/oop"),s=e("./text").Mode,o=e("../tokenizer").Tokenizer,u=e("./text_highlight_rules").TextHighlightRules,a=e("./r_highlight_rules").RHighlightRules,f=e("./matching_brace_outdent").MatchingBraceOutdent,l=e("../unicode"),c=function(){this.$tokenizer=new o((new a).getRules()),this.$outdent=new f};i.inherits(c,s),function(){this.tokenRe=new RegExp("^["+l.packages.L+l.packages.Mn+l.packages.Mc+l.packages.Nd+l.packages.Pc+"._]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+l.packages.L+l.packages.Mn+l.packages.Mc+l.packages.Nd+l.packages.Pc+"._]|s])+","g"),this.$complements={"(":")","[":"]",'"':'"',"'":"'","{":"}"},this.$reOpen=/^[(["'{]$/,this.$reClose=/^[)\]"'}]$/,this.getNextLineIndent=function(e,t,n,r,i){return this.codeModel.getNextLineIndent(i,t,e,n,r)},this.allowAutoInsert=this.smartAllowAutoInsert,this.checkOutdent=function(e,t,n){return/^\s+$/.test(t)?/^\s*[\{\}\)]/.test(n):!1},this.getIndentForOpenBrace=function(e){return this.codeModel.getIndentForOpenBrace(e)},this.autoOutdent=function(e,t,n){if(n==0)return 0;var i=t.getLine(n),s=i.match(/^(\s*[\}\)])/);if(s){var o=s[1].length,u=t.findMatchingBracket({row:n,column:o});if(!u||u.row==n)return 0;var a=this.codeModel.getIndentForOpenBrace(u);t.replace(new r(n,0,n,o-1),a)}s=i.match(/^(\s*\{)/);if(s){var o=s[1].length,a=this.codeModel.getBraceIndent(n-1);t.replace(new r(n,0,n,o-1),a)}},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""},this.transformAction=function(e,t,n,r,i){if(t==="insertion"&&i==="\n"){var s=n.getSelectionRange().start,o=/^((\s*#+')\s*)/.exec(r.doc.getLine(s.row));if(o&&n.getSelectionRange().start.column>=o[2].length)return{text:"\n"+o[1]}}return!1}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/r_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules","ace/mode/tex_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=e("./tex_highlight_rules").TexHighlightRules,u=function(){var e=i.arrayToMap("function|if|in|break|next|repeat|else|for|return|switch|while|try|tryCatch|stop|warning|require|library|attach|detach|source|setMethod|setGeneric|setGroupGeneric|setClass".split("|")),t=i.arrayToMap("NULL|NA|TRUE|FALSE|T|F|Inf|NaN|NA_integer_|NA_real_|NA_character_|NA_complex_".split("|"));this.$rules={start:[{token:"comment.sectionhead",regex:"#+(?!').*(?:----|====|####)\\s*$"},{token:"comment",regex:"#+'",next:"rd-start"},{token:"comment",regex:"#.*$"},{token:"string",regex:'["]',next:"qqstring"},{token:"string",regex:"[']",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+[Li]?\\b"},{token:"constant.numeric",regex:"\\d+L\\b"},{token:"constant.numeric",regex:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b"},{token:"constant.numeric",regex:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b"},{token:"constant.language.boolean",regex:"(?:TRUE|FALSE|T|F)\\b"},{token:"identifier",regex:"`.*?`"},{token:function(n){return e[n]?"keyword":t[n]?"constant.language":n=="..."||n.match(/^\.\.\d+$/)?"variable.language":"identifier"},regex:"[a-zA-Z.][a-zA-Z0-9._]*\\b"},{token:"keyword.operator",regex:"%%|>=|<=|==|!=|\\->|<\\-|\\|\\||&&|=|\\+|\\-|\\*|/|\\^|>|<|!|&|\\||~|\\$|:"},{token:"keyword.operator",regex:"%.*?%"},{token:"paren.keyword.operator",regex:"[[({]"},{token:"paren.keyword.operator",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]};var n=(new o("comment")).getRules();for(var r=0;r\n",position:{row:0,column:15}},this.getLanguageMode=function(e){return this.$session.getState(e.row).match(/^r-/)?"R":"HTML"},this.getNextLineIndent=function(e,t,n,r,i){return this.codeModel.getNextLineIndent(i,t,e,n,r)}}.call(u.prototype),t.Mode=u}),ace.define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/html","ace/mode/folding/html"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("./javascript").Mode,o=e("./css").Mode,u=e("../tokenizer").Tokenizer,a=e("./html_highlight_rules").HtmlHighlightRules,f=e("./behaviour/html").HtmlBehaviour,l=e("./folding/html").FoldMode,c=function(){var e=new a;this.$tokenizer=new u(e.getRules()),this.$behaviour=new f,this.$embeds=e.getEmbeds(),this.createModeDelegates({"js-":s,"css-":o}),this.foldingRules=new l};r.inherits(c,i),function(){this.toggleCommentLines=function(e,t,n,r){return 0},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_util"),a=e("./text_highlight_rules").TextHighlightRules,f=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),l=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},u.tag(this.$rules,"tag","start",f),u.tag(this.$rules,"style","css-start",f),u.tag(this.$rules,"script","js-start",f),this.embedRules(o,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(s,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};r.inherits(l,a),t.HtmlHighlightRules=l}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/html",["require","exports","module","ace/lib/oop","ace/mode/behaviour/xml","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function a(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour/xml").XmlBehaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,u=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],f=function(){this.inherit(i),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),f=new o(r,s.row,s.column),l=f.getCurrentToken(),c=!1;if(!l||!a(l,"meta.tag")&&(!a(l,"text")||!l.value.match("/"))){do l=f.stepBackward();while(l&&(a(l,"string")||a(l,"keyword.operator")||a(l,"entity.attribute-name")||a(l,"text")))}else c=!0;if(!l||!a(l,"meta.tag-name")||f.stepBackward().value.match("/"))return;var h=l.value;if(c)var h=h.substring(0,s.column-l.start);if(u.indexOf(h)!==-1)return;return{text:">",selection:[1,1]}}})};r.inherits(f,i),t.HtmlBehaviour=f}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}),ace.define("ace/mode/rhtml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/r_highlight_rules","ace/mode/html_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./r_highlight_rules").RHighlightRules,s=e("./html_highlight_rules").HtmlHighlightRules,o=e("./text_highlight_rules").TextHighlightRules,u=function(){this.$rules=(new s).getRules(),this.$rules.start.unshift({token:"support.function.codebegin",regex:"^",next:"start"})};r.inherits(u,o),t.RHtmlHighlightRules=u}),ace.define("ace/mode/r_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules","ace/mode/tex_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=e("./tex_highlight_rules").TexHighlightRules,u=function(){var e=i.arrayToMap("function|if|in|break|next|repeat|else|for|return|switch|while|try|tryCatch|stop|warning|require|library|attach|detach|source|setMethod|setGeneric|setGroupGeneric|setClass".split("|")),t=i.arrayToMap("NULL|NA|TRUE|FALSE|T|F|Inf|NaN|NA_integer_|NA_real_|NA_character_|NA_complex_".split("|"));this.$rules={start:[{token:"comment.sectionhead",regex:"#+(?!').*(?:----|====|####)\\s*$"},{token:"comment",regex:"#+'",next:"rd-start"},{token:"comment",regex:"#.*$"},{token:"string",regex:'["]',next:"qqstring"},{token:"string",regex:"[']",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+[Li]?\\b"},{token:"constant.numeric",regex:"\\d+L\\b"},{token:"constant.numeric",regex:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b"},{token:"constant.numeric",regex:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b"},{token:"constant.language.boolean",regex:"(?:TRUE|FALSE|T|F)\\b"},{token:"identifier",regex:"`.*?`"},{token:function(n){return e[n]?"keyword":t[n]?"constant.language":n=="..."||n.match(/^\.\.\d+$/)?"variable.language":"identifier"},regex:"[a-zA-Z.][a-zA-Z0-9._]*\\b"},{token:"keyword.operator",regex:"%%|>=|<=|==|!=|\\->|<\\-|\\|\\||&&|=|\\+|\\-|\\*|/|\\^|>|<|!|&|\\||~|\\$|:"},{token:"keyword.operator",regex:"%.*?%"},{token:"paren.keyword.operator",regex:"[[({]"},{token:"paren.keyword.operator",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]};var n=(new o("comment")).getRules();for(var r=0;r"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:"^=end\\s.*$",next:"start"},{token:"comment",regex:".+"}]}};r.inherits(c,i),t.RubyHighlightRules=c}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u"},{token:"keyword",regex:"(?:use|include)"},{token:e,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]},this.embedRules(s,"doc-",[s.getEndRule("start")])};r.inherits(u,o),t.scadHighlightRules=u}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-scala.js b/common/static/js/vendor/ace/mode-scala.js new file mode 100644 index 0000000000..66e0a8aa06 --- /dev/null +++ b/common/static/js/vendor/ace/mode-scala.js @@ -0,0 +1 @@ +ace.define("ace/mode/scala",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/scala_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./javascript").Mode,s=e("../tokenizer").Tokenizer,o=e("./scala_highlight_rules").ScalaHighlightRules,u=function(){i.call(this),this.$tokenizer=new s((new o).getRules())};r.inherits(u,i),function(){this.createWorker=function(e){return null}}.call(u.prototype),t.Mode=u}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/scala_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e="case|default|do|else|for|if|match|while|throw|return|try|catch|finally|yield|abstract|class|def|extends|final|forSome|implicit|implicits|import|lazy|new|object|override|package|private|protected|sealed|super|this|trait|type|val|var|with",t="true|false",n="AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object|Unit|Any|AnyVal|AnyRef|Null|ScalaObject|Singleton|Seq|Iterable|List|Option|Array|Char|Byte|Short|Int|Long|Nothing",r=this.createKeywordMapper({"variable.language":"this",keyword:e,"support.function":n,"constant.language":t},"identifier");this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'"""',next:"tstring"},{token:"string",regex:'"(?=.)',next:"string"},{token:"symbol.constant",regex:"'[\\w\\d_]+"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],string:[{token:"escape",regex:'\\\\"'},{token:"string",regex:'"',next:"start"},{token:"string.invalid",regex:'[^"\\\\]*$',next:"start"},{token:"string",regex:'[^"\\\\]+'}],tstring:[{token:"string",regex:'"{3,5}',next:"start"},{token:"string",regex:".+?"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.ScalaHighlightRules=o}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-scss.js b/common/static/js/vendor/ace/mode-scss.js new file mode 100644 index 0000000000..d3e6260d27 --- /dev/null +++ b/common/static/js/vendor/ace/mode-scss.js @@ -0,0 +1 @@ +ace.define("ace/mode/scss",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/scss_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./scss_highlight_rules").ScssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./folding/cstyle").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/scss_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=i.arrayToMap(function(){var e="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),t="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),n="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),r=[];for(var i=0,s=e.length;i|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}]}};r.inherits(o,s),t.ScssHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-sh.js b/common/static/js/vendor/ace/mode-sh.js new file mode 100644 index 0000000000..1debff2353 --- /dev/null +++ b/common/static/js/vendor/ace/mode-sh.js @@ -0,0 +1 @@ +ace.define("ace/mode/sh",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/sh_highlight_rules","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./sh_highlight_rules").ShHighlightRules,u=e("../range").Range,a=function(){this.$tokenizer=new s((new o).getRules())};r.inherits(a,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)#/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var a=new u(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);a.start.row=o,a.end.row=o,a.end.column=l[0].length,t.replace(a,l[1])}}else t.indentRows(n,r,"#")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[\:]\s*$/);o&&(r+=n)}return r};var e={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(t,n,r){if(r!=="\r\n"&&r!=="\r"&&r!=="\n")return!1;var i=this.$tokenizer.getLineTokens(n.trim(),t).tokens;if(!i)return!1;do var s=i.pop();while(s&&(s.type=="comment"||s.type=="text"&&s.value.match(/^\s+$/)));return s?s.type=="keyword"&&e[s.value]:!1},this.autoOutdent=function(e,t,n){n+=1;var r=this.$getIndent(t.getLine(n)),i=t.getTabString();r.slice(-i.length)==i&&t.remove(new u(n,r.length-i.length,n,r.length))}}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/sh_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=t.reservedKeywords="!|{|}|case|do|done|elif|else|esac|fi|for|if|in|then|until|while|&|;|export|local|read|typeset|unset|elif|select|set",o=t.languageConstructs="[|]|alias|bg|bind|break|builtin|cd|command|compgen|complete|continue|dirs|disown|echo|enable|eval|exec|exit|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|popd|printf|pushd|pwd|return|set|shift|shopt|source|suspend|test|times|trap|type|ulimit|umask|unalias|wait",u=function(){var e=this.createKeywordMapper({keyword:s,"support.function.builtin":o,"invalid.deprecated":"debugger"},"identifier"),t="(?:(?:[1-9]\\d*)|(?:0))",n="(?:\\.\\d+)",r="(?:\\d+)",i="(?:(?:"+r+"?"+n+")|(?:"+r+"\\.))",u="(?:(?:"+i+"|"+r+")"+")",a="(?:"+u+"|"+i+")",f="(?:&"+r+")",l="[a-zA-Z][a-zA-Z0-9_]*",c="(?:(?:\\$"+l+")|(?:"+l+"=))",h="(?:\\$(?:SHLVL|\\$|\\!|\\?))",p="(?:"+l+"\\s*\\(\\))";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:'"(?:[^\\\\]|\\\\.)*?"'},{token:"variable.language",regex:h},{token:"variable",regex:c},{token:"support.function",regex:p},{token:"support.function",regex:f},{token:"string",regex:"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:a},{token:"constant.numeric",regex:t+"\\b"},{token:e,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|~|<|>|<=|=>|=|!="},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}]}};r.inherits(u,i),t.ShHighlightRules=u}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-sql.js b/common/static/js/vendor/ace/mode-sql.js new file mode 100644 index 0000000000..a3f6ec87da --- /dev/null +++ b/common/static/js/vendor/ace/mode-sql.js @@ -0,0 +1 @@ +ace.define("ace/mode/sql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/sql_highlight_rules","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./sql_highlight_rules").SqlHighlightRules,u=e("../range").Range,a=function(){this.$tokenizer=new s((new o).getRules())};r.inherits(a,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=[],o=/^(\s*)--/;for(var a=n;a<=r;a++)if(!o.test(t.getLine(a))){i=!1;break}if(i){var f=new u(0,0,0,0);for(var a=n;a<=r;a++){var l=t.getLine(a),c=l.match(o);f.start.row=a,f.end.row=a,f.end.column=c[0].length,t.replace(f,c[1])}}else t.indentRows(n,r,"--")}}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/sql_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="select|insert|update|delete|from|where|and|or|group|by|order|limit|offset|having|as|case|when|else|end|type|left|right|join|on|outer|desc|asc",t="true|false|null",n="count|min|max|avg|sum|rank|now|coalesce",r=this.createKeywordMapper({"support.function":n,keyword:e,"constant.language":t},"identifier",!0);this.$rules={start:[{token:"comment",regex:"--.*$"},{token:"string",regex:'".*?"'},{token:"string",regex:"'.*?'"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"text",regex:"\\s+"}]}};r.inherits(s,i),t.SqlHighlightRules=s}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-stylus.js b/common/static/js/vendor/ace/mode-stylus.js new file mode 100644 index 0000000000..2356da0870 --- /dev/null +++ b/common/static/js/vendor/ace/mode-stylus.js @@ -0,0 +1 @@ +ace.define("ace/mode/stylus",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/stylus_highlight_rules","ace/mode/folding/coffee"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./stylus_highlight_rules").StylusHighlightRules,u=e("./folding/coffee").FoldMode,a=function(){var e=new o;this.foldingRules=new u,this.$tokenizer=new s(e.getRules())};r.inherits(a,i),function(){}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/stylus_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/css_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=e("./css_highlight_rules"),o=function(){var e=this.createKeywordMapper({"support.type":s.supportType,"support.function":s.supportFunction,"support.constant":s.supportConstant,"support.constant.color":s.supportConstantColor,"support.constant.fonts":s.supportConstantFonts},"text",!0);this.$rules={start:[{token:"comment",regex:/\/\/.*$/},{token:"comment",regex:/\/\*/,next:"comment"},{token:["entity.name.function.stylus","text"],regex:"^([-a-zA-Z_][-\\w]*)?(\\()"},{token:["entity.other.attribute-name.class.stylus"],regex:"\\.-?[_a-zA-Z]+[_a-zA-Z0-9-]*"},{token:["entity.language.stylus"],regex:"^ *&"},{token:["variable.language.stylus"],regex:"(arguments)"},{token:["keyword.stylus"],regex:"@[-\\w]+"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:s.pseudoElements},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:s.pseudoClasses},{token:["entity.name.tag.stylus"],regex:"(?:\\b)(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|datalist|dd|del|details|dfn|dialog|div|dl|dt|em|eventsource|fieldset|figure|figcaption|footer|form|frame|frameset|(?:h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|label|legend|li|link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|samp|script|section|select|small|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)(?:\\b)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation.definition.entity.stylus","entity.other.attribute-name.id.stylus"],regex:"(#)([a-zA-Z][a-zA-Z0-9_-]*)"},{token:"meta.vendor-prefix.stylus",regex:"-webkit-|-moz\\-|-ms-|-o-"},{token:"keyword.control.stylus",regex:"(?:!important|for|in|return|true|false|null|if|else|unless|return)\\b"},{token:"keyword.operator.stylus",regex:"!|~|\\+|-|(?:\\*)?\\*|\\/|%|(?:\\.)\\.\\.|<|>|(?:=|:|\\?|\\+|-|\\*|\\/|%|<|>)?=|!="},{token:"keyword.operator.stylus",regex:"(?:in|is(?:nt)?|not)\\b"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:s.numRe},{token:"keyword",regex:"(?:ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)\\b"},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"}],qstring:[{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"}]}};r.inherits(o,i),t.StylusHighlightRules=o}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},i.tag(this.$rules,"tag","start")};r.inherits(o,s),t.XmlHighlightRules=o}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../lib/lang"),s=e("../../range").Range,o=e("./fold_mode").FoldMode,u=e("../../token_iterator").TokenIterator,a=t.FoldMode=function(e){o.call(this),this.voidElements=e||{}};r.inherits(a,o),function(){this.getFoldWidget=function(e,t,n){var r=this._getFirstTagInLine(e,n);return r.closing?t=="markbeginend"?"end":"":!r.tagName||this.voidElements[r.tagName.toLowerCase()]?"":r.selfClosing?"":r.value.indexOf("/"+r.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(e,t){var n=e.getTokens(t),r="";for(var s=0;s?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/svg_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/xml_util"],function(e,t,n){var r=e("../lib/oop"),i=e("./javascript_highlight_rules").JavaScriptHighlightRules,s=e("./xml_highlight_rules").XmlHighlightRules,o=e("./xml_util"),u=function(){s.call(this),this.$rules.start.splice(3,0,{token:"meta.tag",regex:"<(?=script)",next:"script"}),o.tag(this.$rules,"script","js-start"),this.embedRules(i,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}])};r.inherits(u,s),t.SvgHighlightRules=u}),ace.define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=t.FoldMode=function(e,t){this.defaultMode=e,this.subModes=t};r.inherits(s,i),function(){this.$getMode=function(e){for(var t in this.subModes)if(e.indexOf(t)===0)return this.subModes[t];return null},this.$tryMode=function(e,t,n,r){var i=this.$getMode(e);return i?i.getFoldWidget(t,n,r):""},this.getFoldWidget=function(e,t,n){return this.$tryMode(e.getState(n-1),e,t,n)||this.$tryMode(e.getState(n),e,t,n)||this.defaultMode.getFoldWidget(e,t,n)},this.getFoldWidgetRange=function(e,t,n){var r=this.$getMode(e.getState(n-1));if(!r||!r.getFoldWidget(e,t,n))r=this.$getMode(e.getState(n));if(!r||!r.getFoldWidget(e,t,n))r=this.defaultMode;return r.getFoldWidgetRange(e,t,n)}}.call(s.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-tcl.js b/common/static/js/vendor/ace/mode-tcl.js new file mode 100644 index 0000000000..dd658f6324 --- /dev/null +++ b/common/static/js/vendor/ace/mode-tcl.js @@ -0,0 +1 @@ +ace.define("ace/mode/tcl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/folding/cstyle","ace/mode/tcl_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./folding/cstyle").FoldMode,u=e("./tcl_highlight_rules").TclHighlightRules,a=e("./matching_brace_outdent").MatchingBraceOutdent,f=e("../range").Range,l=function(){this.$tokenizer=new s((new u).getRules()),this.$outdent=new a,this.foldingRules=new o};r.inherits(l,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)#/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new f(0,0,0,0);for(var o=n;o<=r;o++){var a=t.getLine(o),l=a.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"#")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[]\s*$/);o&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/tcl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*\\\\$",next:"commentfollow"},{token:"comment",regex:"#.*$"},{token:"support.function",regex:"[\\\\]$",next:"splitlineStart"},{token:"text",regex:'[\\\\](?:["]|[{]|[}]|[[]|[]]|[$]|[])'},{token:"text",regex:"^|[^{][;][^}]|[/\r/]",next:"commandItem"},{token:"string",regex:'[ ]*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'[ ]*["]',next:"qqstring"},{token:"variable.instancce",regex:"[$]",next:"variable"},{token:"support.function",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|{\\*}|;|::"},{token:"identifier",regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"paren.lparen",regex:"[[{]",next:"commandItem"},{token:"paren.lparen",regex:"[(]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],commandItem:[{token:"comment",regex:"#.*\\\\$",next:"commentfollow"},{token:"comment",regex:"#.*$",next:"start"},{token:"string",regex:'[ ]*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"variable.instancce",regex:"[$]",next:"variable"},{token:"support.function",regex:"(?:[:][:])[a-zA-Z0-9_/]+(?:[:][:])",next:"commandItem"},{token:"support.function",regex:"[a-zA-Z0-9_/]+(?:[:][:])",next:"commandItem"},{token:"support.function",regex:"(?:[:][:])",next:"commandItem"},{token:"support.function",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|{\\*}|;|::"},{token:"keyword",regex:"[a-zA-Z0-9_/]+",next:"start"}],commentfollow:[{token:"comment",regex:".*\\\\$",next:"commentfollow"},{token:"comment",regex:".+",next:"start"}],splitlineStart:[{token:"text",regex:"^.",next:"start"}],variable:[{token:"variable.instance",regex:"(?:[:][:])?[a-zA-Z_\\d]+(?:(?:[:][:])?[a-zA-Z_\\d]+)?(?:[(][a-zA-Z_\\d]+[)])?",next:"start"},{token:"variable.instance",regex:"[a-zA-Z_\\d]+(?:[(][a-zA-Z_\\d]+[)])?",next:"start"},{token:"variable.instance",regex:"{?[a-zA-Z_\\d]+}?",next:"start"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?["]',next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.TclHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-tex.js b/common/static/js/vendor/ace/mode-tex.js new file mode 100644 index 0000000000..9e61429c63 --- /dev/null +++ b/common/static/js/vendor/ace/mode-tex.js @@ -0,0 +1 @@ +ace.define("ace/mode/tex",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/tex_highlight_rules","ace/mode/matching_brace_outdent"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./text_highlight_rules").TextHighlightRules,u=e("./tex_highlight_rules").TexHighlightRules,a=e("./matching_brace_outdent").MatchingBraceOutdent,f=function(e){e?this.$tokenizer=new s((new o).getRules()):this.$tokenizer=new s((new u).getRules()),this.$outdent=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.allowAutoInsert=function(){return!1}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/tex_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(e){e||(e="text"),this.$rules={start:[{token:"comment",regex:"%.*$"},{token:e,regex:"\\\\[$&%#\\{\\}]"},{token:"keyword",regex:"\\\\(?:documentclass|usepackage|newcounter|setcounter|addtocounter|value|arabic|stepcounter|newenvironment|renewenvironment|ref|vref|eqref|pageref|label|cite[a-zA-Z]*|tag|begin|end|bibitem)\\b",next:"nospell"},{token:"keyword",regex:"\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])"},{token:"paren.keyword.operator",regex:"[[({]"},{token:"paren.keyword.operator",regex:"[\\])}]"},{token:e,regex:"\\s+"}],nospell:[{token:"comment",regex:"%.*$",next:"start"},{token:"nospell."+e,regex:"\\\\[$&%#\\{\\}]"},{token:"keyword",regex:"\\\\(?:documentclass|usepackage|newcounter|setcounter|addtocounter|value|arabic|stepcounter|newenvironment|renewenvironment|ref|vref|eqref|pageref|label|cite[a-zA-Z]*|tag|begin|end|bibitem)\\b"},{token:"keyword",regex:"\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])",next:"start"},{token:"paren.keyword.operator",regex:"[[({]"},{token:"paren.keyword.operator",regex:"[\\])]"},{token:"paren.keyword.operator",regex:"}",next:"start"},{token:"nospell."+e,regex:"\\s+"},{token:"nospell."+e,regex:"\\w+"}]}};r.inherits(o,s),t.TexHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-text.js b/common/static/js/vendor/ace/mode-text.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/static/js/vendor/ace/mode-textile.js b/common/static/js/vendor/ace/mode-textile.js new file mode 100644 index 0000000000..0cd1228332 --- /dev/null +++ b/common/static/js/vendor/ace/mode-textile.js @@ -0,0 +1 @@ +ace.define("ace/mode/textile",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/textile_highlight_rules","ace/mode/matching_brace_outdent"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./textile_highlight_rules").TextileHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u};r.inherits(a,i),function(){this.getNextLineIndent=function(e,t,n){return e=="intag"?n:""},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(a.prototype),t.Mode=a}),ace.define("ace/mode/textile_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:function(e){return e.charAt(0)=="h"?"markup.heading."+e.charAt(1):"markup.heading"},regex:"h1|h2|h3|h4|h5|h6|bq|p|bc|pre",next:"blocktag"},{token:"keyword",regex:"[\\*]+|[#]+"},{token:"text",regex:".+"}],blocktag:[{token:"keyword",regex:"\\. ",next:"start"},{token:"keyword",regex:"\\(",next:"blocktagproperties"}],blocktagproperties:[{token:"keyword",regex:"\\)",next:"blocktag"},{token:"string",regex:"[a-zA-Z0-9\\-_]+"},{token:"keyword",regex:"#"}]}};r.inherits(s,i),t.TextileHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-typescript.js b/common/static/js/vendor/ace/mode-typescript.js new file mode 100644 index 0000000000..ff04abce46 --- /dev/null +++ b/common/static/js/vendor/ace/mode-typescript.js @@ -0,0 +1 @@ +ace.define("ace/mode/typescript",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/typescript_highlight_rules","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/mode/matching_brace_outdent"],function(e,t,n){var r=e("../lib/oop"),i=e("./javascript").Mode,s=e("../tokenizer").Tokenizer,o=e("./typescript_highlight_rules").TypeScriptHighlightRules,u=e("./behaviour/cstyle").CstyleBehaviour,a=e("./folding/cstyle").FoldMode,f=e("./matching_brace_outdent").MatchingBraceOutdent,l=function(){var e=new o;this.$tokenizer=new s(e.getRules()),this.$outdent=new f,this.$behaviour=new u,this.foldingRules=new a};r.inherits(l,i),function(){this.createWorker=function(e){return null}}.call(l.prototype),t.Mode=l}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../range").Range,f=e("../worker/worker_client").WorkerClient,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new l,this.foldingRules=new c};r.inherits(h,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)\/\//;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"//")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="regex_allowed"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||e=="regex_allowed")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("jslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(h.prototype),t.Mode=h}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert"},"identifier"),t="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",n="[a-zA-Z\\$_¡-ï¿¿][a-zA-Z\\d\\$_¡-ï¿¿]*\\b",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},i.getStartRule("doc-start"),{token:"comment",regex:/\/\*/,next:"comment"},{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+n+")(\\.)(prototype)(\\.)("+n+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+n+")(\\.)("+n+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+n+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+n+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+t+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:e,regex:n},{token:"keyword.operator",regex:/--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start"},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",next:"regex_allowed"},{token:"comment",regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"start"},{token:"string",regex:".|\\w+|\\s+"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"start"},{token:"string",regex:".|\\w+|\\s+"}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc",regex:"TODO"},{token:"comment.doc",regex:"[^@\\*]+"},{token:"comment.doc",regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}),ace.define("ace/mode/typescript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/javascript_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./javascript_highlight_rules").JavaScriptHighlightRules,s=function(){var e=[{token:["keyword.operator.ts","text","variable.parameter.function.ts","text"],regex:"\\b(module)(\\s*)([a-zA-Z0-9_?.$][\\w?.$]*)(\\s*\\{)"},{token:["storage.type.variable.ts","text","keyword.other.ts","text"],regex:"(super)(\\s*\\()([a-zA-Z0-9,_?.$\\s]+\\s*)(\\))"},{token:["entity.name.function.ts","paren.lparen","paren.rparen"],regex:"([a-zA-Z_?.$][\\w?.$]*)(\\()(\\))"},{token:["variable.parameter.function.ts","text","variable.parameter.function.ts"],regex:"([a-zA-Z0-9_?.$][\\w?.$]*)(\\s*:\\s*)([a-zA-Z0-9_?.$][\\w?.$]*)"},{token:["keyword.operator.ts"],regex:"(?:\\b(constructor|declare|interface|as|AS|public|private|class|extends|export|super)\\b)"},{token:["storage.type.variable.ts"],regex:"(?:\\b(this\\.|string\\b|bool\\b|number)\\b)"},{token:["keyword.operator.ts","storage.type.variable.ts","keyword.operator.ts","storage.type.variable.ts"],regex:"(class)(\\s+[a-zA-Z0-9_?.$][\\w?.$]*\\s+)(extends)(\\s+[a-zA-Z0-9_?.$][\\w?.$]*\\s+)?"},{token:"keyword",regex:"(?:super|export|class|extends|import)\\b"}],t=(new i).getRules();t.start=e.concat(t.start),this.$rules=t};r.inherits(s,i),t.TypeScriptHighlightRules=s}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-vbscript.js b/common/static/js/vendor/ace/mode-vbscript.js new file mode 100644 index 0000000000..9bfd41eca2 --- /dev/null +++ b/common/static/js/vendor/ace/mode-vbscript.js @@ -0,0 +1 @@ +ace.define("ace/mode/vbscript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/vbscript_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./vbscript_highlight_rules").VBScriptHighlightRules,u=function(){var e=new o;this.$tokenizer=new s(e.getRules())};r.inherits(u,i),function(){}.call(u.prototype),t.Mode=u}),ace.define("ace/mode/vbscript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:["meta.ending-space"],regex:"$"},{token:[null],regex:"^(?=\\t)",next:"state_3"},{token:[null],regex:"^(?= )",next:"state_4"},{token:["storage.type.function.asp","text","entity.name.function.asp","text","punctuation.definition.parameters.asp","variable.parameter.function.asp","punctuation.definition.parameters.asp"],regex:"^\\s*((?:Function|Sub))(\\s*)([a-zA-Z_]\\w*)(\\s*)(\\()([^)]*)(\\)).*\\n?"},{token:"punctuation.definition.comment.asp",regex:"'|REM",next:"comment"},{token:["keyword.control.asp"],regex:"(?:\\b(If|Then|Else|ElseIf|Else If|End If|While|Wend|For|To|Each|Case|Select|End Select|Return|Continue|Do|Until|Loop|Next|With|Exit Do|Exit For|Exit Function|Exit Property|Exit Sub|IIf)\\b)"},{token:["keyword.operator.asp"],regex:"(?:\\b(Mod|And|Not|Or|Xor|as)\\b)"},{token:["storage.type.asp"],regex:"Dim|Call|Class|Const|Dim|Redim|Function|Sub|Private Sub|Public Sub|End sub|End Function|Set|Let|Get|New|Randomize|Option Explicit|On Error Resume Next|On Error GoTo"},{token:["storage.modifier.asp"],regex:"(?:\\b(Private|Public|Default)\\b)"},{token:["constant.language.asp"],regex:"(?:\\s*\\b(Empty|False|Nothing|Null|True)\\b)"},{token:["punctuation.definition.string.begin.asp"],regex:'"',next:"string"},{token:["punctuation.definition.variable.asp"],regex:"(\\$)[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*?\\b\\s*"},{token:["support.class.asp"],regex:"(?:\\b(Application|ObjectContext|Request|Response|Server|Session)\\b)"},{token:["support.class.collection.asp"],regex:"(?:\\b(Contents|StaticObjects|ClientCertificate|Cookies|Form|QueryString|ServerVariables)\\b)"},{token:["support.constant.asp"],regex:"(?:\\b(TotalBytes|Buffer|CacheControl|Charset|ContentType|Expires|ExpiresAbsolute|IsClientConnected|PICS|Status|ScriptTimeout|CodePage|LCID|SessionID|Timeout)\\b)"},{token:["support.function.asp"],regex:"(?:\\b(Lock|Unlock|SetAbort|SetComplete|BianryRead|AddHeader|AppendToLog|BinaryWrite|Clear|End|Flush|Redirect|Write|CreateObject|HTMLEncode|MapPath|URLEncode|Abandon|Convert|Regex)\\b)"},{token:["support.function.event.asp"],regex:"(?:\\b(Application_OnEnd|Application_OnStart|OnTransactionAbort|OnTransactionCommit|Session_OnEnd|Session_OnStart)\\b)"},{token:["support.function.vb.asp"],regex:"(?:\\b(Array|Add|Asc|Atn|CBool|CByte|CCur|CDate|CDbl|Chr|CInt|CLng|Conversions|Cos|CreateObject|CSng|CStr|Date|DateAdd|DateDiff|DatePart|DateSerial|DateValue|Day|Derived|Math|Escape|Eval|Exists|Exp|Filter|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent|GetLocale|GetObject|GetRef|Hex|Hour|InputBox|InStr|InStrRev|Int|Fix|IsArray|IsDate|IsEmpty|IsNull|IsNumeric|IsObject|Item|Items|Join|Keys|LBound|LCase|Left|Len|LoadPicture|Log|LTrim|RTrim|Trim|Maths|Mid|Minute|Month|MonthName|MsgBox|Now|Oct|Remove|RemoveAll|Replace|RGB|Right|Rnd|Round|ScriptEngine|ScriptEngineBuildVersion|ScriptEngineMajorVersion|ScriptEngineMinorVersion|Second|SetLocale|Sgn|Sin|Space|Split|Sqr|StrComp|String|StrReverse|Tan|Time|Timer|TimeSerial|TimeValue|TypeName|UBound|UCase|Unescape|VarType|Weekday|WeekdayName|Year)\\b)"},{token:["constant.numeric.asp"],regex:"-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)(?:L|l|UL|ul|u|U|F|f)?\\b"},{token:["support.type.vb.asp"],regex:"(?:\\b(vbtrue|fvbalse|vbcr|vbcrlf|vbformfeed|vblf|vbnewline|vbnullchar|vbnullstring|int32|vbtab|vbverticaltab|vbbinarycompare|vbtextcomparevbsunday|vbmonday|vbtuesday|vbwednesday|vbthursday|vbfriday|vbsaturday|vbusesystemdayofweek|vbfirstjan1|vbfirstfourdays|vbfirstfullweek|vbgeneraldate|vblongdate|vbshortdate|vblongtime|vbshorttime|vbobjecterror|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant|vbDataObject|vbDecimal|vbByte|vbArray)\\b)"},{token:["entity.name.function.asp"],regex:"(?:(\\b[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*?\\b)(?=\\(\\)?))"},{token:["keyword.operator.asp"],regex:"\\-|\\+|\\*\\/|\\>|\\<|\\=|\\&"}],state_3:[{token:["meta.odd-tab.tabs","meta.even-tab.tabs"],regex:"(\\t)(\\t)?"},{token:"meta.leading-space",regex:"(?=[^\\t])",next:"start"},{token:"meta.leading-space",regex:".",next:"state_3"}],state_4:[{token:["meta.odd-tab.spaces","meta.even-tab.spaces"],regex:"( )( )?"},{token:"meta.leading-space",regex:"(?=[^ ])",next:"start"},{token:"meta.leading-space",regex:".",next:"state_4"}],comment:[{token:"comment.line.apostrophe.asp",regex:"$|(?=(?:%>))",next:"start"},{token:"comment.line.apostrophe.asp",regex:"."}],string:[{token:"constant.character.escape.apostrophe.asp",regex:'""'},{token:"string.quoted.double.asp",regex:'"',next:"start"},{token:"string.quoted.double.asp",regex:"."}]}};r.inherits(s,i),t.VBScriptHighlightRules=s}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-xml.js b/common/static/js/vendor/ace/mode-xml.js new file mode 100644 index 0000000000..ae20199e51 --- /dev/null +++ b/common/static/js/vendor/ace/mode-xml.js @@ -0,0 +1 @@ +ace.define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./xml_highlight_rules").XmlHighlightRules,u=e("./behaviour/xml").XmlBehaviour,a=e("./folding/xml").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules()),this.$behaviour=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./xml_util"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"xml-pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}]},i.tag(this.$rules,"tag","start")};r.inherits(o,s),t.XmlHighlightRules=o}),ace.define("ace/mode/xml_util",["require","exports","module"],function(e,t,n){function r(e){return[{token:"string",regex:'"',next:e+"_qqstring"},{token:"string",regex:"'",next:e+"_qstring"}]}function i(e,t){return[{token:"string",regex:e,next:t},{token:"constant.language.escape",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"string",regex:"\\w+|.|\\s+"}]}t.tag=function(e,t,n,s){e[t]=[{token:"text",regex:"\\s+"},{token:s?function(e){return s[e]?"meta.tag.tag-name."+s[e]:"meta.tag.tag-name"}:"meta.tag.tag-name",regex:"[-_a-zA-Z0-9:]+",next:t+"_embed_attribute_list"},{token:"empty",regex:"",next:t+"_embed_attribute_list"}],e[t+"_qstring"]=i("'",t+"_embed_attribute_list"),e[t+"_qqstring"]=i('"',t+"_embed_attribute_list"),e[t+"_embed_attribute_list"]=[{token:"meta.tag.r",regex:"/?>",next:n},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(r(t))}}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){function u(e,t){var n=!0,r=e.type.split("."),i=t.split(".");return i.forEach(function(e){if(r.indexOf(e)==-1)return n=!1,!1}),n}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,a=function(){this.inherit(s,["string_dquotes"]),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var s=n.getCursorPosition(),a=new o(r,s.row,s.column),f=a.getCurrentToken(),l=!1;if(!f||!u(f,"meta.tag")&&(!u(f,"text")||!f.value.match("/"))){do f=a.stepBackward();while(f&&(u(f,"string")||u(f,"keyword.operator")||u(f,"entity.attribute-name")||u(f,"text")))}else l=!0;if(!f||!u(f,"meta.tag-name")||a.stepBackward().value.match("/"))return;var c=f.value;if(l)var c=c.substring(0,s.column-f.start);return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+2);if(u=="-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../lib/lang"),s=e("../../range").Range,o=e("./fold_mode").FoldMode,u=e("../../token_iterator").TokenIterator,a=t.FoldMode=function(e){o.call(this),this.voidElements=e||{}};r.inherits(a,o),function(){this.getFoldWidget=function(e,t,n){var r=this._getFirstTagInLine(e,n);return r.closing?t=="markbeginend"?"end":"":!r.tagName||this.voidElements[r.tagName.toLowerCase()]?"":r.selfClosing?"":r.value.indexOf("/"+r.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(e,t){var n=e.getTokens(t),r="";for(var s=0;s?)/,this._parseTag=function(e){var t=this.tagRe.exec(e),n=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:e,match:t?t[2]:"",closing:t?!!t[3]:!1,selfClosing:t?!!t[5]||t[2]=="/>":!1,tagName:t?t[4]:"",column:t[1]?n+t[1].length:n}},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){if(!r)var r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()};n+=t.value;if(n.indexOf(">")!==-1){var i=this._parseTag(n);return i.start=r,i.end={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length},e.stepForward(),i}}while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n="",r;do if(t.type.indexOf("meta.tag")===0){r||(r={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()+t.value.length}),n=t.value+n;if(n.indexOf("<")!==-1){var i=this._parseTag(n);return i.end=r,i.start={row:e.getCurrentTokenRow(),column:e.getCurrentTokenColumn()},e.stepBackward(),i}}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.voidElements[t.tagName])return;if(this.voidElements[n.tagName]){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r.match)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.column),l={row:n,column:r.column+r.tagName.length+2};while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.column+r.match.length),c={row:n,column:r.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,s.fromPoints(a.start,c)}else o.push(a)}}}}.call(a.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-xquery.js b/common/static/js/vendor/ace/mode-xquery.js new file mode 100644 index 0000000000..e81da5222b --- /dev/null +++ b/common/static/js/vendor/ace/mode-xquery.js @@ -0,0 +1 @@ +ace.define("ace/mode/xquery",["require","exports","module","ace/worker/worker_client","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xquery_highlight_rules","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../worker/worker_client").WorkerClient,i=e("../lib/oop"),s=e("./text").Mode,o=e("../tokenizer").Tokenizer,u=e("./xquery_highlight_rules").XQueryHighlightRules,a=e("../range").Range,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(e){this.$tokenizer=new o((new u).getRules()),this.$behaviour=new f(e),this.foldingRules=new l};i.inherits(c,s),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=t.match(/\s*(?:then|else|return|[{\(]|<\w+>)\s*$/);return i&&(r+=n),r},this.checkOutdent=function(e,t,n){return/^\s+$/.test(t)?/^\s*[\}\)]/.test(n):!1},this.autoOutdent=function(e,t,n){var r=t.getLine(n),i=r.match(/^(\s*[\}\)])/);if(!i)return 0;var s=i[1].length,o=t.findMatchingBracket({row:n,column:s});if(!o||o.row==n)return 0;var u=this.$getIndent(t.getLine(o.row));t.replace(new a(n,0,n,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""},this.toggleCommentLines=function(e,t,n,r){var i,s,o=!0,u=/^\s*\(:(.*):\)/;for(i=n;i<=r;i++)if(!u.test(t.getLine(i))){o=!1;break}var f=new a(0,0,0,0);for(i=n;i<=r;i++)s=t.getLine(i),f.start.row=i,f.end.row=i,f.end.column=s.length,t.replace(f,o?s.match(u)[1]:"(:"+s+":)")},this.createWorker=function(e){this.$deltas=[];var t=new r(["ace"],"ace/mode/xquery_worker","XQueryWorker"),n=this;return e.getDocument().on("change",function(e){n.$deltas.push(e.data)}),t.attachToDocument(e.getDocument()),t.on("start",function(e){n.$deltas=[]}),t.on("error",function(t){e.setAnnotations([t.data])}),t.on("ok",function(t){e.clearAnnotations()}),t.on("highlight",function(t){if(n.$deltas.length>0)return;var r=0,i=e.getLength()-1,s=t.data.lines,o=t.data.states;e.bgTokenizer.lines=s,e.bgTokenizer.states=o,e.bgTokenizer.fireUpdateEvent(r,i)}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/xquery_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="after|ancestor|ancestor-or-self|and|as|ascending|attribute|before|case|cast|castable|child|collation|comment|copy|count|declare|default|delete|descendant|descendant-or-self|descending|div|document|document-node|element|else|empty|empty-sequence|end|eq|every|except|first|following|following-sibling|for|function|ge|group|gt|idiv|if|import|insert|instance|intersect|into|is|item|last|le|let|lt|mod|modify|module|namespace|namespace-node|ne|node|only|or|order|ordered|parent|preceding|preceding-sibling|processing-instruction|rename|replace|return|satisfies|schema-attribute|schema-element|self|some|stable|start|switch|text|to|treat|try|typeswitch|union|unordered|validate|where|with|xquery|contains|paragraphs|sentences|times|words|by|collectionreturn|variable|version|option|when|encoding|toswitch|catch|tumbling|sliding|window|at|using|stemming|collection|schema|while|on|nodes|index|external|then|in|updating|value|of|containsbreak|loop|continue|exit|returning|append|json|position".split("|"),t="[_A-Za-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌-â€â°-â†â°€-⿯ã€-퟿豈-ï·ï·°-�]",n="[-._A-Za-z0-9·À-ÖØ-öø-˿̀-ͽͿ-῿‌â€â€¿â€â°-â†â°€-⿯ã€-퟿豈-ï·ï·°-�]",r=t+n+"*",i="(?:"+r+":)?"+r,s="(?:(?:Q{.*}"+r+")|(?:"+i+"))";this.$rules={start:[{token:"support.type",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml-pe",regex:"<\\?",next:"pi"},{token:"comment",regex:"<\\!--",next:"xmlcomment"},{token:"comment.doc",regex:"\\(:~",next:"comment.doc"},{token:"comment",regex:"\\(:",next:"comment"},{token:["text","meta.tag"],regex:"(<\\/?)("+i+")",next:"tag"},{token:"constant",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"variable",regex:"\\$"+s},{token:"string",regex:"'",next:"apos-string"},{token:"string",regex:'"',next:"quot-string"},{token:"text",regex:"\\s+"},{token:function(t){return e.indexOf(t.toLowerCase())!==-1?"keyword":"support.function"},regex:s},{token:"keyword.operator",regex:"\\*|:=|=|<|>|\\-|\\+"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"}],tag:[{token:"text",regex:"\\/?>",next:"start"},{token:["text","meta.tag"],regex:"(<\\/)("+i+")",next:"start"},{token:"meta.tag",regex:i},{token:"text",regex:"\\s+"},{token:"string",regex:"'",next:"apos-attr"},{token:"string",regex:'"',next:"quot-attr"},{token:"string",regex:"'.*?'"},{token:"text",regex:"="}],pi:[{token:"xml-pe",regex:".*\\?>",next:"start"},{token:"xml-pe",regex:".*"}],cdata:[{token:"support.type",regex:"\\]\\]>",next:"start"},{token:"support.type",regex:"\\s+"},{token:"support.type",regex:"(?:[^\\]]|\\](?!\\]>))+"}],"comment.doc":[{token:"comment.doc",regex:":\\)",next:"start"},{token:"comment.doc.tag",regex:"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,6}"},{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",regex:"\\s+"},{token:"comment.doc.tag",regex:"TODO"},{token:"comment.doc",regex:"[^@:^\\s]+"},{token:"comment.doc",regex:"."}],comment:[{token:"comment",regex:".*:\\)",next:"start"},{token:"comment",regex:".+"}],xmlcomment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}],"apos-string":[{token:"string",regex:".*'",next:"start"},{token:"string",regex:".*"}],"quot-string":[{token:"string",regex:'.*"',next:"start"},{token:"string",regex:".*"}],"apos-attr":[{token:"string",regex:".*'",next:"tag"},{token:"string",regex:".*"}],"quot-attr":[{token:"string",regex:'.*"',next:"tag"},{token:"string",regex:".*"}]}};r.inherits(s,i),t.XQueryHighlightRules=s}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/mode-yaml.js b/common/static/js/vendor/ace/mode-yaml.js new file mode 100644 index 0000000000..6a805218bc --- /dev/null +++ b/common/static/js/vendor/ace/mode-yaml.js @@ -0,0 +1 @@ +ace.define("ace/mode/yaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/yaml_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/coffee"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./yaml_highlight_rules").YamlHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./folding/coffee").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"list.markup",regex:/^(?:-{3}|\.{3})\s*(?=#|$)/},{token:"list.markup",regex:/^\s*[\-?](?:$|\s)/},{token:"constant",regex:"!![\\w//]+"},{token:"constant.language",regex:"[&\\*][a-zA-Z0-9-_]+"},{token:["meta.tag","keyword"],regex:/^(\s*\w.*?)(\:(?:\s+|$))/},{token:["meta.tag","keyword"],regex:/(\w+?)(\s*\:(?:\s+|$))/},{token:"keyword.operator",regex:"<<\\w*:\\w*"},{token:"keyword.operator",regex:"-\\s*(?=[{])"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"[\\|>]\\w*",next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:/[+\-]?[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?\b/},{token:"constant.numeric",regex:/[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/},{token:"constant.language.boolean",regex:"(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"},{token:"text",regex:"\\w+"}],qqstring:[{token:"string",regex:"(?=(?:(?:\\\\.)|(?:[^:]))*?:)",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.YamlHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u span {font-weight: normal !important;}.ace-github .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-github .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-github .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-github .ace_gutter-active-line {background-color : rgba(0, 0, 0, 0.07);}.ace-github .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-github .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-github .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-idle_fingers.js b/common/static/js/vendor/ace/theme-idle_fingers.js new file mode 100644 index 0000000000..b15dd60399 --- /dev/null +++ b/common/static/js/vendor/ace/theme-idle_fingers.js @@ -0,0 +1 @@ +ace.define("ace/theme/idle_fingers",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-idle-fingers",t.cssText=".ace-idle-fingers .ace_gutter {background: #3b3b3b;color: #fff}.ace-idle-fingers .ace_print-margin {width: 1px;background: #3b3b3b}.ace-idle-fingers .ace_scroller {background-color: #323232}.ace-idle-fingers .ace_text-layer {color: #FFFFFF}.ace-idle-fingers .ace_cursor {border-left: 2px solid #91FF00}.ace-idle-fingers .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #91FF00}.ace-idle-fingers .ace_marker-layer .ace_selection {background: rgba(90, 100, 126, 0.88)}.ace-idle-fingers.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #323232;border-radius: 2px}.ace-idle-fingers .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-idle-fingers .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-idle-fingers .ace_marker-layer .ace_active-line {background: #353637}.ace-idle-fingers .ace_gutter-active-line {background-color: #353637}.ace-idle-fingers .ace_marker-layer .ace_selected-word {border: 1px solid rgba(90, 100, 126, 0.88)}.ace-idle-fingers .ace_invisible {color: #404040}.ace-idle-fingers .ace_keyword,.ace-idle-fingers .ace_meta {color: #CC7833}.ace-idle-fingers .ace_constant,.ace-idle-fingers .ace_constant.ace_character,.ace-idle-fingers .ace_constant.ace_character.ace_escape,.ace-idle-fingers .ace_constant.ace_other,.ace-idle-fingers .ace_support.ace_constant {color: #6C99BB}.ace-idle-fingers .ace_invalid {color: #FFFFFF;background-color: #FF0000}.ace-idle-fingers .ace_fold {background-color: #CC7833;border-color: #FFFFFF}.ace-idle-fingers .ace_support.ace_function {color: #B83426}.ace-idle-fingers .ace_variable.ace_parameter {font-style: italic}.ace-idle-fingers .ace_string {color: #A5C261}.ace-idle-fingers .ace_string.ace_regexp {color: #CCCC33}.ace-idle-fingers .ace_comment {font-style: italic;color: #BC9458}.ace-idle-fingers .ace_meta.ace_tag {color: #FFE5BB}.ace-idle-fingers .ace_entity.ace_name {color: #FFC66D}.ace-idle-fingers .ace_markup.ace_underline {text-decoration: underline}.ace-idle-fingers .ace_collab.ace_user1 {color: #323232;background-color: #FFF980}.ace-idle-fingers .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMwMjL6zzBz5sz/ABEUBGCqhK6UAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-kr.js b/common/static/js/vendor/ace/theme-kr.js new file mode 100644 index 0000000000..89a7f8c5f4 --- /dev/null +++ b/common/static/js/vendor/ace/theme-kr.js @@ -0,0 +1 @@ +ace.define("ace/theme/kr_theme",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-kr-theme",t.cssText=".ace-kr-theme .ace_gutter {background: #1c1917;color: #FCFFE0}.ace-kr-theme .ace_print-margin {width: 1px;background: #1c1917}.ace-kr-theme .ace_scroller {background-color: #0B0A09}.ace-kr-theme .ace_text-layer {color: #FCFFE0}.ace-kr-theme .ace_cursor {border-left: 2px solid #FF9900}.ace-kr-theme .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #FF9900}.ace-kr-theme .ace_marker-layer .ace_selection {background: rgba(170, 0, 255, 0.45)}.ace-kr-theme.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #0B0A09;border-radius: 2px}.ace-kr-theme .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-kr-theme .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(255, 177, 111, 0.32)}.ace-kr-theme .ace_marker-layer .ace_active-line {background: #38403D}.ace-kr-theme .ace_gutter-active-line {background-color : #38403D}.ace-kr-theme .ace_marker-layer .ace_selected-word {border: 1px solid rgba(170, 0, 255, 0.45)}.ace-kr-theme .ace_invisible {color: rgba(255, 177, 111, 0.32)}.ace-kr-theme .ace_keyword,.ace-kr-theme .ace_meta {color: #949C8B}.ace-kr-theme .ace_constant,.ace-kr-theme .ace_constant.ace_character,.ace-kr-theme .ace_constant.ace_character.ace_escape,.ace-kr-theme .ace_constant.ace_other {color: rgba(210, 117, 24, 0.76)}.ace-kr-theme .ace_invalid {color: #F8F8F8;background-color: #A41300}.ace-kr-theme .ace_support {color: #9FC28A}.ace-kr-theme .ace_support.ace_constant {color: #C27E66}.ace-kr-theme .ace_fold {background-color: #949C8B;border-color: #FCFFE0}.ace-kr-theme .ace_support.ace_function {color: #85873A}.ace-kr-theme .ace_storage {color: #FFEE80}.ace-kr-theme .ace_string {color: rgba(164, 161, 181, 0.8)}.ace-kr-theme .ace_string.ace_regexp {color: rgba(125, 255, 192, 0.65)}.ace-kr-theme .ace_comment {font-style: italic;color: #706D5B}.ace-kr-theme .ace_variable {color: #D1A796}.ace-kr-theme .ace_variable.ace_language {color: #FF80E1}.ace-kr-theme .ace_meta.ace_tag {color: #BABD9C}.ace-kr-theme .ace_markup.ace_underline {text-decoration: underline}.ace-kr-theme .ace_markup.ace_list {background-color: #0F0040}.ace-kr-theme .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPg5uL8zzBz5sz/AA1WA+hUYIqjAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-merbivore.js b/common/static/js/vendor/ace/theme-merbivore.js new file mode 100644 index 0000000000..e43cbc7375 --- /dev/null +++ b/common/static/js/vendor/ace/theme-merbivore.js @@ -0,0 +1 @@ +ace.define("ace/theme/merbivore",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-merbivore",t.cssText=".ace-merbivore .ace_gutter {background: #202020;color: #E6E1DC}.ace-merbivore .ace_print-margin {width: 1px;background: #555651}.ace-merbivore .ace_scroller {background-color: #161616}.ace-merbivore .ace_text-layer {color: #E6E1DC}.ace-merbivore .ace_cursor {border-left: 2px solid #FFFFFF}.ace-merbivore .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #FFFFFF}.ace-merbivore .ace_marker-layer .ace_selection {background: #454545}.ace-merbivore.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #161616;border-radius: 2px}.ace-merbivore .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-merbivore .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-merbivore .ace_marker-layer .ace_active-line {background: #333435}.ace-merbivore .ace_gutter-active-line {background-color: #333435}.ace-merbivore .ace_marker-layer .ace_selected-word {border: 1px solid #454545}.ace-merbivore .ace_invisible {color: #404040}.ace-merbivore .ace_entity.ace_name.ace_tag,.ace-merbivore .ace_keyword,.ace-merbivore .ace_meta,.ace-merbivore .ace_meta.ace_tag,.ace-merbivore .ace_storage,.ace-merbivore .ace_support.ace_function {color: #FC6F09}.ace-merbivore .ace_constant,.ace-merbivore .ace_constant.ace_character,.ace-merbivore .ace_constant.ace_character.ace_escape,.ace-merbivore .ace_constant.ace_other,.ace-merbivore .ace_support.ace_type {color: #1EDAFB}.ace-merbivore .ace_constant.ace_character.ace_escape {color: #519F50}.ace-merbivore .ace_constant.ace_language {color: #FDC251}.ace-merbivore .ace_constant.ace_library,.ace-merbivore .ace_string,.ace-merbivore .ace_support.ace_constant {color: #8DFF0A}.ace-merbivore .ace_constant.ace_numeric {color: #58C554}.ace-merbivore .ace_invalid {color: #FFFFFF;background-color: #990000}.ace-merbivore .ace_fold {background-color: #FC6F09;border-color: #E6E1DC}.ace-merbivore .ace_comment {font-style: italic;color: #AD2EA4}.ace-merbivore .ace_entity.ace_other.ace_attribute-name {color: #FFFF89}.ace-merbivore .ace_markup.ace_underline {text-decoration: underline}.ace-merbivore .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMQExP7zzBz5sz/AA50BAyDznYhAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-merbivore_soft.js b/common/static/js/vendor/ace/theme-merbivore_soft.js new file mode 100644 index 0000000000..a55030a262 --- /dev/null +++ b/common/static/js/vendor/ace/theme-merbivore_soft.js @@ -0,0 +1 @@ +ace.define("ace/theme/merbivore_soft",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-merbivore-soft",t.cssText=".ace-merbivore-soft .ace_gutter {background: #262424;color: #E6E1DC}.ace-merbivore-soft .ace_print-margin {width: 1px;background: #262424}.ace-merbivore-soft .ace_scroller {background-color: #1C1C1C}.ace-merbivore-soft .ace_text-layer {color: #E6E1DC}.ace-merbivore-soft .ace_cursor {border-left: 2px solid #FFFFFF}.ace-merbivore-soft .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #FFFFFF}.ace-merbivore-soft .ace_marker-layer .ace_selection {background: #494949}.ace-merbivore-soft.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #1C1C1C;border-radius: 2px}.ace-merbivore-soft .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-merbivore-soft .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-merbivore-soft .ace_marker-layer .ace_active-line {background: #333435}.ace-merbivore-soft .ace_gutter-active-line {background-color: #333435}.ace-merbivore-soft .ace_marker-layer .ace_selected-word {border: 1px solid #494949}.ace-merbivore-soft .ace_invisible {color: #404040}.ace-merbivore-soft .ace_entity.ace_name.ace_tag,.ace-merbivore-soft .ace_keyword,.ace-merbivore-soft .ace_meta,.ace-merbivore-soft .ace_meta.ace_tag,.ace-merbivore-soft .ace_storage {color: #FC803A}.ace-merbivore-soft .ace_constant,.ace-merbivore-soft .ace_constant.ace_character,.ace-merbivore-soft .ace_constant.ace_character.ace_escape,.ace-merbivore-soft .ace_constant.ace_other,.ace-merbivore-soft .ace_support.ace_type {color: #68C1D8}.ace-merbivore-soft .ace_constant.ace_character.ace_escape {color: #B3E5B4}.ace-merbivore-soft .ace_constant.ace_language {color: #E1C582}.ace-merbivore-soft .ace_constant.ace_library,.ace-merbivore-soft .ace_string,.ace-merbivore-soft .ace_support.ace_constant {color: #8EC65F}.ace-merbivore-soft .ace_constant.ace_numeric {color: #7FC578}.ace-merbivore-soft .ace_invalid,.ace-merbivore-soft .ace_invalid.ace_deprecated {color: #FFFFFF;background-color: #FE3838}.ace-merbivore-soft .ace_fold {background-color: #FC803A;border-color: #E6E1DC}.ace-merbivore-soft .ace_comment,.ace-merbivore-soft .ace_meta {font-style: italic;color: #AC4BB8}.ace-merbivore-soft .ace_entity.ace_other.ace_attribute-name {color: #EAF1A3}.ace-merbivore-soft .ace_markup.ace_underline {text-decoration: underline}.ace-merbivore-soft .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWOQkZH5zzBz5sz/AA8EBB6crd1rAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-mono_industrial.js b/common/static/js/vendor/ace/theme-mono_industrial.js new file mode 100644 index 0000000000..8629638f53 --- /dev/null +++ b/common/static/js/vendor/ace/theme-mono_industrial.js @@ -0,0 +1 @@ +ace.define("ace/theme/mono_industrial",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-mono-industrial",t.cssText=".ace-mono-industrial .ace_gutter {background: #1d2521;color: #C5C9C9}.ace-mono-industrial .ace_print-margin {width: 1px;background: #555651}.ace-mono-industrial .ace_scroller {background-color: #222C28}.ace-mono-industrial .ace_text-layer {color: #FFFFFF}.ace-mono-industrial .ace_cursor {border-left: 2px solid #FFFFFF}.ace-mono-industrial .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #FFFFFF}.ace-mono-industrial .ace_marker-layer .ace_selection {background: rgba(145, 153, 148, 0.40)}.ace-mono-industrial.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #222C28;border-radius: 2px}.ace-mono-industrial .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-mono-industrial .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(102, 108, 104, 0.50)}.ace-mono-industrial .ace_marker-layer .ace_active-line {background: rgba(12, 13, 12, 0.25)}.ace-mono-industrial .ace_gutter-active-line {background-color: rgba(12, 13, 12, 0.25)}.ace-mono-industrial .ace_marker-layer .ace_selected-word {border: 1px solid rgba(145, 153, 148, 0.40)}.ace-mono-industrial .ace_invisible {color: rgba(102, 108, 104, 0.50)}.ace-mono-industrial .ace_string {background-color: #151C19;color: #FFFFFF}.ace-mono-industrial .ace_keyword,.ace-mono-industrial .ace_meta {color: #A39E64}.ace-mono-industrial .ace_constant,.ace-mono-industrial .ace_constant.ace_character,.ace-mono-industrial .ace_constant.ace_character.ace_escape,.ace-mono-industrial .ace_constant.ace_numeric,.ace-mono-industrial .ace_constant.ace_other {color: #E98800}.ace-mono-industrial .ace_entity.ace_name.ace_function,.ace-mono-industrial .ace_keyword.ace_operator,.ace-mono-industrial .ace_variable {color: #A8B3AB}.ace-mono-industrial .ace_invalid {color: #FFFFFF;background-color: rgba(153, 0, 0, 0.68)}.ace-mono-industrial .ace_support.ace_constant {color: #C87500}.ace-mono-industrial .ace_fold {background-color: #A8B3AB;border-color: #FFFFFF}.ace-mono-industrial .ace_support.ace_function {color: #588E60}.ace-mono-industrial .ace_entity.ace_name,.ace-mono-industrial .ace_support.ace_class,.ace-mono-industrial .ace_support.ace_type {color: #5778B6}.ace-mono-industrial .ace_storage {color: #C23B00}.ace-mono-industrial .ace_variable.ace_language,.ace-mono-industrial .ace_variable.ace_parameter {color: #648BD2}.ace-mono-industrial .ace_comment {color: #666C68;background-color: #151C19}.ace-mono-industrial .ace_entity.ace_other.ace_attribute-name {color: #909993}.ace-mono-industrial .ace_markup.ace_underline {text-decoration: underline}.ace-mono-industrial .ace_entity.ace_name.ace_tag {color: #A65EFF}.ace-mono-industrial .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQ0tH4zzBz5sz/ABAOBECKH+evAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-monokai.js b/common/static/js/vendor/ace/theme-monokai.js new file mode 100644 index 0000000000..5e51428957 --- /dev/null +++ b/common/static/js/vendor/ace/theme-monokai.js @@ -0,0 +1 @@ +ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-monokai",t.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai .ace_scroller {background-color: #272822}.ace-monokai .ace_text-layer {color: #F8F8F2}.ace-monokai .ace_cursor {border-left: 2px solid #F8F8F0}.ace-monokai .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;border-radius: 2px}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_markup.ace_underline {text-decoration: underline}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQ11D6z7Bq1ar/ABCKBG6g04U2AAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-pastel_on_dark.js b/common/static/js/vendor/ace/theme-pastel_on_dark.js new file mode 100644 index 0000000000..7350acb3c6 --- /dev/null +++ b/common/static/js/vendor/ace/theme-pastel_on_dark.js @@ -0,0 +1 @@ +ace.define("ace/theme/pastel_on_dark",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-pastel-on-dark",t.cssText=".ace-pastel-on-dark .ace_gutter {background: #353030;color: #8F938F}.ace-pastel-on-dark .ace_print-margin {width: 1px;background: #353030}.ace-pastel-on-dark .ace_scroller {background-color: #2C2828}.ace-pastel-on-dark .ace_text-layer {color: #8F938F}.ace-pastel-on-dark .ace_cursor {border-left: 2px solid #A7A7A7}.ace-pastel-on-dark .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #A7A7A7}.ace-pastel-on-dark .ace_marker-layer .ace_selection {background: rgba(221, 240, 255, 0.20)}.ace-pastel-on-dark.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #2C2828;border-radius: 2px}.ace-pastel-on-dark .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-pastel-on-dark .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(255, 255, 255, 0.25)}.ace-pastel-on-dark .ace_marker-layer .ace_active-line {background: rgba(255, 255, 255, 0.031)}.ace-pastel-on-dark .ace_gutter-active-line {background-color: rgba(255, 255, 255, 0.031)}.ace-pastel-on-dark .ace_marker-layer .ace_selected-word {border: 1px solid rgba(221, 240, 255, 0.20)}.ace-pastel-on-dark .ace_invisible {color: rgba(255, 255, 255, 0.25)}.ace-pastel-on-dark .ace_keyword,.ace-pastel-on-dark .ace_meta {color: #757aD8}.ace-pastel-on-dark .ace_constant,.ace-pastel-on-dark .ace_constant.ace_character,.ace-pastel-on-dark .ace_constant.ace_character.ace_escape,.ace-pastel-on-dark .ace_constant.ace_other {color: #4FB7C5}.ace-pastel-on-dark .ace_keyword.ace_operator {color: #797878}.ace-pastel-on-dark .ace_constant.ace_character {color: #AFA472}.ace-pastel-on-dark .ace_constant.ace_language {color: #DE8E30}.ace-pastel-on-dark .ace_constant.ace_numeric {color: #CCCCCC}.ace-pastel-on-dark .ace_invalid,.ace-pastel-on-dark .ace_invalid.ace_illegal {color: #F8F8F8;background-color: rgba(86, 45, 86, 0.75)}.ace-pastel-on-dark .ace_invalid.ace_deprecated {text-decoration: underline;font-style: italic;color: #D2A8A1}.ace-pastel-on-dark .ace_fold {background-color: #757aD8;border-color: #8F938F}.ace-pastel-on-dark .ace_support.ace_function {color: #AEB2F8}.ace-pastel-on-dark .ace_string {color: #66A968}.ace-pastel-on-dark .ace_string.ace_regexp {color: #E9C062}.ace-pastel-on-dark .ace_comment {color: #A6C6FF}.ace-pastel-on-dark .ace_variable {color: #BEBF55}.ace-pastel-on-dark .ace_variable.ace_language {color: #C1C144}.ace-pastel-on-dark .ace_xml-pe {color: #494949}.ace-pastel-on-dark .ace_markup.ace_underline {text-decoration: underline}.ace-pastel-on-dark .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0dD4z9DR0fEfAA+vBBPqhbn1AAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-solarized_dark.js b/common/static/js/vendor/ace/theme-solarized_dark.js new file mode 100644 index 0000000000..0a1ba40263 --- /dev/null +++ b/common/static/js/vendor/ace/theme-solarized_dark.js @@ -0,0 +1 @@ +ace.define("ace/theme/solarized_dark",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-solarized-dark",t.cssText=".ace-solarized-dark .ace_gutter {background: #01313f;color: #d0edf7}.ace-solarized-dark .ace_print-margin {width: 1px;background: #33555E}.ace-solarized-dark .ace_scroller {background-color: #002B36}.ace-solarized-dark .ace_entity.ace_other.ace_attribute-name,.ace-solarized-dark .ace_storage,.ace-solarized-dark .ace_text-layer {color: #93A1A1}.ace-solarized-dark .ace_cursor {border-left: 2px solid #D30102}.ace-solarized-dark .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #D30102}.ace-solarized-dark .ace_marker-layer .ace_active-line,.ace-solarized-dark .ace_marker-layer .ace_selection {background: rgba(255, 255, 255, 0.1)}.ace-solarized-dark.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #002B36;border-radius: 2px}.ace-solarized-dark .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-solarized-dark .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(147, 161, 161, 0.50)}.ace-solarized-dark .ace_gutter-active-line {background-color: #0d3440}.ace-solarized-dark .ace_marker-layer .ace_selected-word {border: 1px solid #073642}.ace-solarized-dark .ace_invisible {color: rgba(147, 161, 161, 0.50)}.ace-solarized-dark .ace_keyword,.ace-solarized-dark .ace_meta,.ace-solarized-dark .ace_support.ace_class,.ace-solarized-dark .ace_support.ace_type {color: #859900}.ace-solarized-dark .ace_constant.ace_character,.ace-solarized-dark .ace_constant.ace_other {color: #CB4B16}.ace-solarized-dark .ace_constant.ace_language {color: #B58900}.ace-solarized-dark .ace_constant.ace_numeric {color: #D33682}.ace-solarized-dark .ace_fold {background-color: #268BD2;border-color: #93A1A1}.ace-solarized-dark .ace_entity.ace_name.ace_function,.ace-solarized-dark .ace_entity.ace_name.ace_tag,.ace-solarized-dark .ace_support.ace_function,.ace-solarized-dark .ace_variable,.ace-solarized-dark .ace_variable.ace_language {color: #268BD2}.ace-solarized-dark .ace_string {color: #2AA198}.ace-solarized-dark .ace_string.ace_regexp {color: #D30102}.ace-solarized-dark .ace_comment {font-style: italic;color: #657B83}.ace-solarized-dark .ace_markup.ace_underline {text-decoration: underline}.ace-solarized-dark .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNg0Db7zzBz5sz/AA82BCv7wOIDAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-solarized_light.js b/common/static/js/vendor/ace/theme-solarized_light.js new file mode 100644 index 0000000000..f0c446f24d --- /dev/null +++ b/common/static/js/vendor/ace/theme-solarized_light.js @@ -0,0 +1 @@ +ace.define("ace/theme/solarized_light",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-solarized-light",t.cssText=".ace-solarized-light .ace_gutter {background: #fbf1d3;color: #333}.ace-solarized-light .ace_print-margin {width: 1px;background: #e8e8e8}.ace-solarized-light .ace_scroller {background-color: #FDF6E3}.ace-solarized-light .ace_text-layer {color: #586E75}.ace-solarized-light .ace_cursor {border-left: 2px solid #000000}.ace-solarized-light .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #000000}.ace-solarized-light .ace_marker-layer .ace_selection {background: #073642}.ace-solarized-light.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #FDF6E3;border-radius: 2px}.ace-solarized-light .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-solarized-light .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(147, 161, 161, 0.50)}.ace-solarized-light .ace_marker-layer .ace_active-line {background: #EEE8D5}.ace-solarized-light .ace_gutter-active-line {background-color : #dcdcdc}.ace-solarized-light .ace_marker-layer .ace_selected-word {border: 1px solid #073642}.ace-solarized-light .ace_invisible {color: rgba(147, 161, 161, 0.50)}.ace-solarized-light .ace_keyword,.ace-solarized-light .ace_meta,.ace-solarized-light .ace_support.ace_class,.ace-solarized-light .ace_support.ace_type {color: #859900}.ace-solarized-light .ace_constant.ace_character,.ace-solarized-light .ace_constant.ace_other {color: #CB4B16}.ace-solarized-light .ace_constant.ace_language {color: #B58900}.ace-solarized-light .ace_constant.ace_numeric {color: #D33682}.ace-solarized-light .ace_fold {background-color: #268BD2;border-color: #586E75}.ace-solarized-light .ace_entity.ace_name.ace_function,.ace-solarized-light .ace_entity.ace_name.ace_tag,.ace-solarized-light .ace_support.ace_function,.ace-solarized-light .ace_variable,.ace-solarized-light .ace_variable.ace_language {color: #268BD2}.ace-solarized-light .ace_storage {color: #073642}.ace-solarized-light .ace_string {color: #2AA198}.ace-solarized-light .ace_string.ace_regexp {color: #D30102}.ace-solarized-light .ace_comment,.ace-solarized-light .ace_entity.ace_other.ace_attribute-name {color: #93A1A1}.ace-solarized-light .ace_markup.ace_underline {text-decoration: underline}.ace-solarized-light .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4++3xf4ZVq1b9BwAjxwbT1g3hiwAAAABJRU5ErkJggg==) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-textmate.js b/common/static/js/vendor/ace/theme-textmate.js new file mode 100644 index 0000000000..d8ef4710d9 --- /dev/null +++ b/common/static/js/vendor/ace/theme-textmate.js @@ -0,0 +1 @@ +ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm .ace_scroller {background-color: #FFFFFF;}.ace-tm .ace_cursor {border-left: 2px solid black;}.ace-tm .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_markup.ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_markup.ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;border-radius: 2px;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-tomorrow.js b/common/static/js/vendor/ace/theme-tomorrow.js new file mode 100644 index 0000000000..6c99f7ac1b --- /dev/null +++ b/common/static/js/vendor/ace/theme-tomorrow.js @@ -0,0 +1 @@ +ace.define("ace/theme/tomorrow",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-tomorrow",t.cssText=".ace-tomorrow .ace_gutter {background: #f6f6f6;color: #4D4D4C}.ace-tomorrow .ace_print-margin {width: 1px;background: #f6f6f6}.ace-tomorrow .ace_scroller {background-color: #FFFFFF}.ace-tomorrow .ace_text-layer {color: #4D4D4C}.ace-tomorrow .ace_cursor {border-left: 2px solid #AEAFAD}.ace-tomorrow .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #AEAFAD}.ace-tomorrow .ace_marker-layer .ace_selection {background: #D6D6D6}.ace-tomorrow.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #FFFFFF;border-radius: 2px}.ace-tomorrow .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-tomorrow .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #D1D1D1}.ace-tomorrow .ace_marker-layer .ace_active-line {background: #EFEFEF}.ace-tomorrow .ace_gutter-active-line {background-color : #dcdcdc}.ace-tomorrow .ace_marker-layer .ace_selected-word {border: 1px solid #D6D6D6}.ace-tomorrow .ace_invisible {color: #D1D1D1}.ace-tomorrow .ace_keyword,.ace-tomorrow .ace_meta,.ace-tomorrow .ace_storage,.ace-tomorrow .ace_storage.ace_type,.ace-tomorrow .ace_support.ace_type {color: #8959A8}.ace-tomorrow .ace_keyword.ace_operator {color: #3E999F}.ace-tomorrow .ace_constant.ace_character,.ace-tomorrow .ace_constant.ace_language,.ace-tomorrow .ace_constant.ace_numeric,.ace-tomorrow .ace_keyword.ace_other.ace_unit,.ace-tomorrow .ace_support.ace_constant,.ace-tomorrow .ace_variable.ace_parameter {color: #F5871F}.ace-tomorrow .ace_constant.ace_other {color: #666969}.ace-tomorrow .ace_invalid {color: #FFFFFF;background-color: #C82829}.ace-tomorrow .ace_invalid.ace_deprecated {color: #FFFFFF;background-color: #8959A8}.ace-tomorrow .ace_fold {background-color: #4271AE;border-color: #4D4D4C}.ace-tomorrow .ace_entity.ace_name.ace_function,.ace-tomorrow .ace_support.ace_function,.ace-tomorrow .ace_variable {color: #4271AE}.ace-tomorrow .ace_support.ace_class,.ace-tomorrow .ace_support.ace_type {color: #C99E00}.ace-tomorrow .ace_markup.ace_heading,.ace-tomorrow .ace_string {color: #718C00}.ace-tomorrow .ace_entity.ace_name.ace_tag,.ace-tomorrow .ace_entity.ace_other.ace_attribute-name,.ace-tomorrow .ace_meta.ace_tag,.ace-tomorrow .ace_string.ace_regexp,.ace-tomorrow .ace_variable {color: #C82829}.ace-tomorrow .ace_comment {color: #8E908C}.ace-tomorrow .ace_markup.ace_underline {text-decoration: underline}.ace-tomorrow .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bdu3f/BwAlfgctduB85QAAAABJRU5ErkJggg==) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-tomorrow_night.js b/common/static/js/vendor/ace/theme-tomorrow_night.js new file mode 100644 index 0000000000..6ce48ca529 --- /dev/null +++ b/common/static/js/vendor/ace/theme-tomorrow_night.js @@ -0,0 +1 @@ +ace.define("ace/theme/tomorrow_night",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-tomorrow-night",t.cssText=".ace-tomorrow-night .ace_gutter {background: #25282c;color: #C5C8C6}.ace-tomorrow-night .ace_print-margin {width: 1px;background: #25282c}.ace-tomorrow-night .ace_scroller {background-color: #1D1F21}.ace-tomorrow-night .ace_text-layer {color: #C5C8C6}.ace-tomorrow-night .ace_cursor {border-left: 2px solid #AEAFAD}.ace-tomorrow-night .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #AEAFAD}.ace-tomorrow-night .ace_marker-layer .ace_selection {background: #373B41}.ace-tomorrow-night.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #1D1F21;border-radius: 2px}.ace-tomorrow-night .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-tomorrow-night .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #4B4E55}.ace-tomorrow-night .ace_marker-layer .ace_active-line {background: #282A2E}.ace-tomorrow-night .ace_gutter-active-line {background-color: #282A2E}.ace-tomorrow-night .ace_marker-layer .ace_selected-word {border: 1px solid #373B41}.ace-tomorrow-night .ace_invisible {color: #4B4E55}.ace-tomorrow-night .ace_keyword,.ace-tomorrow-night .ace_meta,.ace-tomorrow-night .ace_storage,.ace-tomorrow-night .ace_storage.ace_type,.ace-tomorrow-night .ace_support.ace_type {color: #B294BB}.ace-tomorrow-night .ace_keyword.ace_operator {color: #8ABEB7}.ace-tomorrow-night .ace_constant.ace_character,.ace-tomorrow-night .ace_constant.ace_language,.ace-tomorrow-night .ace_constant.ace_numeric,.ace-tomorrow-night .ace_keyword.ace_other.ace_unit,.ace-tomorrow-night .ace_support.ace_constant,.ace-tomorrow-night .ace_variable.ace_parameter {color: #DE935F}.ace-tomorrow-night .ace_constant.ace_other {color: #CED1CF}.ace-tomorrow-night .ace_invalid {color: #CED2CF;background-color: #DF5F5F}.ace-tomorrow-night .ace_invalid.ace_deprecated {color: #CED2CF;background-color: #B798BF}.ace-tomorrow-night .ace_fold {background-color: #81A2BE;border-color: #C5C8C6}.ace-tomorrow-night .ace_entity.ace_name.ace_function,.ace-tomorrow-night .ace_support.ace_function,.ace-tomorrow-night .ace_variable {color: #81A2BE}.ace-tomorrow-night .ace_support.ace_class,.ace-tomorrow-night .ace_support.ace_type {color: #F0C674}.ace-tomorrow-night .ace_markup.ace_heading,.ace-tomorrow-night .ace_string {color: #B5BD68}.ace-tomorrow-night .ace_entity.ace_name.ace_tag,.ace-tomorrow-night .ace_entity.ace_other.ace_attribute-name,.ace-tomorrow-night .ace_meta.ace_tag,.ace-tomorrow-night .ace_string.ace_regexp,.ace-tomorrow-night .ace_variable {color: #CC6666}.ace-tomorrow-night .ace_comment {color: #969896}.ace-tomorrow-night .ace_markup.ace_underline {text-decoration: underline}.ace-tomorrow-night .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWOQlVf8z7Bq1ar/AA/hBFp7egmpAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-tomorrow_night_blue.js b/common/static/js/vendor/ace/theme-tomorrow_night_blue.js new file mode 100644 index 0000000000..743a65566a --- /dev/null +++ b/common/static/js/vendor/ace/theme-tomorrow_night_blue.js @@ -0,0 +1 @@ +ace.define("ace/theme/tomorrow_night_blue",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-tomorrow-night-blue",t.cssText=".ace-tomorrow-night-blue .ace_gutter {background: #00204b;color: #7388b5}.ace-tomorrow-night-blue .ace_print-margin {width: 1px;background: #00204b}.ace-tomorrow-night-blue .ace_scroller {background-color: #002451}.ace-tomorrow-night-blue .ace_constant.ace_other,.ace-tomorrow-night-blue .ace_text-layer {color: #FFFFFF}.ace-tomorrow-night-blue .ace_cursor {border-left: 2px solid #FFFFFF}.ace-tomorrow-night-blue .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #FFFFFF}.ace-tomorrow-night-blue .ace_marker-layer .ace_selection {background: #003F8E}.ace-tomorrow-night-blue.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #002451;border-radius: 2px}.ace-tomorrow-night-blue .ace_marker-layer .ace_step {background: rgb(127, 111, 19)}.ace-tomorrow-night-blue .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404F7D}.ace-tomorrow-night-blue .ace_marker-layer .ace_active-line {background: #00346E}.ace-tomorrow-night-blue .ace_gutter-active-line {background-color: #022040}.ace-tomorrow-night-blue .ace_marker-layer .ace_selected-word {border: 1px solid #003F8E}.ace-tomorrow-night-blue .ace_invisible {color: #404F7D}.ace-tomorrow-night-blue .ace_keyword,.ace-tomorrow-night-blue .ace_meta,.ace-tomorrow-night-blue .ace_storage,.ace-tomorrow-night-blue .ace_storage.ace_type,.ace-tomorrow-night-blue .ace_support.ace_type {color: #EBBBFF}.ace-tomorrow-night-blue .ace_keyword.ace_operator {color: #99FFFF}.ace-tomorrow-night-blue .ace_constant.ace_character,.ace-tomorrow-night-blue .ace_constant.ace_language,.ace-tomorrow-night-blue .ace_constant.ace_numeric,.ace-tomorrow-night-blue .ace_keyword.ace_other.ace_unit,.ace-tomorrow-night-blue .ace_support.ace_constant,.ace-tomorrow-night-blue .ace_variable.ace_parameter {color: #FFC58F}.ace-tomorrow-night-blue .ace_invalid {color: #FFFFFF;background-color: #F99DA5}.ace-tomorrow-night-blue .ace_invalid.ace_deprecated {color: #FFFFFF;background-color: #EBBBFF}.ace-tomorrow-night-blue .ace_fold {background-color: #BBDAFF;border-color: #FFFFFF}.ace-tomorrow-night-blue .ace_entity.ace_name.ace_function,.ace-tomorrow-night-blue .ace_support.ace_function,.ace-tomorrow-night-blue .ace_variable {color: #BBDAFF}.ace-tomorrow-night-blue .ace_support.ace_class,.ace-tomorrow-night-blue .ace_support.ace_type {color: #FFEEAD}.ace-tomorrow-night-blue .ace_markup.ace_heading,.ace-tomorrow-night-blue .ace_string {color: #D1F1A9}.ace-tomorrow-night-blue .ace_entity.ace_name.ace_tag,.ace-tomorrow-night-blue .ace_entity.ace_other.ace_attribute-name,.ace-tomorrow-night-blue .ace_meta.ace_tag,.ace-tomorrow-night-blue .ace_string.ace_regexp,.ace-tomorrow-night-blue .ace_variable {color: #FF9DA4}.ace-tomorrow-night-blue .ace_comment {color: #7285B7}.ace-tomorrow-night-blue .ace_markup.ace_underline {text-decoration: underline}.ace-tomorrow-night-blue .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgUAn8z7Bq1ar/ABBUBHJ4/r3JAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-tomorrow_night_bright.js b/common/static/js/vendor/ace/theme-tomorrow_night_bright.js new file mode 100644 index 0000000000..0540d15250 --- /dev/null +++ b/common/static/js/vendor/ace/theme-tomorrow_night_bright.js @@ -0,0 +1 @@ +ace.define("ace/theme/tomorrow_night_bright",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-tomorrow-night-bright",t.cssText=".ace-tomorrow-night-bright .ace_gutter {background: #1a1a1a;color: #DEDEDE}.ace-tomorrow-night-bright .ace_print-margin {width: 1px;background: #1a1a1a}.ace-tomorrow-night-bright .ace_scroller {background-color: #000000}.ace-tomorrow-night-bright .ace_text-layer {color: #DEDEDE}.ace-tomorrow-night-bright .ace_cursor {border-left: 2px solid #9F9F9F}.ace-tomorrow-night-bright .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #9F9F9F}.ace-tomorrow-night-bright .ace_marker-layer .ace_selection {background: #424242}.ace-tomorrow-night-bright.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #000000;border-radius: 2px}.ace-tomorrow-night-bright .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-tomorrow-night-bright .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #343434}.ace-tomorrow-night-bright .ace_marker-layer .ace_active-line {background: #2A2A2A}.ace-tomorrow-night-bright .ace_gutter-active-line {background-color: #2A2A2A}.ace-tomorrow-night-bright .ace_marker-layer .ace_selected-word {border: 1px solid #424242}.ace-tomorrow-night-bright .ace_invisible {color: #343434}.ace-tomorrow-night-bright .ace_keyword,.ace-tomorrow-night-bright .ace_meta,.ace-tomorrow-night-bright .ace_storage,.ace-tomorrow-night-bright .ace_storage.ace_type,.ace-tomorrow-night-bright .ace_support.ace_type {color: #C397D8}.ace-tomorrow-night-bright .ace_keyword.ace_operator {color: #70C0B1}.ace-tomorrow-night-bright .ace_constant.ace_character,.ace-tomorrow-night-bright .ace_constant.ace_language,.ace-tomorrow-night-bright .ace_constant.ace_numeric,.ace-tomorrow-night-bright .ace_keyword.ace_other.ace_unit,.ace-tomorrow-night-bright .ace_support.ace_constant,.ace-tomorrow-night-bright .ace_variable.ace_parameter {color: #E78C45}.ace-tomorrow-night-bright .ace_constant.ace_other {color: #EEEEEE}.ace-tomorrow-night-bright .ace_invalid {color: #CED2CF;background-color: #DF5F5F}.ace-tomorrow-night-bright .ace_invalid.ace_deprecated {color: #CED2CF;background-color: #B798BF}.ace-tomorrow-night-bright .ace_fold {background-color: #7AA6DA;border-color: #DEDEDE}.ace-tomorrow-night-bright .ace_entity.ace_name.ace_function,.ace-tomorrow-night-bright .ace_support.ace_function,.ace-tomorrow-night-bright .ace_variable {color: #7AA6DA}.ace-tomorrow-night-bright .ace_support.ace_class,.ace-tomorrow-night-bright .ace_support.ace_type {color: #E7C547}.ace-tomorrow-night-bright .ace_markup.ace_heading,.ace-tomorrow-night-bright .ace_string {color: #B9CA4A}.ace-tomorrow-night-bright .ace_entity.ace_name.ace_tag,.ace-tomorrow-night-bright .ace_entity.ace_other.ace_attribute-name,.ace-tomorrow-night-bright .ace_meta.ace_tag,.ace-tomorrow-night-bright .ace_string.ace_regexp,.ace-tomorrow-night-bright .ace_variable {color: #D54E53}.ace-tomorrow-night-bright .ace_comment {color: #969896}.ace-tomorrow-night-bright .ace_markup.ace_underline {text-decoration: underline}.ace-tomorrow-night-bright .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGD4z7Bq1ar/AAz9A/2naJQKAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-tomorrow_night_eighties.js b/common/static/js/vendor/ace/theme-tomorrow_night_eighties.js new file mode 100644 index 0000000000..f5d33a7e87 --- /dev/null +++ b/common/static/js/vendor/ace/theme-tomorrow_night_eighties.js @@ -0,0 +1 @@ +ace.define("ace/theme/tomorrow_night_eighties",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-tomorrow-night-eighties",t.cssText=".ace-tomorrow-night-eighties .ace_gutter {background: #272727;color: #CCC}.ace-tomorrow-night-eighties .ace_print-margin {width: 1px;background: #272727}.ace-tomorrow-night-eighties .ace_scroller {background-color: #2D2D2D}.ace-tomorrow-night-eighties .ace_constant.ace_other,.ace-tomorrow-night-eighties .ace_text-layer {color: #CCCCCC}.ace-tomorrow-night-eighties .ace_cursor {border-left: 2px solid #CCCCCC}.ace-tomorrow-night-eighties .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #CCCCCC}.ace-tomorrow-night-eighties .ace_marker-layer .ace_selection {background: #515151}.ace-tomorrow-night-eighties.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #2D2D2D;border-radius: 2px}.ace-tomorrow-night-eighties .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-tomorrow-night-eighties .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #6A6A6A}.ace-tomorrow-night-eighties .ace_marker-layer .ace_active-line {background: #393939}.ace-tomorrow-night-eighties .ace_gutter-active-line {background-color: #393939}.ace-tomorrow-night-eighties .ace_marker-layer .ace_selected-word {border: 1px solid #515151}.ace-tomorrow-night-eighties .ace_invisible {color: #6A6A6A}.ace-tomorrow-night-eighties .ace_keyword,.ace-tomorrow-night-eighties .ace_meta,.ace-tomorrow-night-eighties .ace_storage,.ace-tomorrow-night-eighties .ace_storage.ace_type,.ace-tomorrow-night-eighties .ace_support.ace_type {color: #CC99CC}.ace-tomorrow-night-eighties .ace_keyword.ace_operator {color: #66CCCC}.ace-tomorrow-night-eighties .ace_constant.ace_character,.ace-tomorrow-night-eighties .ace_constant.ace_language,.ace-tomorrow-night-eighties .ace_constant.ace_numeric,.ace-tomorrow-night-eighties .ace_keyword.ace_other.ace_unit,.ace-tomorrow-night-eighties .ace_support.ace_constant,.ace-tomorrow-night-eighties .ace_variable.ace_parameter {color: #F99157}.ace-tomorrow-night-eighties .ace_invalid {color: #CDCDCD;background-color: #F2777A}.ace-tomorrow-night-eighties .ace_invalid.ace_deprecated {color: #CDCDCD;background-color: #CC99CC}.ace-tomorrow-night-eighties .ace_fold {background-color: #6699CC;border-color: #CCCCCC}.ace-tomorrow-night-eighties .ace_entity.ace_name.ace_function,.ace-tomorrow-night-eighties .ace_support.ace_function,.ace-tomorrow-night-eighties .ace_variable {color: #6699CC}.ace-tomorrow-night-eighties .ace_support.ace_class,.ace-tomorrow-night-eighties .ace_support.ace_type {color: #FFCC66}.ace-tomorrow-night-eighties .ace_markup.ace_heading,.ace-tomorrow-night-eighties .ace_string {color: #99CC99}.ace-tomorrow-night-eighties .ace_comment {color: #999999}.ace-tomorrow-night-eighties .ace_entity.ace_name.ace_tag,.ace-tomorrow-night-eighties .ace_entity.ace_other.ace_attribute-name,.ace-tomorrow-night-eighties .ace_meta.ace_tag,.ace-tomorrow-night-eighties .ace_variable {color: #F2777A}.ace-tomorrow-night-eighties .ace_markup.ace_underline {text-decoration: underline}.ace-tomorrow-night-eighties .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ1dX9z7Bq1ar/ABE1BITwhhuFAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-twilight.js b/common/static/js/vendor/ace/theme-twilight.js new file mode 100644 index 0000000000..0ee85dd0b1 --- /dev/null +++ b/common/static/js/vendor/ace/theme-twilight.js @@ -0,0 +1 @@ +ace.define("ace/theme/twilight",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-twilight",t.cssText=".ace-twilight .ace_gutter {background: #232323;color: #E2E2E2}.ace-twilight .ace_print-margin {width: 1px;background: #232323}.ace-twilight .ace_scroller {background-color: #141414}.ace-twilight .ace_text-layer {color: #F8F8F8}.ace-twilight .ace_cursor {border-left: 2px solid #A7A7A7}.ace-twilight .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #A7A7A7}.ace-twilight .ace_marker-layer .ace_selection {background: rgba(221, 240, 255, 0.20)}.ace-twilight.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #141414;border-radius: 2px}.ace-twilight .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-twilight .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(255, 255, 255, 0.25)}.ace-twilight .ace_marker-layer .ace_active-line {background: rgba(255, 255, 255, 0.031)}.ace-twilight .ace_gutter-active-line {background-color: rgba(255, 255, 255, 0.031)}.ace-twilight .ace_marker-layer .ace_selected-word {border: 1px solid rgba(221, 240, 255, 0.20)}.ace-twilight .ace_invisible {color: rgba(255, 255, 255, 0.25)}.ace-twilight .ace_keyword,.ace-twilight .ace_meta {color: #CDA869}.ace-twilight .ace_constant,.ace-twilight .ace_constant.ace_character,.ace-twilight .ace_constant.ace_character.ace_escape,.ace-twilight .ace_constant.ace_other,.ace-twilight .ace_markup.ace_heading,.ace-twilight .ace_support.ace_constant {color: #CF6A4C}.ace-twilight .ace_invalid.ace_illegal {color: #F8F8F8;background-color: rgba(86, 45, 86, 0.75)}.ace-twilight .ace_invalid.ace_deprecated {text-decoration: underline;font-style: italic;color: #D2A8A1}.ace-twilight .ace_support {color: #9B859D}.ace-twilight .ace_fold {background-color: #AC885B;border-color: #F8F8F8}.ace-twilight .ace_support.ace_function {color: #DAD085}.ace-twilight .ace_markup.ace_list,.ace-twilight .ace_storage {color: #F9EE98}.ace-twilight .ace_entity.ace_name.ace_function,.ace-twilight .ace_meta.ace_tag,.ace-twilight .ace_variable {color: #AC885B}.ace-twilight .ace_string {color: #8F9D6A}.ace-twilight .ace_string.ace_regexp {color: #E9C062}.ace-twilight .ace_comment {font-style: italic;color: #5F5A60}.ace-twilight .ace_variable {color: #7587A6}.ace-twilight .ace_xml-pe {color: #494949}.ace-twilight .ace_markup.ace_underline {text-decoration: underline}.ace-twilight .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMQERH5zzBz5sz/AA5EBAYqeZXWAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-vibrant_ink.js b/common/static/js/vendor/ace/theme-vibrant_ink.js new file mode 100644 index 0000000000..047a645c07 --- /dev/null +++ b/common/static/js/vendor/ace/theme-vibrant_ink.js @@ -0,0 +1 @@ +ace.define("ace/theme/vibrant_ink",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-vibrant-ink",t.cssText=".ace-vibrant-ink .ace_gutter {background: #1a1a1a;color: #BEBEBE}.ace-vibrant-ink .ace_print-margin {width: 1px;background: #1a1a1a}.ace-vibrant-ink .ace_scroller {background-color: #0F0F0F}.ace-vibrant-ink .ace_text-layer {color: #FFFFFF}.ace-vibrant-ink .ace_cursor {border-left: 2px solid #FFFFFF}.ace-vibrant-ink .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #FFFFFF}.ace-vibrant-ink .ace_marker-layer .ace_selection {background: #6699CC}.ace-vibrant-ink.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #0F0F0F;border-radius: 2px}.ace-vibrant-ink .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-vibrant-ink .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-vibrant-ink .ace_marker-layer .ace_active-line {background: #333333}.ace-vibrant-ink .ace_gutter-active-line {background-color: #333333}.ace-vibrant-ink .ace_marker-layer .ace_selected-word {border: 1px solid #6699CC}.ace-vibrant-ink .ace_invisible {color: #404040}.ace-vibrant-ink .ace_keyword,.ace-vibrant-ink .ace_meta {color: #FF6600}.ace-vibrant-ink .ace_constant,.ace-vibrant-ink .ace_constant.ace_character,.ace-vibrant-ink .ace_constant.ace_character.ace_escape,.ace-vibrant-ink .ace_constant.ace_other {color: #339999}.ace-vibrant-ink .ace_constant.ace_numeric {color: #99CC99}.ace-vibrant-ink .ace_invalid,.ace-vibrant-ink .ace_invalid.ace_deprecated {color: #CCFF33;background-color: #000000}.ace-vibrant-ink .ace_fold {background-color: #FFCC00;border-color: #FFFFFF}.ace-vibrant-ink .ace_entity.ace_name.ace_function,.ace-vibrant-ink .ace_support.ace_function,.ace-vibrant-ink .ace_variable {color: #FFCC00}.ace-vibrant-ink .ace_variable.ace_parameter {font-style: italic}.ace-vibrant-ink .ace_string {color: #66FF00}.ace-vibrant-ink .ace_string.ace_regexp {color: #44B4CC}.ace-vibrant-ink .ace_comment {color: #9933CC}.ace-vibrant-ink .ace_entity.ace_other.ace_attribute-name {font-style: italic;color: #99CC99}.ace-vibrant-ink .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPg5+f/z7Bq1ar/AA5lBCqoLxsgAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/theme-xcode.js b/common/static/js/vendor/ace/theme-xcode.js new file mode 100644 index 0000000000..943a15d1a2 --- /dev/null +++ b/common/static/js/vendor/ace/theme-xcode.js @@ -0,0 +1 @@ +ace.define("ace/theme/xcode",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-xcode",t.cssText="/* THIS THEME WAS AUTOGENERATED BY Theme.tmpl.css (UUID: EE3AD170-2B7F-4DE1-B724-C75F13FE0085) */.ace-xcode .ace_gutter {background: #e8e8e8;color: #333}.ace-xcode .ace_print-margin {width: 1px;background: #e8e8e8}.ace-xcode .ace_scroller {background-color: #FFFFFF}.ace-xcode .ace_text-layer {color: #000000}.ace-xcode .ace_cursor {border-left: 2px solid #000000}.ace-xcode .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #000000}.ace-xcode .ace_marker-layer .ace_selection {background: #B5D5FF}.ace-xcode.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #FFFFFF;border-radius: 2px}.ace-xcode .ace_marker-layer .ace_step {background: rgb(198, 219, 174)}.ace-xcode .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #BFBFBF}.ace-xcode .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.071)}.ace-xcode .ace_gutter-active-line {background-color: rgba(0, 0, 0, 0.071)}.ace-xcode .ace_marker-layer .ace_selected-word {border: 1px solid #B5D5FF}.ace-xcode .ace_constant.ace_language,.ace-xcode .ace_keyword,.ace-xcode .ace_meta,.ace-xcode .ace_variable.ace_language {color: #C800A4}.ace-xcode .ace_invisible {color: #BFBFBF}.ace-xcode .ace_constant.ace_character,.ace-xcode .ace_constant.ace_other {color: #275A5E}.ace-xcode .ace_constant.ace_numeric {color: #3A00DC}.ace-xcode .ace_entity.ace_other.ace_attribute-name,.ace-xcode .ace_support.ace_constant,.ace-xcode .ace_support.ace_function {color: #450084}.ace-xcode .ace_fold {background-color: #C800A4;border-color: #000000}.ace-xcode .ace_entity.ace_name.ace_tag,.ace-xcode .ace_support.ace_class,.ace-xcode .ace_support.ace_type {color: #790EAD}.ace-xcode .ace_storage {color: #C900A4}.ace-xcode .ace_string {color: #DF0002}.ace-xcode .ace_comment {color: #008E00}.ace-xcode .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==) right repeat-y;}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file diff --git a/common/static/js/vendor/ace/worker-coffee.js b/common/static/js/vendor/ace/worker-coffee.js new file mode 100644 index 0000000000..9f7cfca3a8 --- /dev/null +++ b/common/static/js/vendor/ace/worker-coffee.js @@ -0,0 +1 @@ +"no use strict";function initBaseUrls(e){require.tlns=e}function initSender(){var e=require(null,"ace/lib/event_emitter").EventEmitter,t=require(null,"ace/lib/oop"),n=function(){};return function(){t.implement(this,e),this.callback=function(e,t){postMessage({type:"call",id:t,data:e})},this.emit=function(e,t){postMessage({type:"event",name:e,data:t})}}.call(n.prototype),new n}if(typeof window!="undefined"&&window.document)throw"atempt to load ace worker into main window instead of webWorker";var console={log:function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})},error:function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})}},window={console:console},normalizeModule=function(e,t){if(t.indexOf("!")!==-1){var n=t.split("!");return normalizeModule(e,n[0])+"!"+normalizeModule(e,n[1])}if(t.charAt(0)=="."){var r=e.split("/").slice(0,-1).join("/");t=r+"/"+t;while(t.indexOf(".")!==-1&&i!=t){var i=t;t=t.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return t},require=function(e,t){if(!t.charAt)throw new Error("worker.js require() accepts only (parentId, id) as arguments");t=normalizeModule(e,t);var n=require.modules[t];if(n)return n.initialized||(n.initialized=!0,n.exports=n.factory().exports),n.exports;var r=t.split("/");r[0]=require.tlns[r[0]]||r[0];var i=r.join("/")+".js";return require.id=t,importScripts(i),require(e,t)};require.modules={},require.tlns={};var define=function(e,t,n){arguments.length==2?(n=t,typeof e!="string"&&(t=e,e=require.id)):arguments.length==1&&(n=e,e=require.id);if(e.indexOf("text!")===0)return;var r=function(t,n){return require(e,t,n)};require.modules[e]={factory:function(){var e={exports:{}},t=n(r,e.exports,e);return t&&(e.exports=t),e}}},main,sender;onmessage=function(e){var t=e.data;if(t.command){if(!main[t.command])throw new Error("Unknown command:"+t.command);main[t.command].apply(main,t.args)}else if(t.init){initBaseUrls(t.tlns),require(null,"ace/lib/fixoldbrowsers"),sender=initSender();var n=require(null,t.module)[t.classname];main=new n(sender)}else t.event&&sender&&sender._emit(t.event,t.data)},define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(e,t,n){e("./regexp"),e("./es5-shim")}),define("ace/lib/regexp",["require","exports","module"],function(e,t,n){function o(e){return(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":"")}function u(e,t,n){if(Array.prototype.indexOf)return e.indexOf(t,n);for(var r=n||0;r1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function m(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError;var r=o.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e,u=n.apply(s,r.concat(o.call(arguments)));return u!==null&&Object(u)===u?u:s}return n.apply(t,r.concat(o.call(arguments)))};return i});var r=Function.prototype.call,i=Array.prototype,s=Object.prototype,o=i.slice,u=r.bind(s.toString),a=r.bind(s.hasOwnProperty),f,l,c,h,p;if(p=a(s,"__defineGetter__"))f=r.bind(s.__defineGetter__),l=r.bind(s.__defineSetter__),c=r.bind(s.__lookupGetter__),h=r.bind(s.__lookupSetter__);Array.isArray||(Array.isArray=function(t){return u(t)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=D(this),r=arguments[1],i=0,s=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;while(i>>0,i=Array(r),s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o>>0,i=[],s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i=0,s;if(arguments.length>=2)s=arguments[1];else do{if(i in n){s=n[i++];break}if(++i>=r)throw new TypeError}while(!0);for(;i>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i,s=r-1;if(arguments.length>=2)i=arguments[1];else do{if(s in n){i=n[s--];break}if(--s<0)throw new TypeError}while(!0);do s in this&&(i=t.call(void 0,i,n[s],s,n));while(s--);return i}),Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var n=D(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=M(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,M(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:s)});if(!Object.getOwnPropertyDescriptor){var d="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(d+t);if(!a(t,n))return;var r,i,o;r={enumerable:!0,configurable:!0};if(p){var u=t.__proto__;t.__proto__=s;var i=c(t,n),o=h(t,n);t.__proto__=u;if(i||o)return i&&(r.get=i),o&&(r.set=o),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var v;Object.prototype.__proto__===null?v=function(){return{__proto__:null}}:v=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=v();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var g=m({}),y=typeof document=="undefined"||m(document.createElement("div"));if(!g||!y)var b=Object.defineProperty}if(!Object.defineProperty||b){var w="Property description must be an object: ",E="Object.defineProperty called on non-object: ",S="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(E+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(w+r);if(b)try{return b.call(Object,t,n,r)}catch(i){}if(a(r,"value"))if(p&&(c(t,n)||h(t,n))){var o=t.__proto__;t.__proto__=s,delete t[n],t[n]=r.value,t.__proto__=o}else t[n]=r.value;else{if(!p)throw new TypeError(S);a(r,"get")&&f(t,n,r.get),a(r,"set")&&l(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)a(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(x){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(a(t,n))n+="?";t[n]=!0;var r=a(t,n);return delete t[n],r});if(!Object.keys){var T=!0,N=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],C=N.length;for(var k in{toString:null})T=!1;Object.keys=function P(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var P=[];for(var t in e)a(e,t)&&P.push(t);if(T)for(var n=0,r=C;n9999?"+":"")+("00000"+Math.abs(i)).slice(0<=i&&i<=9999?-4:-6),n=t.length;while(n--)r=t[n],r<10&&(t[n]="0"+r);return i+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(t){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(e){var t=function i(t,n,r,s,o,u,a){var f=arguments.length;if(this instanceof e){var l=f==1&&String(t)===t?new e(i.parse(t)):f>=7?new e(t,n,r,s,o,u,a):f>=6?new e(t,n,r,s,o,u):f>=5?new e(t,n,r,s,o):f>=4?new e(t,n,r,s):f>=3?new e(t,n,r):f>=2?new e(t,n):f>=1?new e(t):new e;return l.constructor=i,l}return e.apply(this,arguments)},n=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var r in e)t[r]=e[r];return t.now=e.now,t.UTC=e.UTC,t.prototype=e.prototype,t.prototype.constructor=t,t.parse=function(r){var i=n.exec(r);if(i){i.shift();for(var s=1;s<7;s++)i[s]=+(i[s]||(s<3?1:0)),s==1&&i[s]--;var o=+i.pop(),u=+i.pop(),a=i.pop(),f=0;if(a){if(u>23||o>59)return NaN;f=(u*60+o)*6e4*(a=="+"?-1:1)}var l=+i[0];return 0<=l&&l<=99?(i[0]=l+400,e.UTC.apply(this,i)+f-126227808e5):e.UTC.apply(this,i)+f}return e.parse.apply(this,arguments)},t}(Date));var L=" \n \f\r   ᠎ â€â€‚         âŸã€€\u2028\u2029";if(!String.prototype.trim||L.trim()){L="["+L+"]";var A=new RegExp("^"+L+L+"*"),O=new RegExp(L+L+"*$");String.prototype.trim=function(){return String(this).replace(A,"").replace(O,"")}}var M=function(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e},_="a"[0]!="a",D=function(e){if(e==null)throw new TypeError;return _&&typeof e=="string"&&e?e.split(""):Object(e)}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){var r={};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=function(){this.propagationStopped=!0}),t.preventDefault||(t.preventDefault=function(){this.defaultPrevented=!0});for(var i=0;i=t&&(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this.insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this.insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this.removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this.insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};if(this.start.row>t)var i={row:t+1,column:0};if(this.start.rowthis.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column;t.action==="insertText"?n.start.row===r&&n.start.column<=i?n.start.row===n.end.row?i+=n.end.column-n.start.column:(i-=n.start.column,r+=n.end.row-n.start.row):n.start.row!==n.end.row&&n.start.row=i?i=n.start.column:i=Math.max(0,i-(n.end.column-n.start.column)):n.start.row!==n.end.row&&n.start.row=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n=0||G.call(a,n)>=0)&&(f=n.toUpperCase(),f==="WHEN"&&(c=this.tag(),G.call(x,c)>=0)?f="LEADING_WHEN":f==="FOR"?this.seenFor=!0:f==="UNLESS"?f="IF":G.call(U,f)>=0?f="UNARY":G.call(H,f)>=0&&(f!=="INSTANCEOF"&&this.seenFor?(f="FOR"+f,this.seenFor=!1):(f="RELATION",this.value()==="!"&&(this.tokens.pop(),n="!"+n)))),G.call(E,n)>=0&&(t?(f="IDENTIFIER",n=new String(n),n.reserved=!0):G.call(B,n)>=0&&this.error('reserved word "'+n+'"')),t||(G.call(o,n)>=0&&(n=u[n]),f=function(){switch(n){case"!":return"UNARY";case"==":case"!=":return"COMPARE";case"&&":case"||":return"LOGIC";case"true":case"false":return"BOOL";case"break":case"continue":return"STATEMENT";default:return f}}()),this.token(f,n),e&&this.token(":",":"),r.length)):0},e.prototype.numberToken=function(){var e,t,n,r,i;if(!(n=_.exec(this.chunk)))return 0;r=n[0],/^0[BOX]/.test(r)?this.error("radix prefix '"+r+"' must be lowercase"):/E/.test(r)&&!/^0x/.test(r)?this.error("exponential notation '"+r+"' must be indicated with a lowercase 'e'"):/^0\d*[89]/.test(r)?this.error("decimal literal '"+r+"' must not be prefixed with '0'"):/^0\d+/.test(r)&&this.error("octal literal '"+r+"' must be prefixed with '0o'"),t=r.length;if(i=/^0o([0-7]+)/.exec(r))r="0x"+parseInt(i[1],8).toString(16);if(e=/^0b([01]+)/.exec(r))r="0x"+parseInt(e[1],2).toString(16);return this.token("NUMBER",r),t},e.prototype.stringToken=function(){var e,t,n;switch(this.chunk.charAt(0)){case"'":if(!(e=I.exec(this.chunk)))return 0;this.token("STRING",(n=e[0]).replace(L,"\\\n"));break;case'"':if(!(n=this.balancedString(this.chunk,'"')))return 0;0=0)?0:(n=P.exec(this.chunk))?(o=n,n=o[0],i=o[1],e=o[2],i.slice(0,2)==="/*"&&this.error("regular expressions cannot begin with `*`"),i==="//"&&(i="/(?:)/"),this.token("REGEX",""+i+e),n.length):0)},e.prototype.heregexToken=function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p;r=e[0],t=e[1],n=e[2];if(0>t.indexOf("#{"))return i=t.replace(m,"").replace(/\//g,"\\/"),i.match(/^\*/)&&this.error("regular expressions cannot begin with `*`"),this.token("REGEX","/"+(i||"(?:)")+"/"+n),r.length;this.token("IDENTIFIER","RegExp"),this.tokens.push(["CALL_START","("]),o=[],l=this.interpolateString(t,{regex:!0});for(a=0,f=l.length;athis.indent){if(r)return this.indebt=i-this.indent,this.suppressNewlines(),t.length;e=i-this.indent+this.outdebt,this.token("INDENT",e),this.indents.push(e),this.ends.push("OUTDENT"),this.outdebt=this.indebt=0}else this.indebt=0,this.outdentToken(this.indent-i,r);return this.indent=i,t.length},e.prototype.outdentToken=function(e,t){var n,r;while(e>0)r=this.indents.length-1,this.indents[r]===void 0?e=0:this.indents[r]===this.outdebt?(e-=this.outdebt,this.outdebt=0):this.indents[r]=0)&&this.error('reserved word "'+this.value()+"\" can't be assigned");if((u=t[1])==="||"||u==="&&")return t[0]="COMPOUND_ASSIGN",t[1]+="=",r.length}if(r===";")this.seenFor=!1,n="TERMINATOR";else if(G.call(k,r)>=0)n="MATH";else if(G.call(l,r)>=0)n="COMPARE";else if(G.call(c,r)>=0)n="COMPOUND_ASSIGN";else if(G.call(U,r)>=0)n="UNARY";else if(G.call(F,r)>=0)n="SHIFT";else if(G.call(N,r)>=0||r==="?"&&(t!=null?t.spaced:void 0))n="LOGIC";else if(t&&!t.spaced)if(r==="("&&(a=t[0],G.call(i,a)>=0))t[0]==="?"&&(t[0]="FUNC_EXIST"),n="CALL_START";else if(r==="["&&(f=t[0],G.call(y,f)>=0)){n="INDEX_START";switch(t[0]){case"?":t[0]="INDEX_SOAK"}}switch(r){case"(":case"{":case"[":this.ends.push(b[r]);break;case")":case"}":case"]":this.pair(r)}return this.token(n,r),r.length},e.prototype.sanitizeHeredoc=function(e,t){var n,r,i,s,o;i=t.indent,r=t.herecomment;if(r){p.test(e)&&this.error('block comment cannot contain "*/", starting');if(e.indexOf("\n")<=0)return e}else while(s=d.exec(e)){n=s[1];if(i===null||0<(o=n.length)&&of;r=1<=f?++a:--a){if(n){--n;continue}switch(i=e.charAt(r)){case"\\":++n;continue;case t:u.pop();if(!u.length)return e.slice(0,+r+1||9e9);t=u[u.length-1];continue}t!=="}"||i!=='"'&&i!=="'"?t==="}"&&i==="/"&&(s=v.exec(e.slice(r))||P.exec(e.slice(r)))?n+=s[0].length-1:t==="}"&&i==="{"?u.push(t="}"):t==='"'&&o==="#"&&i==="{"&&u.push(t="}"):u.push(t=i),o=i}return this.error("missing "+u.pop()+", starting")},e.prototype.interpolateString=function(t,n){var r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w;n==null&&(n={}),i=n.heredoc,h=n.regex,d=[],c=0,s=-1;while(f=t.charAt(s+=1)){if(f==="\\"){s+=1;continue}if(f!=="#"||t.charAt(s+1)!=="{"||!(r=this.balancedString(t.slice(s+1),"}")))continue;c1&&(l.unshift(["(","(",this.line]),l.push([")",")",this.line])),d.push(["TOKENS",l])}s+=r.length,c=s+1}s>c&&c1)&&this.token("(","(");for(s=m=0,g=d.length;m|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/,z=/^[^\n\S]+/,f=/^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/,s=/^[-=]>/,A=/^(?:\n[^\n\S]*)+/,I=/^'[^\\']*(?:\\.[^\\']*)*'/,w=/^`[^\\`]*(?:\\.[^\\`]*)*`/,P=/^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/,v=/^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/,m=/\s+(?:#.*)?/g,L=/\n/g,d=/\n+([^\n\S]*)/g,p=/\*\//,T=/^\s*(?:,|\??\.(?![.\d])|::)/,R=/\s+$/,c=["-=","+=","/=","*=","%=","||=","&&=","?=","<<=",">>=",">>>=","&=","^=","|="],U=["!","~","NEW","TYPEOF","DELETE","DO"],N=["&&","||","&","|","^"],F=["<<",">>",">>>"],l=["==","!=","<",">","<=",">="],k=["*","/","%"],H=["IN","OF","INSTANCEOF"],r=["TRUE","FALSE"],O=["NUMBER","REGEX","BOOL","NULL","UNDEFINED","++","--","]"],M=O.concat(")","}","THIS","IDENTIFIER","STRING"),i=["IDENTIFIER","STRING","REGEX",")","]","}","?","::","@","THIS","SUPER"],y=i.concat("NUMBER","BOOL","NULL","UNDEFINED"),x=["INDENT","OUTDENT","TERMINATOR"]}),define("ace/mode/coffee/rewriter",["require","exports","module"],function(e,t,n){var r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E=[].indexOf||function(e){for(var t=0,n=this.length;t=0)r+=1;else if(f=i[0],E.call(s,f)>=0)r-=1;e+=1}return e-1},e.prototype.removeLeadingNewlines=function(){var e,t,n,r,i;i=this.tokens;for(e=n=0,r=i.length;n=0)?(n.splice(t,1),0):1})},e.prototype.closeOpenCalls=function(){var e,t;return t=function(e,t){var n;return(n=e[0])===")"||n==="CALL_END"||e[0]==="OUTDENT"&&this.tag(t-1)===")"},e=function(e,t){return this.tokens[e[0]==="OUTDENT"?t-1:t][0]="CALL_END"},this.scanTokens(function(n,r){return n[0]==="CALL_START"&&this.detectEnd(r+1,t,e),1})},e.prototype.closeOpenIndexes=function(){var e,t;return t=function(e,t){var n;return(n=e[0])==="]"||n==="INDEX_END"},e=function(e,t){return e[0]="INDEX_END"},this.scanTokens(function(n,r){return n[0]==="INDEX_START"&&this.detectEnd(r+1,t,e),1})},e.prototype.addImplicitBraces=function(){var e,t,n,r,i,u,a,l;return r=[],i=null,l=null,n=!0,u=0,a=0,t=function(e,t){var r,i,s,o,u,c;return u=this.tokens.slice(t+1,+(t+3)+1||9e9),r=u[0],o=u[1],s=u[2],"HERECOMMENT"===(r!=null?r[0]:void 0)?!1:(i=e[0],E.call(p,i)>=0&&(n=!1),(i==="TERMINATOR"||i==="OUTDENT"||E.call(f,i)>=0&&n&&t-a!==1)&&(!l&&this.tag(t-1)!==","||(o!=null?o[0]:void 0)!==":"&&((r!=null?r[0]:void 0)!=="@"||(s!=null?s[0]:void 0)!==":"))||i===","&&r&&(c=r[0])!=="IDENTIFIER"&&c!=="NUMBER"&&c!=="STRING"&&c!=="@"&&c!=="TERMINATOR"&&c!=="OUTDENT")},e=function(e,t){var n;return n=this.generate("}","}",e[2]),this.tokens.splice(t,0,n)},this.scanTokens(function(u,f,c){var h,d,v,m,g,y,b,w;if(b=m=u[0],E.call(o,b)>=0)return r.push([m==="INDENT"&&this.tag(f-1)==="{"?"{":m,f]),1;if(E.call(s,m)>=0)return i=r.pop(),1;if(m!==":"||(h=this.tag(f-2))!==":"&&((w=r[r.length-1])!=null?w[0]:void 0)==="{")return 1;n=!0,a=f+1,r.push(["{"]),d=h==="@"?f-2:f-1;while(this.tag(d-2)==="HERECOMMENT")d-=2;return v=this.tag(d-1),l=!v||E.call(p,v)>=0,y=new String("{"),y.generated=!0,g=this.generate("{",y,u[2]),c.splice(d,0,g),this.detectEnd(f+2,t,e),2})},e.prototype.addImplicitParentheses=function(){var e,t,n,r,i;return n=i=r=!1,t=function(e,t){var n,s,o,a;s=e[0];if(!i&&e.fromThen)return!0;if(s==="IF"||s==="ELSE"||s==="CATCH"||s==="->"||s==="=>"||s==="CLASS")i=!0;if(s==="IF"||s==="ELSE"||s==="SWITCH"||s==="TRY"||s==="=")r=!0;return s!=="."&&s!=="?."&&s!=="::"||this.tag(t-1)!=="OUTDENT"?!e.generated&&this.tag(t-1)!==","&&(E.call(f,s)>=0||s==="INDENT"&&!r)&&(s!=="INDENT"||(o=this.tag(t-2))!=="CLASS"&&o!=="EXTENDS"&&(a=this.tag(t-1),E.call(u,a)<0)&&(!(n=this.tokens[t+1])||!n.generated||n[0]!=="{")):!0},e=function(e,t){return this.tokens.splice(t,0,this.generate("CALL_END",")",e[2]))},this.scanTokens(function(s,o,u){var f,h,d,v,m,g,y,b;m=s[0];if(m==="CLASS"||m==="IF"||m==="FOR"||m==="WHILE")n=!0;return g=u.slice(o-1,+(o+1)+1||9e9),v=g[0],h=g[1],d=g[2],f=!n&&m==="INDENT"&&d&&d.generated&&d[0]==="{"&&v&&(y=v[0],E.call(l,y)>=0),i=!1,r=!1,E.call(p,m)>=0&&(n=!1),v&&!v.spaced&&m==="?"&&(s.call=!0),s.fromThen?1:f||(v!=null?v.spaced:void 0)&&(v.call||(b=v[0],E.call(l,b)>=0))&&(E.call(a,m)>=0||!s.spaced&&!s.newLine&&E.call(c,m)>=0)?(u.splice(o,0,this.generate("CALL_START","(",s[2])),this.detectEnd(o+1,t,e),v[0]==="?"&&(v[0]="FUNC_EXIST"),2):1})},e.prototype.addImplicitIndentation=function(){var e,t,n,r,i;return i=n=r=null,t=function(e,t){var n;return e[1]!==";"&&(n=e[0],E.call(d,n)>=0)&&(e[0]!=="ELSE"||i==="IF"||i==="THEN")},e=function(e,t){return this.tokens.splice(this.tag(t-1)===","?t-1:t,0,r)},this.scanTokens(function(s,o,u){var a,f,l;return a=s[0],a==="TERMINATOR"&&this.tag(o+1)==="THEN"?(u.splice(o,1),0):a==="ELSE"&&this.tag(o-1)!=="OUTDENT"?(u.splice.apply(u,[o,0].concat(S.call(this.indentation(s)))),2):a!=="CATCH"||(f=this.tag(o+2))!=="OUTDENT"&&f!=="TERMINATOR"&&f!=="FINALLY"?E.call(v,a)>=0&&this.tag(o+1)!=="INDENT"&&(a!=="ELSE"||this.tag(o+1)!=="IF")?(i=a,l=this.indentation(s,!0),n=l[0],r=l[1],i==="THEN"&&(n.fromThen=!0),u.splice(o+1,0,n),this.detectEnd(o+2,t,e),a==="THEN"&&u.splice(o,1),1):1:(u.splice.apply(u,[o+2,0].concat(S.call(this.indentation(s)))),4)})},e.prototype.tagPostfixConditionals=function(){var e,t,n;return n=null,t=function(e,t){var n;return(n=e[0])==="TERMINATOR"||n==="INDENT"},e=function(e,t){if(e[0]!=="INDENT"||e.generated&&!e.fromThen)return n[0]="POST_"+n[0]},this.scanTokens(function(r,i){return r[0]!=="IF"?1:(n=r,this.detectEnd(i+1,t,e),1)})},e.prototype.indentation=function(e,t){var n,r;return t==null&&(t=!1),n=["INDENT",2,e[2]],r=["OUTDENT",2,e[2]],t&&(n.generated=r.generated=!0),[n,r]},e.prototype.generate=function(e,t,n){var r;return r=[e,t,n],r.generated=!0,r},e.prototype.tag=function(e){var t;return(t=this.tokens[e])!=null?t[0]:void 0},e}(),r=[["(",")"],["[","]"],["{","}"],["INDENT","OUTDENT"],["CALL_START","CALL_END"],["PARAM_START","PARAM_END"],["INDEX_START","INDEX_END"]],t.INVERSES=h={},o=[],s=[];for(y=0,b=r.length;y","=>","[","(","{","--","++"],c=["+","-"],u=["->","=>","{","[",","],f=["POST_IF","FOR","WHILE","UNTIL","WHEN","BY","LOOP","TERMINATOR"],v=["ELSE","->","=>","TRY","FINALLY","THEN"],d=["TERMINATOR","CATCH","FINALLY","ELSE","OUTDENT","LEADING_WHEN"],p=["TERMINATOR","INDENT","OUTDENT"]}),define("ace/mode/coffee/helpers",["require","exports","module"],function(e,t,n){var r,i,s;t.starts=function(e,t,n){return t===e.substr(n,t.length)},t.ends=function(e,t,n){var r;return r=t.length,t===e.substr(e.length-r-(n||0),r)},t.compact=function(e){var t,n,r,i;i=[];for(n=0,r=e.length;n":51,"=>":52,OptComma:53,",":54,Param:55,ParamVar:56,"...":57,Array:58,Object:59,Splat:60,SimpleAssignable:61,Accessor:62,Parenthetical:63,Range:64,This:65,".":66,"?.":67,"::":68,Index:69,INDEX_START:70,IndexValue:71,INDEX_END:72,INDEX_SOAK:73,Slice:74,"{":75,AssignList:76,"}":77,CLASS:78,EXTENDS:79,OptFuncExist:80,Arguments:81,SUPER:82,FUNC_EXIST:83,CALL_START:84,CALL_END:85,ArgList:86,THIS:87,"@":88,"[":89,"]":90,RangeDots:91,"..":92,Arg:93,SimpleArgs:94,TRY:95,Catch:96,FINALLY:97,CATCH:98,THROW:99,"(":100,")":101,WhileSource:102,WHILE:103,WHEN:104,UNTIL:105,Loop:106,LOOP:107,ForBody:108,FOR:109,ForStart:110,ForSource:111,ForVariables:112,OWN:113,ForValue:114,FORIN:115,FOROF:116,BY:117,SWITCH:118,Whens:119,ELSE:120,When:121,LEADING_WHEN:122,IfBlock:123,IF:124,POST_IF:125,UNARY:126,"-":127,"+":128,"--":129,"++":130,"?":131,MATH:132,SHIFT:133,COMPARE:134,LOGIC:135,RELATION:136,COMPOUND_ASSIGN:137,$accept:0,$end:1},terminals_:{2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"UNDEFINED",37:"NULL",38:"BOOL",40:"=",43:":",45:"RETURN",46:"HERECOMMENT",47:"PARAM_START",49:"PARAM_END",51:"->",52:"=>",54:",",57:"...",66:".",67:"?.",68:"::",70:"INDEX_START",72:"INDEX_END",73:"INDEX_SOAK",75:"{",77:"}",78:"CLASS",79:"EXTENDS",82:"SUPER",83:"FUNC_EXIST",84:"CALL_START",85:"CALL_END",87:"THIS",88:"@",89:"[",90:"]",92:"..",95:"TRY",97:"FINALLY",98:"CATCH",99:"THROW",100:"(",101:")",103:"WHILE",104:"WHEN",105:"UNTIL",107:"LOOP",109:"FOR",113:"OWN",115:"FORIN",116:"FOROF",117:"BY",118:"SWITCH",120:"ELSE",122:"LEADING_WHEN",124:"IF",125:"POST_IF",126:"UNARY",127:"-",128:"+",129:"--",130:"++",131:"?",132:"MATH",133:"SHIFT",134:"COMPARE",135:"LOGIC",136:"RELATION",137:"COMPOUND_ASSIGN"},productions_:[0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[41,1],[41,3],[41,5],[41,1],[42,1],[42,1],[42,1],[10,2],[10,1],[11,1],[15,5],[15,2],[50,1],[50,1],[53,0],[53,1],[48,0],[48,1],[48,3],[48,4],[48,6],[55,1],[55,2],[55,3],[56,1],[56,1],[56,1],[56,1],[60,2],[61,1],[61,2],[61,2],[61,1],[39,1],[39,1],[39,1],[13,1],[13,1],[13,1],[13,1],[13,1],[62,2],[62,2],[62,2],[62,1],[62,1],[69,3],[69,2],[71,1],[71,1],[59,4],[76,0],[76,1],[76,3],[76,4],[76,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[80,0],[80,1],[81,2],[81,4],[65,1],[65,1],[44,2],[58,2],[58,4],[91,1],[91,1],[64,5],[74,3],[74,2],[74,2],[74,1],[86,1],[86,3],[86,4],[86,4],[86,6],[93,1],[93,1],[94,1],[94,3],[19,2],[19,3],[19,4],[19,5],[96,3],[24,2],[63,3],[63,5],[102,2],[102,4],[102,2],[102,4],[20,2],[20,2],[20,2],[20,1],[106,2],[106,2],[21,2],[21,2],[21,2],[108,2],[108,2],[110,2],[110,3],[114,1],[114,1],[114,1],[114,1],[112,1],[112,3],[111,2],[111,2],[111,4],[111,4],[111,4],[111,6],[111,6],[22,5],[22,7],[22,4],[22,6],[119,1],[119,2],[121,3],[121,4],[123,3],[123,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]],performAction:function(t,n,r,i,s,o,u){var a=o.length-1;switch(s){case 1:return this.$=new i.Block;case 2:return this.$=o[a];case 3:return this.$=o[a-1];case 4:this.$=i.Block.wrap([o[a]]);break;case 5:this.$=o[a-2].push(o[a]);break;case 6:this.$=o[a-1];break;case 7:this.$=o[a];break;case 8:this.$=o[a];break;case 9:this.$=o[a];break;case 10:this.$=o[a];break;case 11:this.$=new i.Literal(o[a]);break;case 12:this.$=o[a];break;case 13:this.$=o[a];break;case 14:this.$=o[a];break;case 15:this.$=o[a];break;case 16:this.$=o[a];break;case 17:this.$=o[a];break;case 18:this.$=o[a];break;case 19:this.$=o[a];break;case 20:this.$=o[a];break;case 21:this.$=o[a];break;case 22:this.$=o[a];break;case 23:this.$=o[a];break;case 24:this.$=new i.Block;break;case 25:this.$=o[a-1];break;case 26:this.$=new i.Literal(o[a]);break;case 27:this.$=new i.Literal(o[a]);break;case 28:this.$=new i.Literal(o[a]);break;case 29:this.$=o[a];break;case 30:this.$=new i.Literal(o[a]);break;case 31:this.$=new i.Literal(o[a]);break;case 32:this.$=new i.Literal(o[a]);break;case 33:this.$=new i.Undefined;break;case 34:this.$=new i.Null;break;case 35:this.$=new i.Bool(o[a]);break;case 36:this.$=new i.Assign(o[a-2],o[a]);break;case 37:this.$=new i.Assign(o[a-3],o[a]);break;case 38:this.$=new i.Assign(o[a-4],o[a-1]);break;case 39:this.$=new i.Value(o[a]);break;case 40:this.$=new i.Assign(new i.Value(o[a-2]),o[a],"object");break;case 41:this.$=new i.Assign(new i.Value(o[a-4]),o[a-1],"object");break;case 42:this.$=o[a];break;case 43:this.$=o[a];break;case 44:this.$=o[a];break;case 45:this.$=o[a];break;case 46:this.$=new i.Return(o[a]);break;case 47:this.$=new i.Return;break;case 48:this.$=new i.Comment(o[a]);break;case 49:this.$=new i.Code(o[a-3],o[a],o[a-1]);break;case 50:this.$=new i.Code([],o[a],o[a-1]);break;case 51:this.$="func";break;case 52:this.$="boundfunc";break;case 53:this.$=o[a];break;case 54:this.$=o[a];break;case 55:this.$=[];break;case 56:this.$=[o[a]];break;case 57:this.$=o[a-2].concat(o[a]);break;case 58:this.$=o[a-3].concat(o[a]);break;case 59:this.$=o[a-5].concat(o[a-2]);break;case 60:this.$=new i.Param(o[a]);break;case 61:this.$=new i.Param(o[a-1],null,!0);break;case 62:this.$=new i.Param(o[a-2],o[a]);break;case 63:this.$=o[a];break;case 64:this.$=o[a];break;case 65:this.$=o[a];break;case 66:this.$=o[a];break;case 67:this.$=new i.Splat(o[a-1]);break;case 68:this.$=new i.Value(o[a]);break;case 69:this.$=o[a-1].add(o[a]);break;case 70:this.$=new i.Value(o[a-1],[].concat(o[a]));break;case 71:this.$=o[a];break;case 72:this.$=o[a];break;case 73:this.$=new i.Value(o[a]);break;case 74:this.$=new i.Value(o[a]);break;case 75:this.$=o[a];break;case 76:this.$=new i.Value(o[a]);break;case 77:this.$=new i.Value(o[a]);break;case 78:this.$=new i.Value(o[a]);break;case 79:this.$=o[a];break;case 80:this.$=new i.Access(o[a]);break;case 81:this.$=new i.Access(o[a],"soak");break;case 82:this.$=[new i.Access(new i.Literal("prototype")),new i.Access(o[a])];break;case 83:this.$=new i.Access(new i.Literal("prototype"));break;case 84:this.$=o[a];break;case 85:this.$=o[a-1];break;case 86:this.$=i.extend(o[a],{soak:!0});break;case 87:this.$=new i.Index(o[a]);break;case 88:this.$=new i.Slice(o[a]);break;case 89:this.$=new i.Obj(o[a-2],o[a-3].generated);break;case 90:this.$=[];break;case 91:this.$=[o[a]];break;case 92:this.$=o[a-2].concat(o[a]);break;case 93:this.$=o[a-3].concat(o[a]);break;case 94:this.$=o[a-5].concat(o[a-2]);break;case 95:this.$=new i.Class;break;case 96:this.$=new i.Class(null,null,o[a]);break;case 97:this.$=new i.Class(null,o[a]);break;case 98:this.$=new i.Class(null,o[a-1],o[a]);break;case 99:this.$=new i.Class(o[a]);break;case 100:this.$=new i.Class(o[a-1],null,o[a]);break;case 101:this.$=new i.Class(o[a-2],o[a]);break;case 102:this.$=new i.Class(o[a-3],o[a-1],o[a]);break;case 103:this.$=new i.Call(o[a-2],o[a],o[a-1]);break;case 104:this.$=new i.Call(o[a-2],o[a],o[a-1]);break;case 105:this.$=new i.Call("super",[new i.Splat(new i.Literal("arguments"))]);break;case 106:this.$=new i.Call("super",o[a]);break;case 107:this.$=!1;break;case 108:this.$=!0;break;case 109:this.$=[];break;case 110:this.$=o[a-2];break;case 111:this.$=new i.Value(new i.Literal("this"));break;case 112:this.$=new i.Value(new i.Literal("this"));break;case 113:this.$=new i.Value(new i.Literal("this"),[new i.Access(o[a])],"this");break;case 114:this.$=new i.Arr([]);break;case 115:this.$=new i.Arr(o[a-2]);break;case 116:this.$="inclusive";break;case 117:this.$="exclusive";break;case 118:this.$=new i.Range(o[a-3],o[a-1],o[a-2]);break;case 119:this.$=new i.Range(o[a-2],o[a],o[a-1]);break;case 120:this.$=new i.Range(o[a-1],null,o[a]);break;case 121:this.$=new i.Range(null,o[a],o[a-1]);break;case 122:this.$=new i.Range(null,null,o[a]);break;case 123:this.$=[o[a]];break;case 124:this.$=o[a-2].concat(o[a]);break;case 125:this.$=o[a-3].concat(o[a]);break;case 126:this.$=o[a-2];break;case 127:this.$=o[a-5].concat(o[a-2]);break;case 128:this.$=o[a];break;case 129:this.$=o[a];break;case 130:this.$=o[a];break;case 131:this.$=[].concat(o[a-2],o[a]);break;case 132:this.$=new i.Try(o[a]);break;case 133:this.$=new i.Try(o[a-1],o[a][0],o[a][1]);break;case 134:this.$=new i.Try(o[a-2],null,null,o[a]);break;case 135:this.$=new i.Try(o[a-3],o[a-2][0],o[a-2][1],o[a]);break;case 136:this.$=[o[a-1],o[a]];break;case 137:this.$=new i.Throw(o[a]);break;case 138:this.$=new i.Parens(o[a-1]);break;case 139:this.$=new i.Parens(o[a-2]);break;case 140:this.$=new i.While(o[a]);break;case 141:this.$=new i.While(o[a-2],{guard:o[a]});break;case 142:this.$=new i.While(o[a],{invert:!0});break;case 143:this.$=new i.While(o[a-2],{invert:!0,guard:o[a]});break;case 144:this.$=o[a-1].addBody(o[a]);break;case 145:this.$=o[a].addBody(i.Block.wrap([o[a-1]]));break;case 146:this.$=o[a].addBody(i.Block.wrap([o[a-1]]));break;case 147:this.$=o[a];break;case 148:this.$=(new i.While(new i.Literal("true"))).addBody(o[a]);break;case 149:this.$=(new i.While(new i.Literal("true"))).addBody(i.Block.wrap([o[a]]));break;case 150:this.$=new i.For(o[a-1],o[a]);break;case 151:this.$=new i.For(o[a-1],o[a]);break;case 152:this.$=new i.For(o[a],o[a-1]);break;case 153:this.$={source:new i.Value(o[a])};break;case 154:this.$=function(){return o[a].own=o[a-1].own,o[a].name=o[a-1][0],o[a].index=o[a-1][1],o[a]}();break;case 155:this.$=o[a];break;case 156:this.$=function(){return o[a].own=!0,o[a]}();break;case 157:this.$=o[a];break;case 158:this.$=o[a];break;case 159:this.$=new i.Value(o[a]);break;case 160:this.$=new i.Value(o[a]);break;case 161:this.$=[o[a]];break;case 162:this.$=[o[a-2],o[a]];break;case 163:this.$={source:o[a]};break;case 164:this.$={source:o[a],object:!0};break;case 165:this.$={source:o[a-2],guard:o[a]};break;case 166:this.$={source:o[a-2],guard:o[a],object:!0};break;case 167:this.$={source:o[a-2],step:o[a]};break;case 168:this.$={source:o[a-4],guard:o[a-2],step:o[a]};break;case 169:this.$={source:o[a-4],step:o[a-2],guard:o[a]};break;case 170:this.$=new i.Switch(o[a-3],o[a-1]);break;case 171:this.$=new i.Switch(o[a-5],o[a-3],o[a-1]);break;case 172:this.$=new i.Switch(null,o[a-1]);break;case 173:this.$=new i.Switch(null,o[a-3],o[a-1]);break;case 174:this.$=o[a];break;case 175:this.$=o[a-1].concat(o[a]);break;case 176:this.$=[[o[a-1],o[a]]];break;case 177:this.$=[[o[a-2],o[a-1]]];break;case 178:this.$=new i.If(o[a-1],o[a],{type:o[a-2]});break;case 179:this.$=o[a-4].addElse(new i.If(o[a-1],o[a],{type:o[a-2]}));break;case 180:this.$=o[a];break;case 181:this.$=o[a-2].addElse(o[a]);break;case 182:this.$=new i.If(o[a],i.Block.wrap([o[a-2]]),{type:o[a-1],statement:!0});break;case 183:this.$=new i.If(o[a],i.Block.wrap([o[a-2]]),{type:o[a-1],statement:!0});break;case 184:this.$=new i.Op(o[a-1],o[a]);break;case 185:this.$=new i.Op("-",o[a]);break;case 186:this.$=new i.Op("+",o[a]);break;case 187:this.$=new i.Op("--",o[a]);break;case 188:this.$=new i.Op("++",o[a]);break;case 189:this.$=new i.Op("--",o[a-1],null,!0);break;case 190:this.$=new i.Op("++",o[a-1],null,!0);break;case 191:this.$=new i.Existence(o[a-1]);break;case 192:this.$=new i.Op("+",o[a-2],o[a]);break;case 193:this.$=new i.Op("-",o[a-2],o[a]);break;case 194:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 195:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 196:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 197:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 198:this.$=function(){return o[a-1].charAt(0)==="!"?(new i.Op(o[a-1].slice(1),o[a-2],o[a])).invert():new i.Op(o[a-1],o[a-2],o[a])}();break;case 199:this.$=new i.Assign(o[a-2],o[a],o[a-1]);break;case 200:this.$=new i.Assign(o[a-4],o[a-1],o[a-3]);break;case 201:this.$=new i.Extends(o[a-2],o[a])}},table:[{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[3]},{1:[2,2],6:[1,74]},{6:[1,75]},{1:[2,4],6:[2,4],26:[2,4],101:[2,4]},{4:77,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,76],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,7],6:[2,7],26:[2,7],101:[2,7],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,8],6:[2,8],26:[2,8],101:[2,8],102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],49:[2,12],54:[2,12],57:[2,12],62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,12],73:[1,100],77:[2,12],80:92,83:[1,94],84:[2,107],85:[2,12],90:[2,12],92:[2,12],101:[2,12],103:[2,12],104:[2,12],105:[2,12],109:[2,12],117:[2,12],125:[2,12],127:[2,12],128:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12],135:[2,12],136:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],49:[2,13],54:[2,13],57:[2,13],62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,13],73:[1,100],77:[2,13],80:101,83:[1,94],84:[2,107],85:[2,13],90:[2,13],92:[2,13],101:[2,13],103:[2,13],104:[2,13],105:[2,13],109:[2,13],117:[2,13],125:[2,13],127:[2,13],128:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13],135:[2,13],136:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],49:[2,14],54:[2,14],57:[2,14],72:[2,14],77:[2,14],85:[2,14],90:[2,14],92:[2,14],101:[2,14],103:[2,14],104:[2,14],105:[2,14],109:[2,14],117:[2,14],125:[2,14],127:[2,14],128:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14],135:[2,14],136:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],49:[2,15],54:[2,15],57:[2,15],72:[2,15],77:[2,15],85:[2,15],90:[2,15],92:[2,15],101:[2,15],103:[2,15],104:[2,15],105:[2,15],109:[2,15],117:[2,15],125:[2,15],127:[2,15],128:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15],135:[2,15],136:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],49:[2,16],54:[2,16],57:[2,16],72:[2,16],77:[2,16],85:[2,16],90:[2,16],92:[2,16],101:[2,16],103:[2,16],104:[2,16],105:[2,16],109:[2,16],117:[2,16],125:[2,16],127:[2,16],128:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16],135:[2,16],136:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],49:[2,17],54:[2,17],57:[2,17],72:[2,17],77:[2,17],85:[2,17],90:[2,17],92:[2,17],101:[2,17],103:[2,17],104:[2,17],105:[2,17],109:[2,17],117:[2,17],125:[2,17],127:[2,17],128:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17],135:[2,17],136:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],49:[2,18],54:[2,18],57:[2,18],72:[2,18],77:[2,18],85:[2,18],90:[2,18],92:[2,18],101:[2,18],103:[2,18],104:[2,18],105:[2,18],109:[2,18],117:[2,18],125:[2,18],127:[2,18],128:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18],135:[2,18],136:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],49:[2,19],54:[2,19],57:[2,19],72:[2,19],77:[2,19],85:[2,19],90:[2,19],92:[2,19],101:[2,19],103:[2,19],104:[2,19],105:[2,19],109:[2,19],117:[2,19],125:[2,19],127:[2,19],128:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19],135:[2,19],136:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],49:[2,20],54:[2,20],57:[2,20],72:[2,20],77:[2,20],85:[2,20],90:[2,20],92:[2,20],101:[2,20],103:[2,20],104:[2,20],105:[2,20],109:[2,20],117:[2,20],125:[2,20],127:[2,20],128:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20],135:[2,20],136:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],49:[2,21],54:[2,21],57:[2,21],72:[2,21],77:[2,21],85:[2,21],90:[2,21],92:[2,21],101:[2,21],103:[2,21],104:[2,21],105:[2,21],109:[2,21],117:[2,21],125:[2,21],127:[2,21],128:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21],135:[2,21],136:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],49:[2,22],54:[2,22],57:[2,22],72:[2,22],77:[2,22],85:[2,22],90:[2,22],92:[2,22],101:[2,22],103:[2,22],104:[2,22],105:[2,22],109:[2,22],117:[2,22],125:[2,22],127:[2,22],128:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22],135:[2,22],136:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],49:[2,23],54:[2,23],57:[2,23],72:[2,23],77:[2,23],85:[2,23],90:[2,23],92:[2,23],101:[2,23],103:[2,23],104:[2,23],105:[2,23],109:[2,23],117:[2,23],125:[2,23],127:[2,23],128:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23],135:[2,23],136:[2,23]},{1:[2,9],6:[2,9],26:[2,9],101:[2,9],103:[2,9],105:[2,9],109:[2,9],125:[2,9]},{1:[2,10],6:[2,10],26:[2,10],101:[2,10],103:[2,10],105:[2,10],109:[2,10],125:[2,10]},{1:[2,11],6:[2,11],26:[2,11],101:[2,11],103:[2,11],105:[2,11],109:[2,11],125:[2,11]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],40:[1,103],49:[2,75],54:[2,75],57:[2,75],66:[2,75],67:[2,75],68:[2,75],70:[2,75],72:[2,75],73:[2,75],77:[2,75],83:[2,75],84:[2,75],85:[2,75],90:[2,75],92:[2,75],101:[2,75],103:[2,75],104:[2,75],105:[2,75],109:[2,75],117:[2,75],125:[2,75],127:[2,75],128:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],49:[2,76],54:[2,76],57:[2,76],66:[2,76],67:[2,76],68:[2,76],70:[2,76],72:[2,76],73:[2,76],77:[2,76],83:[2,76],84:[2,76],85:[2,76],90:[2,76],92:[2,76],101:[2,76],103:[2,76],104:[2,76],105:[2,76],109:[2,76],117:[2,76],125:[2,76],127:[2,76],128:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76],136:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],49:[2,77],54:[2,77],57:[2,77],66:[2,77],67:[2,77],68:[2,77],70:[2,77],72:[2,77],73:[2,77],77:[2,77],83:[2,77],84:[2,77],85:[2,77],90:[2,77],92:[2,77],101:[2,77],103:[2,77],104:[2,77],105:[2,77],109:[2,77],117:[2,77],125:[2,77],127:[2,77],128:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77],136:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],49:[2,78],54:[2,78],57:[2,78],66:[2,78],67:[2,78],68:[2,78],70:[2,78],72:[2,78],73:[2,78],77:[2,78],83:[2,78],84:[2,78],85:[2,78],90:[2,78],92:[2,78],101:[2,78],103:[2,78],104:[2,78],105:[2,78],109:[2,78],117:[2,78],125:[2,78],127:[2,78],128:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78],136:[2,78]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],49:[2,79],54:[2,79],57:[2,79],66:[2,79],67:[2,79],68:[2,79],70:[2,79],72:[2,79],73:[2,79],77:[2,79],83:[2,79],84:[2,79],85:[2,79],90:[2,79],92:[2,79],101:[2,79],103:[2,79],104:[2,79],105:[2,79],109:[2,79],117:[2,79],125:[2,79],127:[2,79],128:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79],136:[2,79]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],49:[2,105],54:[2,105],57:[2,105],66:[2,105],67:[2,105],68:[2,105],70:[2,105],72:[2,105],73:[2,105],77:[2,105],81:104,83:[2,105],84:[1,105],85:[2,105],90:[2,105],92:[2,105],101:[2,105],103:[2,105],104:[2,105],105:[2,105],109:[2,105],117:[2,105],125:[2,105],127:[2,105],128:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105],135:[2,105],136:[2,105]},{6:[2,55],25:[2,55],27:109,28:[1,73],44:110,48:106,49:[2,55],54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{5:115,25:[1,5]},{8:116,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:118,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:119,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:120,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:124,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],40:[2,72],49:[2,72],54:[2,72],57:[2,72],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,72],73:[2,72],77:[2,72],79:[1,128],83:[2,72],84:[2,72],85:[2,72],90:[2,72],92:[2,72],101:[2,72],103:[2,72],104:[2,72],105:[2,72],109:[2,72],117:[2,72],125:[2,72],127:[2,72],128:[2,72],129:[1,125],130:[1,126],131:[2,72],132:[2,72],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[1,127]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],49:[2,180],54:[2,180],57:[2,180],72:[2,180],77:[2,180],85:[2,180],90:[2,180],92:[2,180],101:[2,180],103:[2,180],104:[2,180],105:[2,180],109:[2,180],117:[2,180],120:[1,129],125:[2,180],127:[2,180],128:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180],135:[2,180],136:[2,180]},{5:130,25:[1,5]},{5:131,25:[1,5]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],49:[2,147],54:[2,147],57:[2,147],72:[2,147],77:[2,147],85:[2,147],90:[2,147],92:[2,147],101:[2,147],103:[2,147],104:[2,147],105:[2,147],109:[2,147],117:[2,147],125:[2,147],127:[2,147],128:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147],135:[2,147],136:[2,147]},{5:132,25:[1,5]},{8:133,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,134],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,95],5:135,6:[2,95],13:121,14:122,25:[1,5],26:[2,95],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,49:[2,95],54:[2,95],57:[2,95],58:47,59:48,61:137,63:25,64:26,65:27,72:[2,95],75:[1,70],77:[2,95],79:[1,136],82:[1,28],85:[2,95],87:[1,58],88:[1,59],89:[1,57],90:[2,95],92:[2,95],100:[1,56],101:[2,95],103:[2,95],104:[2,95],105:[2,95],109:[2,95],117:[2,95],125:[2,95],127:[2,95],128:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95],135:[2,95],136:[2,95]},{8:138,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,47],6:[2,47],8:139,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,47],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,47],102:39,103:[2,47],105:[2,47],106:40,107:[1,67],108:41,109:[2,47],110:69,118:[1,42],123:37,124:[1,64],125:[2,47],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],54:[2,48],77:[2,48],101:[2,48],103:[2,48],105:[2,48],109:[2,48],125:[2,48]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],40:[2,73],49:[2,73],54:[2,73],57:[2,73],66:[2,73],67:[2,73],68:[2,73],70:[2,73],72:[2,73],73:[2,73],77:[2,73],83:[2,73],84:[2,73],85:[2,73],90:[2,73],92:[2,73],101:[2,73],103:[2,73],104:[2,73],105:[2,73],109:[2,73],117:[2,73],125:[2,73],127:[2,73],128:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],40:[2,74],49:[2,74],54:[2,74],57:[2,74],66:[2,74],67:[2,74],68:[2,74],70:[2,74],72:[2,74],73:[2,74],77:[2,74],83:[2,74],84:[2,74],85:[2,74],90:[2,74],92:[2,74],101:[2,74],103:[2,74],104:[2,74],105:[2,74],109:[2,74],117:[2,74],125:[2,74],127:[2,74],128:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],49:[2,29],54:[2,29],57:[2,29],66:[2,29],67:[2,29],68:[2,29],70:[2,29],72:[2,29],73:[2,29],77:[2,29],83:[2,29],84:[2,29],85:[2,29],90:[2,29],92:[2,29],101:[2,29],103:[2,29],104:[2,29],105:[2,29],109:[2,29],117:[2,29],125:[2,29],127:[2,29],128:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29],135:[2,29],136:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],49:[2,30],54:[2,30],57:[2,30],66:[2,30],67:[2,30],68:[2,30],70:[2,30],72:[2,30],73:[2,30],77:[2,30],83:[2,30],84:[2,30],85:[2,30],90:[2,30],92:[2,30],101:[2,30],103:[2,30],104:[2,30],105:[2,30],109:[2,30],117:[2,30],125:[2,30],127:[2,30],128:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],49:[2,31],54:[2,31],57:[2,31],66:[2,31],67:[2,31],68:[2,31],70:[2,31],72:[2,31],73:[2,31],77:[2,31],83:[2,31],84:[2,31],85:[2,31],90:[2,31],92:[2,31],101:[2,31],103:[2,31],104:[2,31],105:[2,31],109:[2,31],117:[2,31],125:[2,31],127:[2,31],128:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31],135:[2,31],136:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],49:[2,32],54:[2,32],57:[2,32],66:[2,32],67:[2,32],68:[2,32],70:[2,32],72:[2,32],73:[2,32],77:[2,32],83:[2,32],84:[2,32],85:[2,32],90:[2,32],92:[2,32],101:[2,32],103:[2,32],104:[2,32],105:[2,32],109:[2,32],117:[2,32],125:[2,32],127:[2,32],128:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32],135:[2,32],136:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],49:[2,33],54:[2,33],57:[2,33],66:[2,33],67:[2,33],68:[2,33],70:[2,33],72:[2,33],73:[2,33],77:[2,33],83:[2,33],84:[2,33],85:[2,33],90:[2,33],92:[2,33],101:[2,33],103:[2,33],104:[2,33],105:[2,33],109:[2,33],117:[2,33],125:[2,33],127:[2,33],128:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33],135:[2,33],136:[2,33]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],49:[2,34],54:[2,34],57:[2,34],66:[2,34],67:[2,34],68:[2,34],70:[2,34],72:[2,34],73:[2,34],77:[2,34],83:[2,34],84:[2,34],85:[2,34],90:[2,34],92:[2,34],101:[2,34],103:[2,34],104:[2,34],105:[2,34],109:[2,34],117:[2,34],125:[2,34],127:[2,34],128:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34],135:[2,34],136:[2,34]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],49:[2,35],54:[2,35],57:[2,35],66:[2,35],67:[2,35],68:[2,35],70:[2,35],72:[2,35],73:[2,35],77:[2,35],83:[2,35],84:[2,35],85:[2,35],90:[2,35],92:[2,35],101:[2,35],103:[2,35],104:[2,35],105:[2,35],109:[2,35],117:[2,35],125:[2,35],127:[2,35],128:[2,35],131:[2,35],132:[2,35],133:[2,35],134:[2,35],135:[2,35],136:[2,35]},{4:140,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,141],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:142,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],49:[2,111],54:[2,111],57:[2,111],66:[2,111],67:[2,111],68:[2,111],70:[2,111],72:[2,111],73:[2,111],77:[2,111],83:[2,111],84:[2,111],85:[2,111],90:[2,111],92:[2,111],101:[2,111],103:[2,111],104:[2,111],105:[2,111],109:[2,111],117:[2,111],125:[2,111],127:[2,111],128:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111],135:[2,111],136:[2,111]},{1:[2,112],6:[2,112],25:[2,112],26:[2,112],27:148,28:[1,73],49:[2,112],54:[2,112],57:[2,112],66:[2,112],67:[2,112],68:[2,112],70:[2,112],72:[2,112],73:[2,112],77:[2,112],83:[2,112],84:[2,112],85:[2,112],90:[2,112],92:[2,112],101:[2,112],103:[2,112],104:[2,112],105:[2,112],109:[2,112],117:[2,112],125:[2,112],127:[2,112],128:[2,112],131:[2,112],132:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112]},{25:[2,51]},{25:[2,52]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],40:[2,68],49:[2,68],54:[2,68],57:[2,68],66:[2,68],67:[2,68],68:[2,68],70:[2,68],72:[2,68],73:[2,68],77:[2,68],79:[2,68],83:[2,68],84:[2,68],85:[2,68],90:[2,68],92:[2,68],101:[2,68],103:[2,68],104:[2,68],105:[2,68],109:[2,68],117:[2,68],125:[2,68],127:[2,68],128:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[2,68],136:[2,68],137:[2,68]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],40:[2,71],49:[2,71],54:[2,71],57:[2,71],66:[2,71],67:[2,71],68:[2,71],70:[2,71],72:[2,71],73:[2,71],77:[2,71],79:[2,71],83:[2,71],84:[2,71],85:[2,71],90:[2,71],92:[2,71],101:[2,71],103:[2,71],104:[2,71],105:[2,71],109:[2,71],117:[2,71],125:[2,71],127:[2,71],128:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71],135:[2,71],136:[2,71],137:[2,71]},{8:149,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:150,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:151,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:152,8:153,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{27:158,28:[1,73],44:159,58:160,59:161,64:154,75:[1,70],88:[1,113],89:[1,57],112:155,113:[1,156],114:157},{111:162,115:[1,163],116:[1,164]},{6:[2,90],11:168,25:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:165,77:[2,90],88:[1,113]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],43:[2,27],49:[2,27],54:[2,27],57:[2,27],66:[2,27],67:[2,27],68:[2,27],70:[2,27],72:[2,27],73:[2,27],77:[2,27],83:[2,27],84:[2,27],85:[2,27],90:[2,27],92:[2,27],101:[2,27],103:[2,27],104:[2,27],105:[2,27],109:[2,27],117:[2,27],125:[2,27],127:[2,27],128:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27],135:[2,27],136:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],43:[2,28],49:[2,28],54:[2,28],57:[2,28],66:[2,28],67:[2,28],68:[2,28],70:[2,28],72:[2,28],73:[2,28],77:[2,28],83:[2,28],84:[2,28],85:[2,28],90:[2,28],92:[2,28],101:[2,28],103:[2,28],104:[2,28],105:[2,28],109:[2,28],117:[2,28],125:[2,28],127:[2,28],128:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28],135:[2,28],136:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],40:[2,26],43:[2,26],49:[2,26],54:[2,26],57:[2,26],66:[2,26],67:[2,26],68:[2,26],70:[2,26],72:[2,26],73:[2,26],77:[2,26],79:[2,26],83:[2,26],84:[2,26],85:[2,26],90:[2,26],92:[2,26],101:[2,26],103:[2,26],104:[2,26],105:[2,26],109:[2,26],115:[2,26],116:[2,26],117:[2,26],125:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26],136:[2,26],137:[2,26]},{1:[2,6],6:[2,6],7:172,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,6],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],49:[2,24],54:[2,24],57:[2,24],72:[2,24],77:[2,24],85:[2,24],90:[2,24],92:[2,24],97:[2,24],98:[2,24],101:[2,24],103:[2,24],104:[2,24],105:[2,24],109:[2,24],117:[2,24],120:[2,24],122:[2,24],125:[2,24],127:[2,24],128:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24],135:[2,24],136:[2,24]},{6:[1,74],26:[1,173]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],49:[2,191],54:[2,191],57:[2,191],72:[2,191],77:[2,191],85:[2,191],90:[2,191],92:[2,191],101:[2,191],103:[2,191],104:[2,191],105:[2,191],109:[2,191],117:[2,191],125:[2,191],127:[2,191],128:[2,191],131:[2,191],132:[2,191],133:[2,191],134:[2,191],135:[2,191],136:[2,191]},{8:174,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:175,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:176,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:177,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:178,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:179,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:180,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:181,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],49:[2,146],54:[2,146],57:[2,146],72:[2,146],77:[2,146],85:[2,146],90:[2,146],92:[2,146],101:[2,146],103:[2,146],104:[2,146],105:[2,146],109:[2,146],117:[2,146],125:[2,146],127:[2,146],128:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146],135:[2,146],136:[2,146]},{1:[2,151],6:[2,151],25:[2,151],26:[2,151],49:[2,151],54:[2,151],57:[2,151],72:[2,151],77:[2,151],85:[2,151],90:[2,151],92:[2,151],101:[2,151],103:[2,151],104:[2,151],105:[2,151],109:[2,151],117:[2,151],125:[2,151],127:[2,151],128:[2,151],131:[2,151],132:[2,151],133:[2,151],134:[2,151],135:[2,151],136:[2,151]},{8:182,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],49:[2,145],54:[2,145],57:[2,145],72:[2,145],77:[2,145],85:[2,145],90:[2,145],92:[2,145],101:[2,145],103:[2,145],104:[2,145],105:[2,145],109:[2,145],117:[2,145],125:[2,145],127:[2,145],128:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145],135:[2,145],136:[2,145]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],49:[2,150],54:[2,150],57:[2,150],72:[2,150],77:[2,150],85:[2,150],90:[2,150],92:[2,150],101:[2,150],103:[2,150],104:[2,150],105:[2,150],109:[2,150],117:[2,150],125:[2,150],127:[2,150],128:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150],135:[2,150],136:[2,150]},{81:183,84:[1,105]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],40:[2,69],49:[2,69],54:[2,69],57:[2,69],66:[2,69],67:[2,69],68:[2,69],70:[2,69],72:[2,69],73:[2,69],77:[2,69],79:[2,69],83:[2,69],84:[2,69],85:[2,69],90:[2,69],92:[2,69],101:[2,69],103:[2,69],104:[2,69],105:[2,69],109:[2,69],117:[2,69],125:[2,69],127:[2,69],128:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69],135:[2,69],136:[2,69],137:[2,69]},{84:[2,108]},{27:184,28:[1,73]},{27:185,28:[1,73]},{1:[2,83],6:[2,83],25:[2,83],26:[2,83],27:186,28:[1,73],40:[2,83],49:[2,83],54:[2,83],57:[2,83],66:[2,83],67:[2,83],68:[2,83],70:[2,83],72:[2,83],73:[2,83],77:[2,83],79:[2,83],83:[2,83],84:[2,83],85:[2,83],90:[2,83],92:[2,83],101:[2,83],103:[2,83],104:[2,83],105:[2,83],109:[2,83],117:[2,83],125:[2,83],127:[2,83],128:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],133:[2,83],134:[2,83],135:[2,83],136:[2,83],137:[2,83]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],40:[2,84],49:[2,84],54:[2,84],57:[2,84],66:[2,84],67:[2,84],68:[2,84],70:[2,84],72:[2,84],73:[2,84],77:[2,84],79:[2,84],83:[2,84],84:[2,84],85:[2,84],90:[2,84],92:[2,84],101:[2,84],103:[2,84],104:[2,84],105:[2,84],109:[2,84],117:[2,84],125:[2,84],127:[2,84],128:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84]},{8:188,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],57:[1,192],58:47,59:48,61:36,63:25,64:26,65:27,71:187,74:189,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],91:190,92:[1,191],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{69:193,70:[1,99],73:[1,100]},{81:194,84:[1,105]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],40:[2,70],49:[2,70],54:[2,70],57:[2,70],66:[2,70],67:[2,70],68:[2,70],70:[2,70],72:[2,70],73:[2,70],77:[2,70],79:[2,70],83:[2,70],84:[2,70],85:[2,70],90:[2,70],92:[2,70],101:[2,70],103:[2,70],104:[2,70],105:[2,70],109:[2,70],117:[2,70],125:[2,70],127:[2,70],128:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70],135:[2,70],136:[2,70],137:[2,70]},{6:[1,196],8:195,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,197],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],49:[2,106],54:[2,106],57:[2,106],66:[2,106],67:[2,106],68:[2,106],70:[2,106],72:[2,106],73:[2,106],77:[2,106],83:[2,106],84:[2,106],85:[2,106],90:[2,106],92:[2,106],101:[2,106],103:[2,106],104:[2,106],105:[2,106],109:[2,106],117:[2,106],125:[2,106],127:[2,106],128:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106],135:[2,106],136:[2,106]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[1,198],86:199,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],49:[1,201],53:203,54:[1,202]},{6:[2,56],25:[2,56],26:[2,56],49:[2,56],54:[2,56]},{6:[2,60],25:[2,60],26:[2,60],40:[1,205],49:[2,60],54:[2,60],57:[1,204]},{6:[2,63],25:[2,63],26:[2,63],40:[2,63],49:[2,63],54:[2,63],57:[2,63]},{6:[2,64],25:[2,64],26:[2,64],40:[2,64],49:[2,64],54:[2,64],57:[2,64]},{6:[2,65],25:[2,65],26:[2,65],40:[2,65],49:[2,65],54:[2,65],57:[2,65]},{6:[2,66],25:[2,66],26:[2,66],40:[2,66],49:[2,66],54:[2,66],57:[2,66]},{27:148,28:[1,73]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,50],6:[2,50],25:[2,50],26:[2,50],49:[2,50],54:[2,50],57:[2,50],72:[2,50],77:[2,50],85:[2,50],90:[2,50],92:[2,50],101:[2,50],103:[2,50],104:[2,50],105:[2,50],109:[2,50],117:[2,50],125:[2,50],127:[2,50],128:[2,50],131:[2,50],132:[2,50],133:[2,50],134:[2,50],135:[2,50],136:[2,50]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],49:[2,184],54:[2,184],57:[2,184],72:[2,184],77:[2,184],85:[2,184],90:[2,184],92:[2,184],101:[2,184],102:87,103:[2,184],104:[2,184],105:[2,184],108:88,109:[2,184],110:69,117:[2,184],125:[2,184],127:[2,184],128:[2,184],131:[1,78],132:[2,184],133:[2,184],134:[2,184],135:[2,184],136:[2,184]},{102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],49:[2,185],54:[2,185],57:[2,185],72:[2,185],77:[2,185],85:[2,185],90:[2,185],92:[2,185],101:[2,185],102:87,103:[2,185],104:[2,185],105:[2,185],108:88,109:[2,185],110:69,117:[2,185],125:[2,185],127:[2,185],128:[2,185],131:[1,78],132:[2,185],133:[2,185],134:[2,185],135:[2,185],136:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],49:[2,186],54:[2,186],57:[2,186],72:[2,186],77:[2,186],85:[2,186],90:[2,186],92:[2,186],101:[2,186],102:87,103:[2,186],104:[2,186],105:[2,186],108:88,109:[2,186],110:69,117:[2,186],125:[2,186],127:[2,186],128:[2,186],131:[1,78],132:[2,186],133:[2,186],134:[2,186],135:[2,186],136:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],49:[2,187],54:[2,187],57:[2,187],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,187],73:[2,72],77:[2,187],83:[2,72],84:[2,72],85:[2,187],90:[2,187],92:[2,187],101:[2,187],103:[2,187],104:[2,187],105:[2,187],109:[2,187],117:[2,187],125:[2,187],127:[2,187],128:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187],135:[2,187],136:[2,187]},{62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:92,83:[1,94],84:[2,107]},{62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:101,83:[1,94],84:[2,107]},{66:[2,75],67:[2,75],68:[2,75],70:[2,75],73:[2,75],83:[2,75],84:[2,75]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],49:[2,188],54:[2,188],57:[2,188],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,188],73:[2,72],77:[2,188],83:[2,72],84:[2,72],85:[2,188],90:[2,188],92:[2,188],101:[2,188],103:[2,188],104:[2,188],105:[2,188],109:[2,188],117:[2,188],125:[2,188],127:[2,188],128:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188],135:[2,188],136:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],49:[2,189],54:[2,189],57:[2,189],72:[2,189],77:[2,189],85:[2,189],90:[2,189],92:[2,189],101:[2,189],103:[2,189],104:[2,189],105:[2,189],109:[2,189],117:[2,189],125:[2,189],127:[2,189],128:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189],135:[2,189],136:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],49:[2,190],54:[2,190],57:[2,190],72:[2,190],77:[2,190],85:[2,190],90:[2,190],92:[2,190],101:[2,190],103:[2,190],104:[2,190],105:[2,190],109:[2,190],117:[2,190],125:[2,190],127:[2,190],128:[2,190],131:[2,190],132:[2,190],133:[2,190],134:[2,190],135:[2,190],136:[2,190]},{8:206,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,207],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:208,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:209,25:[1,5],124:[1,210]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],49:[2,132],54:[2,132],57:[2,132],72:[2,132],77:[2,132],85:[2,132],90:[2,132],92:[2,132],96:211,97:[1,212],98:[1,213],101:[2,132],103:[2,132],104:[2,132],105:[2,132],109:[2,132],117:[2,132],125:[2,132],127:[2,132],128:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132],135:[2,132],136:[2,132]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],49:[2,144],54:[2,144],57:[2,144],72:[2,144],77:[2,144],85:[2,144],90:[2,144],92:[2,144],101:[2,144],103:[2,144],104:[2,144],105:[2,144],109:[2,144],117:[2,144],125:[2,144],127:[2,144],128:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144],135:[2,144],136:[2,144]},{1:[2,152],6:[2,152],25:[2,152],26:[2,152],49:[2,152],54:[2,152],57:[2,152],72:[2,152],77:[2,152],85:[2,152],90:[2,152],92:[2,152],101:[2,152],103:[2,152],104:[2,152],105:[2,152],109:[2,152],117:[2,152],125:[2,152],127:[2,152],128:[2,152],131:[2,152],132:[2,152],133:[2,152],134:[2,152],135:[2,152],136:[2,152]},{25:[1,214],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{119:215,121:216,122:[1,217]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],49:[2,96],54:[2,96],57:[2,96],72:[2,96],77:[2,96],85:[2,96],90:[2,96],92:[2,96],101:[2,96],103:[2,96],104:[2,96],105:[2,96],109:[2,96],117:[2,96],125:[2,96],127:[2,96],128:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96],135:[2,96],136:[2,96]},{8:218,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,99],5:219,6:[2,99],25:[1,5],26:[2,99],49:[2,99],54:[2,99],57:[2,99],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,99],73:[2,72],77:[2,99],79:[1,220],83:[2,72],84:[2,72],85:[2,99],90:[2,99],92:[2,99],101:[2,99],103:[2,99],104:[2,99],105:[2,99],109:[2,99],117:[2,99],125:[2,99],127:[2,99],128:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99],135:[2,99],136:[2,99]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],49:[2,137],54:[2,137],57:[2,137],72:[2,137],77:[2,137],85:[2,137],90:[2,137],92:[2,137],101:[2,137],102:87,103:[2,137],104:[2,137],105:[2,137],108:88,109:[2,137],110:69,117:[2,137],125:[2,137],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,46],6:[2,46],26:[2,46],101:[2,46],102:87,103:[2,46],105:[2,46],108:88,109:[2,46],110:69,125:[2,46],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,74],101:[1,221]},{4:222,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,128],25:[2,128],54:[2,128],57:[1,224],90:[2,128],91:223,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],40:[2,114],49:[2,114],54:[2,114],57:[2,114],66:[2,114],67:[2,114],68:[2,114],70:[2,114],72:[2,114],73:[2,114],77:[2,114],83:[2,114],84:[2,114],85:[2,114],90:[2,114],92:[2,114],101:[2,114],103:[2,114],104:[2,114],105:[2,114],109:[2,114],115:[2,114],116:[2,114],117:[2,114],125:[2,114],127:[2,114],128:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114],135:[2,114],136:[2,114]},{6:[2,53],25:[2,53],53:225,54:[1,226],90:[2,53]},{6:[2,123],25:[2,123],26:[2,123],54:[2,123],85:[2,123],90:[2,123]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:227,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,129],25:[2,129],26:[2,129],54:[2,129],85:[2,129],90:[2,129]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],40:[2,113],43:[2,113],49:[2,113],54:[2,113],57:[2,113],66:[2,113],67:[2,113],68:[2,113],70:[2,113],72:[2,113],73:[2,113],77:[2,113],79:[2,113],83:[2,113],84:[2,113],85:[2,113],90:[2,113],92:[2,113],101:[2,113],103:[2,113],104:[2,113],105:[2,113],109:[2,113],115:[2,113],116:[2,113],117:[2,113],125:[2,113],127:[2,113],128:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113],135:[2,113],136:[2,113],137:[2,113]},{5:228,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],49:[2,140],54:[2,140],57:[2,140],72:[2,140],77:[2,140],85:[2,140],90:[2,140],92:[2,140],101:[2,140],102:87,103:[1,65],104:[1,229],105:[1,66],108:88,109:[1,68],110:69,117:[2,140],125:[2,140],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],49:[2,142],54:[2,142],57:[2,142],72:[2,142],77:[2,142],85:[2,142],90:[2,142],92:[2,142],101:[2,142],102:87,103:[1,65],104:[1,230],105:[1,66],108:88,109:[1,68],110:69,117:[2,142],125:[2,142],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],49:[2,148],54:[2,148],57:[2,148],72:[2,148],77:[2,148],85:[2,148],90:[2,148],92:[2,148],101:[2,148],103:[2,148],104:[2,148],105:[2,148],109:[2,148],117:[2,148],125:[2,148],127:[2,148],128:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148],135:[2,148],136:[2,148]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],49:[2,149],54:[2,149],57:[2,149],72:[2,149],77:[2,149],85:[2,149],90:[2,149],92:[2,149],101:[2,149],102:87,103:[1,65],104:[2,149],105:[1,66],108:88,109:[1,68],110:69,117:[2,149],125:[2,149],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,153],6:[2,153],25:[2,153],26:[2,153],49:[2,153],54:[2,153],57:[2,153],72:[2,153],77:[2,153],85:[2,153],90:[2,153],92:[2,153],101:[2,153],103:[2,153],104:[2,153],105:[2,153],109:[2,153],117:[2,153],125:[2,153],127:[2,153],128:[2,153],131:[2,153],132:[2,153],133:[2,153],134:[2,153],135:[2,153],136:[2,153]},{115:[2,155],116:[2,155]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],112:231,114:157},{54:[1,232],115:[2,161],116:[2,161]},{54:[2,157],115:[2,157],116:[2,157]},{54:[2,158],115:[2,158],116:[2,158]},{54:[2,159],115:[2,159],116:[2,159]},{54:[2,160],115:[2,160],116:[2,160]},{1:[2,154],6:[2,154],25:[2,154],26:[2,154],49:[2,154],54:[2,154],57:[2,154],72:[2,154],77:[2,154],85:[2,154],90:[2,154],92:[2,154],101:[2,154],103:[2,154],104:[2,154],105:[2,154],109:[2,154],117:[2,154],125:[2,154],127:[2,154],128:[2,154],131:[2,154],132:[2,154],133:[2,154],134:[2,154],135:[2,154],136:[2,154]},{8:233,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:234,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],53:235,54:[1,236],77:[2,53]},{6:[2,91],25:[2,91],26:[2,91],54:[2,91],77:[2,91]},{6:[2,39],25:[2,39],26:[2,39],43:[1,237],54:[2,39],77:[2,39]},{6:[2,42],25:[2,42],26:[2,42],54:[2,42],77:[2,42]},{6:[2,43],25:[2,43],26:[2,43],43:[2,43],54:[2,43],77:[2,43]},{6:[2,44],25:[2,44],26:[2,44],43:[2,44],54:[2,44],77:[2,44]},{6:[2,45],25:[2,45],26:[2,45],43:[2,45],54:[2,45],77:[2,45]},{1:[2,5],6:[2,5],26:[2,5],101:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],49:[2,25],54:[2,25],57:[2,25],72:[2,25],77:[2,25],85:[2,25],90:[2,25],92:[2,25],97:[2,25],98:[2,25],101:[2,25],103:[2,25],104:[2,25],105:[2,25],109:[2,25],117:[2,25],120:[2,25],122:[2,25],125:[2,25],127:[2,25],128:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25],135:[2,25],136:[2,25]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],49:[2,192],54:[2,192],57:[2,192],72:[2,192],77:[2,192],85:[2,192],90:[2,192],92:[2,192],101:[2,192],102:87,103:[2,192],104:[2,192],105:[2,192],108:88,109:[2,192],110:69,117:[2,192],125:[2,192],127:[2,192],128:[2,192],131:[1,78],132:[1,81],133:[2,192],134:[2,192],135:[2,192],136:[2,192]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],49:[2,193],54:[2,193],57:[2,193],72:[2,193],77:[2,193],85:[2,193],90:[2,193],92:[2,193],101:[2,193],102:87,103:[2,193],104:[2,193],105:[2,193],108:88,109:[2,193],110:69,117:[2,193],125:[2,193],127:[2,193],128:[2,193],131:[1,78],132:[1,81],133:[2,193],134:[2,193],135:[2,193],136:[2,193]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],49:[2,194],54:[2,194],57:[2,194],72:[2,194],77:[2,194],85:[2,194],90:[2,194],92:[2,194],101:[2,194],102:87,103:[2,194],104:[2,194],105:[2,194],108:88,109:[2,194],110:69,117:[2,194],125:[2,194],127:[2,194],128:[2,194],131:[1,78],132:[2,194],133:[2,194],134:[2,194],135:[2,194],136:[2,194]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],49:[2,195],54:[2,195],57:[2,195],72:[2,195],77:[2,195],85:[2,195],90:[2,195],92:[2,195],101:[2,195],102:87,103:[2,195],104:[2,195],105:[2,195],108:88,109:[2,195],110:69,117:[2,195],125:[2,195],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[2,195],134:[2,195],135:[2,195],136:[2,195]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],49:[2,196],54:[2,196],57:[2,196],72:[2,196],77:[2,196],85:[2,196],90:[2,196],92:[2,196],101:[2,196],102:87,103:[2,196],104:[2,196],105:[2,196],108:88,109:[2,196],110:69,117:[2,196],125:[2,196],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,196],135:[2,196],136:[1,85]},{1:[2,197],6:[2,197],25:[2,197],26:[2,197],49:[2,197],54:[2,197],57:[2,197],72:[2,197],77:[2,197],85:[2,197],90:[2,197],92:[2,197],101:[2,197],102:87,103:[2,197],104:[2,197],105:[2,197],108:88,109:[2,197],110:69,117:[2,197],125:[2,197],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[2,197],136:[1,85]},{1:[2,198],6:[2,198],25:[2,198],26:[2,198],49:[2,198],54:[2,198],57:[2,198],72:[2,198],77:[2,198],85:[2,198],90:[2,198],92:[2,198],101:[2,198],102:87,103:[2,198],104:[2,198],105:[2,198],108:88,109:[2,198],110:69,117:[2,198],125:[2,198],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,198],135:[2,198],136:[2,198]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],49:[2,183],54:[2,183],57:[2,183],72:[2,183],77:[2,183],85:[2,183],90:[2,183],92:[2,183],101:[2,183],102:87,103:[1,65],104:[2,183],105:[1,66],108:88,109:[1,68],110:69,117:[2,183],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],49:[2,182],54:[2,182],57:[2,182],72:[2,182],77:[2,182],85:[2,182],90:[2,182],92:[2,182],101:[2,182],102:87,103:[1,65],104:[2,182],105:[1,66],108:88,109:[1,68],110:69,117:[2,182],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,103],6:[2,103],25:[2,103],26:[2,103],49:[2,103],54:[2,103],57:[2,103],66:[2,103],67:[2,103],68:[2,103],70:[2,103],72:[2,103],73:[2,103],77:[2,103],83:[2,103],84:[2,103],85:[2,103],90:[2,103],92:[2,103],101:[2,103],103:[2,103],104:[2,103],105:[2,103],109:[2,103],117:[2,103],125:[2,103],127:[2,103],128:[2,103],131:[2,103],132:[2,103],133:[2,103],134:[2,103],135:[2,103],136:[2,103]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],40:[2,80],49:[2,80],54:[2,80],57:[2,80],66:[2,80],67:[2,80],68:[2,80],70:[2,80],72:[2,80],73:[2,80],77:[2,80],79:[2,80],83:[2,80],84:[2,80],85:[2,80],90:[2,80],92:[2,80],101:[2,80],103:[2,80],104:[2,80],105:[2,80],109:[2,80],117:[2,80],125:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80],136:[2,80],137:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],40:[2,81],49:[2,81],54:[2,81],57:[2,81],66:[2,81],67:[2,81],68:[2,81],70:[2,81],72:[2,81],73:[2,81],77:[2,81],79:[2,81],83:[2,81],84:[2,81],85:[2,81],90:[2,81],92:[2,81],101:[2,81],103:[2,81],104:[2,81],105:[2,81],109:[2,81],117:[2,81],125:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81],136:[2,81],137:[2,81]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],40:[2,82],49:[2,82],54:[2,82],57:[2,82],66:[2,82],67:[2,82],68:[2,82],70:[2,82],72:[2,82],73:[2,82],77:[2,82],79:[2,82],83:[2,82],84:[2,82],85:[2,82],90:[2,82],92:[2,82],101:[2,82],103:[2,82],104:[2,82],105:[2,82],109:[2,82],117:[2,82],125:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82],136:[2,82],137:[2,82]},{72:[1,238]},{57:[1,192],72:[2,87],91:239,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{72:[2,88]},{8:240,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,122],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{12:[2,116],28:[2,116],30:[2,116],31:[2,116],33:[2,116],34:[2,116],35:[2,116],36:[2,116],37:[2,116],38:[2,116],45:[2,116],46:[2,116],47:[2,116],51:[2,116],52:[2,116],72:[2,116],75:[2,116],78:[2,116],82:[2,116],87:[2,116],88:[2,116],89:[2,116],95:[2,116],99:[2,116],100:[2,116],103:[2,116],105:[2,116],107:[2,116],109:[2,116],118:[2,116],124:[2,116],126:[2,116],127:[2,116],128:[2,116],129:[2,116],130:[2,116]},{12:[2,117],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],72:[2,117],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{1:[2,86],6:[2,86],25:[2,86],26:[2,86],40:[2,86],49:[2,86],54:[2,86],57:[2,86],66:[2,86],67:[2,86],68:[2,86],70:[2,86],72:[2,86],73:[2,86],77:[2,86],79:[2,86],83:[2,86],84:[2,86],85:[2,86],90:[2,86],92:[2,86],101:[2,86],103:[2,86],104:[2,86],105:[2,86],109:[2,86],117:[2,86],125:[2,86],127:[2,86],128:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],49:[2,104],54:[2,104],57:[2,104],66:[2,104],67:[2,104],68:[2,104],70:[2,104],72:[2,104],73:[2,104],77:[2,104],83:[2,104],84:[2,104],85:[2,104],90:[2,104],92:[2,104],101:[2,104],103:[2,104],104:[2,104],105:[2,104],109:[2,104],117:[2,104],125:[2,104],127:[2,104],128:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104],135:[2,104],136:[2,104]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],49:[2,36],54:[2,36],57:[2,36],72:[2,36],77:[2,36],85:[2,36],90:[2,36],92:[2,36],101:[2,36],102:87,103:[2,36],104:[2,36],105:[2,36],108:88,109:[2,36],110:69,117:[2,36],125:[2,36],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:241,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:242,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],49:[2,109],54:[2,109],57:[2,109],66:[2,109],67:[2,109],68:[2,109],70:[2,109],72:[2,109],73:[2,109],77:[2,109],83:[2,109],84:[2,109],85:[2,109],90:[2,109],92:[2,109],101:[2,109],103:[2,109],104:[2,109],105:[2,109],109:[2,109],117:[2,109],125:[2,109],127:[2,109],128:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109],136:[2,109]},{6:[2,53],25:[2,53],53:243,54:[1,226],85:[2,53]},{6:[2,128],25:[2,128],26:[2,128],54:[2,128],57:[1,244],85:[2,128],90:[2,128],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{50:245,51:[1,60],52:[1,61]},{6:[2,54],25:[2,54],26:[2,54],27:109,28:[1,73],44:110,55:246,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[1,247],25:[1,248]},{6:[2,61],25:[2,61],26:[2,61],49:[2,61],54:[2,61]},{8:249,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,199],6:[2,199],25:[2,199],26:[2,199],49:[2,199],54:[2,199],57:[2,199],72:[2,199],77:[2,199],85:[2,199],90:[2,199],92:[2,199],101:[2,199],102:87,103:[2,199],104:[2,199],105:[2,199],108:88,109:[2,199],110:69,117:[2,199],125:[2,199],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:250,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,201],6:[2,201],25:[2,201],26:[2,201],49:[2,201],54:[2,201],57:[2,201],72:[2,201],77:[2,201],85:[2,201],90:[2,201],92:[2,201],101:[2,201],102:87,103:[2,201],104:[2,201],105:[2,201],108:88,109:[2,201],110:69,117:[2,201],125:[2,201],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],49:[2,181],54:[2,181],57:[2,181],72:[2,181],77:[2,181],85:[2,181],90:[2,181],92:[2,181],101:[2,181],103:[2,181],104:[2,181],105:[2,181],109:[2,181],117:[2,181],125:[2,181],127:[2,181],128:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181],135:[2,181],136:[2,181]},{8:251,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],49:[2,133],54:[2,133],57:[2,133],72:[2,133],77:[2,133],85:[2,133],90:[2,133],92:[2,133],97:[1,252],101:[2,133],103:[2,133],104:[2,133],105:[2,133],109:[2,133],117:[2,133],125:[2,133],127:[2,133],128:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133],135:[2,133],136:[2,133]},{5:253,25:[1,5]},{27:254,28:[1,73]},{119:255,121:216,122:[1,217]},{26:[1,256],120:[1,257],121:258,122:[1,217]},{26:[2,174],120:[2,174],122:[2,174]},{8:260,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],94:259,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,97],5:261,6:[2,97],25:[1,5],26:[2,97],49:[2,97],54:[2,97],57:[2,97],72:[2,97],77:[2,97],85:[2,97],90:[2,97],92:[2,97],101:[2,97],102:87,103:[1,65],104:[2,97],105:[1,66],108:88,109:[1,68],110:69,117:[2,97],125:[2,97],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],49:[2,100],54:[2,100],57:[2,100],72:[2,100],77:[2,100],85:[2,100],90:[2,100],92:[2,100],101:[2,100],103:[2,100],104:[2,100],105:[2,100],109:[2,100],117:[2,100],125:[2,100],127:[2,100],128:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100],135:[2,100],136:[2,100]},{8:262,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],49:[2,138],54:[2,138],57:[2,138],66:[2,138],67:[2,138],68:[2,138],70:[2,138],72:[2,138],73:[2,138],77:[2,138],83:[2,138],84:[2,138],85:[2,138],90:[2,138],92:[2,138],101:[2,138],103:[2,138],104:[2,138],105:[2,138],109:[2,138],117:[2,138],125:[2,138],127:[2,138],128:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138],135:[2,138],136:[2,138]},{6:[1,74],26:[1,263]},{8:264,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,67],12:[2,117],25:[2,67],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],54:[2,67],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],90:[2,67],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{6:[1,266],25:[1,267],90:[1,265]},{6:[2,54],8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,54],26:[2,54],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[2,54],87:[1,58],88:[1,59],89:[1,57],90:[2,54],93:268,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],26:[2,53],53:269,54:[1,226]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],49:[2,178],54:[2,178],57:[2,178],72:[2,178],77:[2,178],85:[2,178],90:[2,178],92:[2,178],101:[2,178],103:[2,178],104:[2,178],105:[2,178],109:[2,178],117:[2,178],120:[2,178],125:[2,178],127:[2,178],128:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178],135:[2,178],136:[2,178]},{8:270,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:271,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{115:[2,156],116:[2,156]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],114:272},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],49:[2,163],54:[2,163],57:[2,163],72:[2,163],77:[2,163],85:[2,163],90:[2,163],92:[2,163],101:[2,163],102:87,103:[2,163],104:[1,273],105:[2,163],108:88,109:[2,163],110:69,117:[1,274],125:[2,163],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],49:[2,164],54:[2,164],57:[2,164],72:[2,164],77:[2,164],85:[2,164],90:[2,164],92:[2,164],101:[2,164],102:87,103:[2,164],104:[1,275],105:[2,164],108:88,109:[2,164],110:69,117:[2,164],125:[2,164],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,277],25:[1,278],77:[1,276]},{6:[2,54],11:168,25:[2,54],26:[2,54],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:279,42:167,44:171,46:[1,46],77:[2,54],88:[1,113]},{8:280,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,281],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],40:[2,85],49:[2,85],54:[2,85],57:[2,85],66:[2,85],67:[2,85],68:[2,85],70:[2,85],72:[2,85],73:[2,85],77:[2,85],79:[2,85],83:[2,85],84:[2,85],85:[2,85],90:[2,85],92:[2,85],101:[2,85],103:[2,85],104:[2,85],105:[2,85],109:[2,85],117:[2,85],125:[2,85],127:[2,85],128:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85]},{8:282,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,120],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,121],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,37],6:[2,37],25:[2,37],26:[2,37],49:[2,37],54:[2,37],57:[2,37],72:[2,37],77:[2,37],85:[2,37],90:[2,37],92:[2,37],101:[2,37],102:87,103:[2,37],104:[2,37],105:[2,37],108:88,109:[2,37],110:69,117:[2,37],125:[2,37],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,283],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],85:[1,284]},{6:[2,67],25:[2,67],26:[2,67],54:[2,67],85:[2,67],90:[2,67]},{5:285,25:[1,5]},{6:[2,57],25:[2,57],26:[2,57],49:[2,57],54:[2,57]},{27:109,28:[1,73],44:110,55:286,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,55],25:[2,55],26:[2,55],27:109,28:[1,73],44:110,48:287,54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,62],25:[2,62],26:[2,62],49:[2,62],54:[2,62],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,288],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:289,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:290,25:[1,5]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],49:[2,134],54:[2,134],57:[2,134],72:[2,134],77:[2,134],85:[2,134],90:[2,134],92:[2,134],101:[2,134],103:[2,134],104:[2,134],105:[2,134],109:[2,134],117:[2,134],125:[2,134],127:[2,134],128:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134],135:[2,134],136:[2,134]},{5:291,25:[1,5]},{26:[1,292],120:[1,293],121:258,122:[1,217]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],49:[2,172],54:[2,172],57:[2,172],72:[2,172],77:[2,172],85:[2,172],90:[2,172],92:[2,172],101:[2,172],103:[2,172],104:[2,172],105:[2,172],109:[2,172],117:[2,172],125:[2,172],127:[2,172],128:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172],135:[2,172],136:[2,172]},{5:294,25:[1,5]},{26:[2,175],120:[2,175],122:[2,175]},{5:295,25:[1,5],54:[1,296]},{25:[2,130],54:[2,130],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],49:[2,98],54:[2,98],57:[2,98],72:[2,98],77:[2,98],85:[2,98],90:[2,98],92:[2,98],101:[2,98],103:[2,98],104:[2,98],105:[2,98],109:[2,98],117:[2,98],125:[2,98],127:[2,98],128:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98],135:[2,98],136:[2,98]},{1:[2,101],5:297,6:[2,101],25:[1,5],26:[2,101],49:[2,101],54:[2,101],57:[2,101],72:[2,101],77:[2,101],85:[2,101],90:[2,101],92:[2,101],101:[2,101],102:87,103:[1,65],104:[2,101],105:[1,66],108:88,109:[1,68],110:69,117:[2,101],125:[2,101],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{101:[1,298]},{90:[1,299],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,115],6:[2,115],25:[2,115],26:[2,115],40:[2,115],49:[2,115],54:[2,115],57:[2,115],66:[2,115],67:[2,115],68:[2,115],70:[2,115],72:[2,115],73:[2,115],77:[2,115],83:[2,115],84:[2,115],85:[2,115],90:[2,115],92:[2,115],101:[2,115],103:[2,115],104:[2,115],105:[2,115],109:[2,115],115:[2,115],116:[2,115],117:[2,115],125:[2,115],127:[2,115],128:[2,115],131:[2,115],132:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],93:300,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:301,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,124],25:[2,124],26:[2,124],54:[2,124],85:[2,124],90:[2,124]},{6:[1,266],25:[1,267],26:[1,302]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],49:[2,141],54:[2,141],57:[2,141],72:[2,141],77:[2,141],85:[2,141],90:[2,141],92:[2,141],101:[2,141],102:87,103:[1,65],104:[2,141],105:[1,66],108:88,109:[1,68],110:69,117:[2,141],125:[2,141],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],49:[2,143],54:[2,143],57:[2,143],72:[2,143],77:[2,143],85:[2,143],90:[2,143],92:[2,143],101:[2,143],102:87,103:[1,65],104:[2,143],105:[1,66],108:88,109:[1,68],110:69,117:[2,143],125:[2,143],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{115:[2,162],116:[2,162]},{8:303,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:304,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:305,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,89],6:[2,89],25:[2,89],26:[2,89],40:[2,89],49:[2,89],54:[2,89],57:[2,89],66:[2,89],67:[2,89],68:[2,89],70:[2,89],72:[2,89],73:[2,89],77:[2,89],83:[2,89],84:[2,89],85:[2,89],90:[2,89],92:[2,89],101:[2,89],103:[2,89],104:[2,89],105:[2,89],109:[2,89],115:[2,89],116:[2,89],117:[2,89],125:[2,89],127:[2,89],128:[2,89],131:[2,89],132:[2,89],133:[2,89],134:[2,89],135:[2,89],136:[2,89]},{11:168,27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:306,42:167,44:171,46:[1,46],88:[1,113]},{6:[2,90],11:168,25:[2,90],26:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:307,88:[1,113]},{6:[2,92],25:[2,92],26:[2,92],54:[2,92],77:[2,92]},{6:[2,40],25:[2,40],26:[2,40],54:[2,40],77:[2,40],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:308,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,119],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,38],6:[2,38],25:[2,38],26:[2,38],49:[2,38],54:[2,38],57:[2,38],72:[2,38],77:[2,38],85:[2,38],90:[2,38],92:[2,38],101:[2,38],103:[2,38],104:[2,38],105:[2,38],109:[2,38],117:[2,38],125:[2,38],127:[2,38],128:[2,38],131:[2,38],132:[2,38],133:[2,38],134:[2,38],135:[2,38],136:[2,38]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],49:[2,110],54:[2,110],57:[2,110],66:[2,110],67:[2,110],68:[2,110],70:[2,110],72:[2,110],73:[2,110],77:[2,110],83:[2,110],84:[2,110],85:[2,110],90:[2,110],92:[2,110],101:[2,110],103:[2,110],104:[2,110],105:[2,110],109:[2,110],117:[2,110],125:[2,110],127:[2,110],128:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110],135:[2,110],136:[2,110]},{1:[2,49],6:[2,49],25:[2,49],26:[2,49],49:[2,49],54:[2,49],57:[2,49],72:[2,49],77:[2,49],85:[2,49],90:[2,49],92:[2,49],101:[2,49],103:[2,49],104:[2,49],105:[2,49],109:[2,49],117:[2,49],125:[2,49],127:[2,49],128:[2,49],131:[2,49],132:[2,49],133:[2,49],134:[2,49],135:[2,49],136:[2,49]},{6:[2,58],25:[2,58],26:[2,58],49:[2,58],54:[2,58]},{6:[2,53],25:[2,53],26:[2,53],53:309,54:[1,202]},{1:[2,200],6:[2,200],25:[2,200],26:[2,200],49:[2,200],54:[2,200],57:[2,200],72:[2,200],77:[2,200],85:[2,200],90:[2,200],92:[2,200],101:[2,200],103:[2,200],104:[2,200],105:[2,200],109:[2,200],117:[2,200],125:[2,200],127:[2,200],128:[2,200],131:[2,200],132:[2,200],133:[2,200],134:[2,200],135:[2,200],136:[2,200]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],49:[2,179],54:[2,179],57:[2,179],72:[2,179],77:[2,179],85:[2,179],90:[2,179],92:[2,179],101:[2,179],103:[2,179],104:[2,179],105:[2,179],109:[2,179],117:[2,179],120:[2,179],125:[2,179],127:[2,179],128:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179],135:[2,179],136:[2,179]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],49:[2,135],54:[2,135],57:[2,135],72:[2,135],77:[2,135],85:[2,135],90:[2,135],92:[2,135],101:[2,135],103:[2,135],104:[2,135],105:[2,135],109:[2,135],117:[2,135],125:[2,135],127:[2,135],128:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135],135:[2,135],136:[2,135]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],49:[2,136],54:[2,136],57:[2,136],72:[2,136],77:[2,136],85:[2,136],90:[2,136],92:[2,136],97:[2,136],101:[2,136],103:[2,136],104:[2,136],105:[2,136],109:[2,136],117:[2,136],125:[2,136],127:[2,136],128:[2,136],131:[2,136],132:[2,136],133:[2,136],134:[2,136],135:[2,136],136:[2,136]},{1:[2,170],6:[2,170],25:[2,170],26:[2,170],49:[2,170],54:[2,170],57:[2,170],72:[2,170],77:[2,170],85:[2,170],90:[2,170],92:[2,170],101:[2,170],103:[2,170],104:[2,170],105:[2,170],109:[2,170],117:[2,170],125:[2,170],127:[2,170],128:[2,170],131:[2,170],132:[2,170],133:[2,170],134:[2,170],135:[2,170],136:[2,170]},{5:310,25:[1,5]},{26:[1,311]},{6:[1,312],26:[2,176],120:[2,176],122:[2,176]},{8:313,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],49:[2,102],54:[2,102],57:[2,102],72:[2,102],77:[2,102],85:[2,102],90:[2,102],92:[2,102],101:[2,102],103:[2,102],104:[2,102],105:[2,102],109:[2,102],117:[2,102],125:[2,102],127:[2,102],128:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102],135:[2,102],136:[2,102]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],49:[2,139],54:[2,139],57:[2,139],66:[2,139],67:[2,139],68:[2,139],70:[2,139],72:[2,139],73:[2,139],77:[2,139],83:[2,139],84:[2,139],85:[2,139],90:[2,139],92:[2,139],101:[2,139],103:[2,139],104:[2,139],105:[2,139],109:[2,139],117:[2,139],125:[2,139],127:[2,139],128:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139],135:[2,139],136:[2,139]},{1:[2,118],6:[2,118],25:[2,118],26:[2,118],49:[2,118],54:[2,118],57:[2,118],66:[2,118],67:[2,118],68:[2,118],70:[2,118],72:[2,118],73:[2,118],77:[2,118],83:[2,118],84:[2,118],85:[2,118],90:[2,118],92:[2,118],101:[2,118],103:[2,118],104:[2,118],105:[2,118],109:[2,118],117:[2,118],125:[2,118],127:[2,118],128:[2,118],131:[2,118],132:[2,118],133:[2,118],134:[2,118],135:[2,118],136:[2,118]},{6:[2,125],25:[2,125],26:[2,125],54:[2,125],85:[2,125],90:[2,125]},{6:[2,53],25:[2,53],26:[2,53],53:314,54:[1,226]},{6:[2,126],25:[2,126],26:[2,126],54:[2,126],85:[2,126],90:[2,126]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],49:[2,165],54:[2,165],57:[2,165],72:[2,165],77:[2,165],85:[2,165],90:[2,165],92:[2,165],101:[2,165],102:87,103:[2,165],104:[2,165],105:[2,165],108:88,109:[2,165],110:69,117:[1,315],125:[2,165],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],49:[2,167],54:[2,167],57:[2,167],72:[2,167],77:[2,167],85:[2,167],90:[2,167],92:[2,167],101:[2,167],102:87,103:[2,167],104:[1,316],105:[2,167],108:88,109:[2,167],110:69,117:[2,167],125:[2,167],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],49:[2,166],54:[2,166],57:[2,166],72:[2,166],77:[2,166],85:[2,166],90:[2,166],92:[2,166],101:[2,166],102:87,103:[2,166],104:[2,166],105:[2,166],108:88,109:[2,166],110:69,117:[2,166],125:[2,166],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,93],25:[2,93],26:[2,93],54:[2,93],77:[2,93]},{6:[2,53],25:[2,53],26:[2,53],53:317,54:[1,236]},{26:[1,318],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,247],25:[1,248],26:[1,319]},{26:[1,320]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],49:[2,173],54:[2,173],57:[2,173],72:[2,173],77:[2,173],85:[2,173],90:[2,173],92:[2,173],101:[2,173],103:[2,173],104:[2,173],105:[2,173],109:[2,173],117:[2,173],125:[2,173],127:[2,173],128:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173],135:[2,173],136:[2,173]},{26:[2,177],120:[2,177],122:[2,177]},{25:[2,131],54:[2,131],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],26:[1,321]},{8:322,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:323,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[1,277],25:[1,278],26:[1,324]},{6:[2,41],25:[2,41],26:[2,41],54:[2,41],77:[2,41]},{6:[2,59],25:[2,59],26:[2,59],49:[2,59],54:[2,59]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],49:[2,171],54:[2,171],57:[2,171],72:[2,171],77:[2,171],85:[2,171],90:[2,171],92:[2,171],101:[2,171],103:[2,171],104:[2,171],105:[2,171],109:[2,171],117:[2,171],125:[2,171],127:[2,171],128:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171],135:[2,171],136:[2,171]},{6:[2,127],25:[2,127],26:[2,127],54:[2,127],85:[2,127],90:[2,127]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],49:[2,168],54:[2,168],57:[2,168],72:[2,168],77:[2,168],85:[2,168],90:[2,168],92:[2,168],101:[2,168],102:87,103:[2,168],104:[2,168],105:[2,168],108:88,109:[2,168],110:69,117:[2,168],125:[2,168],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,169],6:[2,169],25:[2,169],26:[2,169],49:[2,169],54:[2,169],57:[2,169],72:[2,169],77:[2,169],85:[2,169],90:[2,169],92:[2,169],101:[2,169],102:87,103:[2,169],104:[2,169],105:[2,169],108:88,109:[2,169],110:69,117:[2,169],125:[2,169],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,94],25:[2,94],26:[2,94],54:[2,94],77:[2,94]}],defaultActions:{60:[2,51],61:[2,52],75:[2,3],94:[2,108],189:[2,88]},parseError:function(t,n){throw new Error(t)},parse:function(t){function d(e){r.length=r.length-2*e,i.length=i.length-e,s.length=s.length-e}function v(){var e;return e=n.lexer.lex()||1,typeof e!="number"&&(e=n.symbols_[e]||e),e}var n=this,r=[0],i=[null],s=[],o=this.table,u="",a=0,f=0,l=0,c=2,h=1;this.lexer.setInput(t),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,typeof this.lexer.yylloc=="undefined"&&(this.lexer.yylloc={});var p=this.lexer.yylloc;s.push(p),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);var m,g,y,b,w,E,S={},x,T,N,C;for(;;){y=r[r.length-1],this.defaultActions[y]?b=this.defaultActions[y]:(m==null&&(m=v()),b=o[y]&&o[y][m]);if(typeof b=="undefined"||!b.length||!b[0]){if(!l){C=[];for(x in o[y])this.terminals_[x]&&x>2&&C.push("'"+this.terminals_[x]+"'");var k="";this.lexer.showPosition?k="Parse error on line "+(a+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+C.join(", ")+", got '"+this.terminals_[m]+"'":k="Parse error on line "+(a+1)+": Unexpected "+(m==1?"end of input":"'"+(this.terminals_[m]||m)+"'"),this.parseError(k,{text:this.lexer.match,token:this.terminals_[m]||m,line:this.lexer.yylineno,loc:p,expected:C})}if(l==3){if(m==h)throw new Error(k||"Parsing halted.");f=this.lexer.yyleng,u=this.lexer.yytext,a=this.lexer.yylineno,p=this.lexer.yylloc,m=v()}for(;;){if(c.toString()in o[y])break;if(y==0)throw new Error(k||"Parsing halted.");d(1),y=r[r.length-1]}g=m,m=c,y=r[r.length-1],b=o[y]&&o[y][c],l=3}if(b[0]instanceof Array&&b.length>1)throw new Error("Parse Error: multiple actions possible at state: "+y+", token: "+m);switch(b[0]){case 1:r.push(m),i.push(this.lexer.yytext),s.push(this.lexer.yylloc),r.push(b[1]),m=null,g?(m=g,g=null):(f=this.lexer.yyleng,u=this.lexer.yytext,a=this.lexer.yylineno,p=this.lexer.yylloc,l>0&&l--);break;case 2:T=this.productions_[b[1]][1],S.$=i[i.length-T],S._$={first_line:s[s.length-(T||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(T||1)].first_column,last_column:s[s.length-1].last_column},E=this.performAction.call(S,u,f,a,this.yy,b[1],i,s);if(typeof E!="undefined")return E;T&&(r=r.slice(0,-1*T*2),i=i.slice(0,-1*T),s=s.slice(0,-1*T)),r.push(this.productions_[b[1]][0]),i.push(S.$),s.push(S._$),N=o[r[r.length-2]][r[r.length-1]],r.push(N);break;case 3:return!0}}return!0}};undefined,n.exports=r}),define("ace/mode/coffee/nodes",["require","exports","module","ace/mode/coffee/scope","ace/mode/coffee/lexer","ace/mode/coffee/helpers"],function(e,t,n){var r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D,P,H,B,j,F,I,q,R,U,z,W,X,V,$,J,K,Q,G,Y,Z,et,tt,nt,rt,it,st,ot,ut,at,ft,lt,ct,ht,pt={}.hasOwnProperty,dt=function(e,t){function r(){this.constructor=e}for(var n in t)pt.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e},vt=[].indexOf||function(e){for(var t=0,n=this.length;t1&&e.level>=T?"("+n+")":n)},t.prototype.compileRoot=function(e){var t,n,r,i,s,o;return e.indent=e.bare?"":X,e.scope=new R(null,this,null),e.level=k,this.spaced=!0,i="",e.bare||(s=function(){var e,t,i,s;i=this.expressions,s=[];for(r=e=0,t=i.length;e=S?"(void 0)":"void 0"},t}(o),t.Null=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return dt(t,e),t.prototype.isAssignable=M,t.prototype.isComplex=M,t.prototype.compileNode=function(){return"null"},t}(o),t.Bool=function(e){function t(e){this.val=e}return dt(t,e),t.prototype.isAssignable=M,t.prototype.isComplex=M,t.prototype.compileNode=function(){return this.val},t}(o),t.Return=F=function(e){function t(e){e&&!e.unwrap().isUndefined&&(this.expression=e)}return dt(t,e),t.prototype.children=["expression"],t.prototype.isStatement=Y,t.prototype.makeReturn=V,t.prototype.jumps=V,t.prototype.compile=function(e,n){var r,i;return r=(i=this.expression)!=null?i.makeReturn():void 0,!r||r instanceof t?t.__super__.compile.call(this,e,n):r.compile(e,n)},t.prototype.compileNode=function(e){return this.tab+("return"+[this.expression?" "+this.expression.compile(e,C):void 0]+";")},t}(o),t.Value=Q=function(e){function t(e,n,r){return!n&&e instanceof t?e:(this.base=e,this.properties=n||[],r&&(this[r]=!0),this)}return dt(t,e),t.prototype.children=["base","properties"],t.prototype.add=function(e){return this.properties=this.properties.concat(e),this},t.prototype.hasProperties=function(){return!!this.properties.length},t.prototype.isArray=function(){return!this.properties.length&&this.base instanceof i},t.prototype.isComplex=function(){return this.hasProperties()||this.base.isComplex()},t.prototype.isAssignable=function(){return this.hasProperties()||this.base.isAssignable()},t.prototype.isSimpleNumber=function(){return this.base instanceof L&&I.test(this.base.value)},t.prototype.isString=function(){return this.base instanceof L&&y.test(this.base.value)},t.prototype.isAtomic=function(){var e,t,n,r;r=this.properties.concat(this.base);for(t=0,n=r.length;t"+this.equals],a=p[0],i=p[1],n=this.stepNum?+this.stepNum>0?""+a+" "+this.toVar:""+i+" "+this.toVar:u?(d=[+this.fromNum,+this.toNum],r=d[0],c=d[1],d,r<=c?""+a+" "+c:""+i+" "+c):(t=""+this.fromVar+" <= "+this.toVar,""+t+" ? "+a+" "+this.toVar+" : "+i+" "+this.toVar),l=this.stepVar?""+s+" += "+this.stepVar:u?f?r<=c?"++"+s:"--"+s:r<=c?""+s+"++":""+s+"--":f?""+t+" ? ++"+s+" : --"+s:""+t+" ? "+s+"++ : "+s+"--",f&&(h=""+o+" = "+h),f&&(l=""+o+" = "+l),""+h+"; "+n+"; "+l):this.compileArray(e)},t.prototype.compileArray=function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v;if(this.fromNum&&this.toNum&&Math.abs(this.fromNum-this.toNum)<=20)return f=function(){v=[];for(var e=p=+this.fromNum,t=+this.toNum;p<=t?e<=t:e>=t;p<=t?e++:e--)v.push(e);return v}.apply(this),this.exclusive&&f.pop(),"["+f.join(", ")+"]";o=this.tab+X,s=e.scope.freeVariable("i"),l=e.scope.freeVariable("results"),a="\n"+o+l+" = [];",this.fromNum&&this.toNum?(e.index=s,n=this.compileNode(e)):(c=""+s+" = "+this.fromC+(this.toC!==this.toVar?", "+this.toC:""),r=""+this.fromVar+" <= "+this.toVar,n="var "+c+"; "+r+" ? "+s+" <"+this.equals+" "+this.toVar+" : "+s+" >"+this.equals+" "+this.toVar+"; "+r+" ? "+s+"++ : "+s+"--"),u="{ "+l+".push("+s+"); }\n"+o+"return "+l+";\n"+e.indent,i=function(e){return e!=null?e.contains(function(e){return e instanceof L&&e.value==="arguments"&&!e.asKey}):void 0};if(i(this.from)||i(this.to))t=", arguments";return"(function() {"+a+"\n"+o+"for ("+n+")"+u+"}).apply(this"+(t!=null?t:"")+")"},t}(o),t.Slice=U=function(e){function t(e){this.range=e,t.__super__.constructor.call(this)}return dt(t,e),t.prototype.children=["range"],t.prototype.compileNode=function(e){var t,n,r,i,s,o;return o=this.range,i=o.to,n=o.from,r=n&&n.compile(e,C)||"0",t=i&&i.compile(e,C),i&&(!!this.range.exclusive||+t!==-1)&&(s=", "+(this.range.exclusive?t:I.test(t)?""+(+t+1):(t=i.compile(e,S),"+"+t+" + 1 || 9e9"))),".slice("+r+(s||"")+")"},t}(o),t.Obj=_=function(e){function t(e,t){this.generated=t!=null?t:!1,this.objects=this.properties=e||[]}return dt(t,e),t.prototype.children=["properties"],t.prototype.compileNode=function(e){var t,n,r,i,o,u,a,f,l,c,p;l=this.properties;if(!l.length)return this.front?"({})":"{}";if(this.generated)for(c=0,p=l.length;c=0?"[\n"+e.indent+t+"\n"+this.tab+"]":"["+t+"]")):"[]"},t.prototype.assigns=function(e){var t,n,r,i;i=this.objects;for(n=0,r=i.length;n=0)throw SyntaxError("variable name may not be "+e);return e&&(e=m.test(e)&&e)},t.prototype.setContext=function(e){return this.body.traverseChildren(!1,function(t){if(t.classBody)return!1;if(t instanceof L&&t.value==="this")return t.value=e;if(t instanceof c){t.klass=e;if(t.bound)return t.context=e}})},t.prototype.addBoundFunctions=function(e){var t,n,i,s,o,u;if(this.boundFuncs.length){o=this.boundFuncs,u=[];for(i=0,s=o.length;i=0);if(i&&this.context!=="object")throw SyntaxError('variable name may not be "'+s+'"')}return dt(t,e),t.prototype.children=["variable","value"],t.prototype.isStatement=function(e){return(e!=null?e.level:void 0)===k&&this.context!=null&&vt.call(this.context,"?")>=0},t.prototype.assigns=function(e){return this[this.context==="object"?"value":"variable"].assigns(e)},t.prototype.unfoldSoak=function(e){return ft(e,this,"variable")},t.prototype.compileNode=function(e){var t,n,r,i,s,o,u,a,f;if(t=this.variable instanceof Q){if(this.variable.isArray()||this.variable.isObject())return this.compilePatternMatch(e);if(this.variable.isSplice())return this.compileSplice(e);if((o=this.context)==="||="||o==="&&="||o==="?=")return this.compileConditional(e)}r=this.variable.compile(e,T);if(!this.context){if(!(s=this.variable.unwrapAll()).isAssignable())throw SyntaxError('"'+this.variable.compile(e)+'" cannot be assigned.');if(typeof s.hasProperties=="function"?!s.hasProperties():!void 0)this.param?e.scope.add(r,"var"):e.scope.find(r)}return this.value instanceof c&&(n=A.exec(r))&&(n[1]&&(this.value.klass=n[1]),this.value.name=(u=(a=(f=n[2])!=null?f:n[3])!=null?a:n[4])!=null?u:n[5]),i=this.value.compile(e,T),this.context==="object"?""+r+": "+i:(i=r+(" "+(this.context||"=")+" ")+i,e.level<=T?i:"("+i+")")},t.prototype.compilePatternMatch=function(e){var n,i,s,o,u,a,f,l,c,h,p,d,v,g,y,b,w,S,x,C,A,O,M,_,D,P,j;y=e.level===k,w=this.value,h=this.variable.base.objects;if(!(p=h.length))return s=w.compile(e),e.level>=N?"("+s+")":s;a=this.variable.isObject();if(y&&p===1&&!((c=h[0])instanceof z)){c instanceof t?(A=c,O=A.variable,u=O.base,c=A.value):c.base instanceof H?(M=(new Q(c.unwrapAll())).cacheReference(e),c=M[0],u=M[1]):u=a?c["this"]?c.properties[0].name:c:new L(0),n=m.test(u.unwrap().value||0),w=new Q(w),w.properties.push(new(n?r:E)(u));if(_=c.unwrap().value,vt.call(B,_)>=0)throw new SyntaxError("assignment to a reserved word: "+c.compile(e)+" = "+w.compile(e));return(new t(c,w,null,{param:this.param})).compile(e,k)}S=w.compile(e,T),i=[],g=!1;if(!m.test(S)||this.variable.assigns(S))i.push(""+(d=e.scope.freeVariable("ref"))+" = "+S),S=d;for(o=x=0,C=h.length;x=0)throw new SyntaxError("assignment to a reserved word: "+c.compile(e)+" = "+b.compile(e));i.push((new t(c,b,null,{param:this.param,subpattern:!0})).compile(e,T))}return!y&&!this.subpattern&&i.push(S),s=i.join(", "),e.level=0&&(e.isExistentialEquals=!0),(new D(this.context.slice(0,-1),n,new t(r,this.value,"="))).compile(e)},t.prototype.compileSplice=function(e){var t,n,r,i,s,o,u,a,f,l,c,h;return l=this.variable.properties.pop().range,r=l.from,u=l.to,n=l.exclusive,o=this.variable.compile(e),c=(r!=null?r.cache(e,N):void 0)||["0","0"],i=c[0],s=c[1],u?(r!=null?r.isSimpleNumber():void 0)&&u.isSimpleNumber()?(u=+u.compile(e)- +s,n||(u+=1)):(u=u.compile(e,S)+" - "+s,n||(u+=" + 1")):u="9e9",h=this.value.cache(e,T),a=h[0],f=h[1],t="[].splice.apply("+o+", ["+i+", "+u+"].concat("+a+")), "+f,e.level>k?"("+t+")":t},t}(o),t.Code=c=function(e){function t(e,t,n){this.params=e||[],this.body=t||new u,this.bound=n==="boundfunc",this.bound&&(this.context="_this")}return dt(t,e),t.prototype.children=["params","body"],t.prototype.isStatement=function(){return!!this.ctor},t.prototype.jumps=M,t.prototype.compileNode=function(e){var t,n,r,o,u,a,f,l,c,h,p,d,v,m,g,y,w,E,x,T,N,C,k,A,O,M,_,P,H,B,j,F,I;e.scope=new R(e.scope,this.body,this),e.scope.shared=et(e,"sharedScope"),e.indent+=X,delete e.bare,delete e.isExistentialEquals,c=[],n=[],_=this.paramNames();for(g=0,x=_.length;g=S?"("+t+")":t},t.prototype.paramNames=function(){var e,t,n,r,i;e=[],i=this.params;for(n=0,r=i.length;n=0)throw SyntaxError('parameter name "'+e+'" is not allowed')}return dt(t,e),t.prototype.children=["name","value"],t.prototype.compile=function(e){return this.name.compile(e,T)},t.prototype.asReference=function(e){var t;return this.reference?this.reference:(t=this.name,t["this"]?(t=t.properties[0].name,t.value.reserved&&(t=new L(e.scope.freeVariable(t.value)))):t.isComplex()&&(t=new L(e.scope.freeVariable("arg"))),t=new Q(t),this.splat&&(t=new z(t)),this.reference=t)},t.prototype.isComplex=function(){return this.name.isComplex()},t.prototype.names=function(e){var t,n,r,i,o,u;e==null&&(e=this.name),t=function(e){var t;return t=e.properties[0].name.value,t.reserved?[]:[t]};if(e instanceof L)return[e.value];if(e instanceof Q)return t(e);n=[],u=e.objects;for(i=0,o=u.length;i=n.length)return"";if(n.length===1)return o=n[0].compile(e,T),r?o:""+lt("slice")+".call("+o+")";i=n.slice(a);for(u=l=0,c=i.length;l1?t.expressions.unshift(new b((new H(this.guard)).invert(),new L("continue"))):this.guard&&(t=u.wrap([new b(this.guard,t)]))),t="\n"+t.compile(e,k)+"\n"+this.tab),n=i+this.tab+("while ("+this.condition.compile(e,C)+") {"+t+"}"),this.returns&&(n+="\n"+this.tab+"return "+r+";"),n},t}(o),t.Op=D=function(e){function r(e,n,r,i){if(e==="in")return new w(n,r);if(e==="do")return this.generateDo(n);if(e==="new"){if(n instanceof a&&!n["do"]&&!n.isNew)return n.newInstance();if(n instanceof c&&n.bound||n["do"])n=new H(n)}return this.operator=t[e]||e,this.first=n,this.second=r,this.flip=!!i,this}var t,n;return dt(r,e),t={"==":"===","!=":"!==",of:"in"},n={"!==":"===","===":"!=="},r.prototype.children=["first","second"],r.prototype.isSimpleNumber=M,r.prototype.isUnary=function(){return!this.second},r.prototype.isComplex=function(){var e;return!this.isUnary()||(e=this.operator)!=="+"&&e!=="-"||this.first.isComplex()},r.prototype.isChainable=function(){var e;return(e=this.operator)==="<"||e===">"||e===">="||e==="<="||e==="==="||e==="!=="},r.prototype.invert=function(){var e,t,i,s,o;if(this.isChainable()&&this.first.isChainable()){e=!0,t=this;while(t&&t.operator)e&&(e=t.operator in n),t=t.first;if(!e)return(new H(this)).invert();t=this;while(t&&t.operator)t.invert=!t.invert,t.operator=n[t.operator],t=t.first;return this}return(s=n[this.operator])?(this.operator=s,this.first.unwrap()instanceof r&&this.first.invert(),this):this.second?(new H(this)).invert():this.operator==="!"&&(i=this.first.unwrap())instanceof r&&((o=i.operator)==="!"||o==="in"||o==="instanceof")?i:new r("!",this)},r.prototype.unfoldSoak=function(e){var t;return((t=this.operator)==="++"||t==="--"||t==="delete")&&ft(e,this,"first")},r.prototype.generateDo=function(e){var t,n,r,i,o,u,f,l;i=[],n=e instanceof s&&(o=e.value.unwrap())instanceof c?o:e,l=n.params||[];for(u=0,f=l.length;u=0))throw SyntaxError("prefix increment/decrement may not have eval or arguments operand");return this.isUnary()?this.compileUnary(e):n?this.compileChain(e):this.operator==="?"?this.compileExistence(e):(t=this.first.compile(e,N)+" "+this.operator+" "+this.second.compile(e,N),e.level<=N?t:"("+t+")")},r.prototype.compileChain=function(e){var t,n,r,i;return i=this.first.second.cache(e),this.first.second=i[0],r=i[1],n=this.first.compile(e,N),t=""+n+" "+(this.invert?"&&":"||")+" "+r.compile(e)+" "+this.operator+" "+this.second.compile(e,N),"("+t+")"},r.prototype.compileExistence=function(e){var t,n;return this.first.isComplex()?(n=new L(e.scope.freeVariable("ref")),t=new H(new s(n,this.first))):(t=this.first,n=t),(new b(new p(t),n,{type:"if"})).addElse(this.second).compile(e)},r.prototype.compileUnary=function(e){var t,n,i;if(e.level>=S)return(new H(this)).compile(e);n=[t=this.operator],i=t==="+"||t==="-",(t==="new"||t==="typeof"||t==="delete"||i&&this.first instanceof r&&this.first.operator===t)&&n.push(" ");if(i&&this.first instanceof r||t==="new"&&this.first.isStatement(e))this.first=new H(this.first);return n.push(this.first.compile(e,N)),this.flip&&n.reverse(),n.join("")},r.prototype.toString=function(e){return r.__super__.toString.call(this,e,this.constructor.name+" "+this.operator)},r}(o),t.In=w=function(e){function t(e,t){this.object=e,this.array=t}return dt(t,e),t.prototype.children=["object","array"],t.prototype.invert=O,t.prototype.compileNode=function(e){var t,n,r,i,s;if(this.array instanceof Q&&this.array.isArray()){s=this.array.base.objects;for(r=0,i=s.length;r= 0"),r===n?t:(t=r+", "+t,e.level=0)throw SyntaxError('catch variable may not be "'+this.error.value+'"');return e.scope.check(this.error.value)||e.scope.add(this.error.value,"param")," catch"+r+"{\n"+this.recovery.compile(e,k)+"\n"+this.tab+"}"}if(!this.ensure&&!this.recovery)return" catch (_error) {}"}.call(this),n=this.ensure?" finally {\n"+this.ensure.compile(e,k)+"\n"+this.tab+"}":"",""+this.tab+"try {\n"+i+"\n"+this.tab+"}"+(t||"")+n},t}(o),t.Throw=$=function(e){function t(e){this.expression=e}return dt(t,e),t.prototype.children=["expression"],t.prototype.isStatement=Y,t.prototype.jumps=M,t.prototype.makeReturn=V,t.prototype.compileNode=function(e){return this.tab+("throw "+this.expression.compile(e)+";")},t}(o),t.Existence=p=function(e){function t(e){this.expression=e}return dt(t,e),t.prototype.children=["expression"],t.prototype.invert=O,t.prototype.compileNode=function(e){var t,n,r,i;return this.expression.front=this.front,r=this.expression.compile(e,N),m.test(r)&&!e.scope.check(r)?(i=this.negated?["===","||"]:["!==","&&"],t=i[0],n=i[1],r="typeof "+r+" "+t+' "undefined" '+n+" "+r+" "+t+" null"):r=""+r+" "+(this.negated?"==":"!=")+" null",e.level<=x?r:"("+r+")"},t}(o),t.Parens=H=function(e){function t(e){this.body=e}return dt(t,e),t.prototype.children=["body"],t.prototype.unwrap=function(){return this.body},t.prototype.isComplex=function(){return this.body.isComplex()},t.prototype.compileNode=function(e){var t,n,r;return r=this.body.unwrap(),r instanceof Q&&r.isAtomic()?(r.front=this.front,r.compile(e)):(n=r.compile(e,C),t=e.level1?t.expressions.unshift(new b((new H(this.guard)).invert(),new L("continue"))):this.guard&&(t=u.wrap([new b(this.guard,t)]))),this.pattern&&t.expressions.unshift(new s(this.name,new L(""+M+"["+c+"]"))),n+=this.pluckDirectCall(e,t),g&&(_="\n"+a+g+";"),this.object&&(r=""+c+" in "+M,this.own&&(o="\n"+a+"if (!"+lt("hasProp")+".call("+M+", "+c+")) continue;")),t=t.compile(st(e,{indent:a}),k),t&&(t="\n"+t+"\n"),""+n+(w||"")+this.tab+"for ("+r+") {"+o+_+t+this.tab+"}"+(E||"")},t.prototype.pluckDirectCall=function(e,t){var n,r,i,o,u,f,l,h,p,d,v,m,g,y,b;r="",d=t.expressions;for(u=h=0,p=d.length;h=x?"("+r+")":r},t.prototype.unfoldSoak=function(){return this.soak&&this},t}(o),l={wrap:function(e,t,n){var i,s,o,f,l;if(e.jumps())return e;o=new c([],u.wrap([e])),i=[];if((f=e.contains(this.literalArgs))||e.contains(this.literalThis))l=new L(f?"apply":"call"),i=[new L("this")],f&&i.push(new L("arguments")),o=new Q(o,[new r(l)]);return o.noReturn=n,s=new a(o,i),t?u.wrap([s]):s},literalArgs:function(e){return e instanceof L&&e.value==="arguments"&&!e.asKey},literalThis:function(e){return e instanceof L&&e.value==="this"&&!e.asKey||e instanceof c&&e.bound||e instanceof a&&e.isSuper}},ft=function(e,t,n){var r;if(!(r=t[n].unfoldSoak(e)))return;return t[n]=r.body,r.body=new Q(t),r},K={"extends":function(){return"function(child, parent) { for (var key in parent) { if ("+lt("hasProp")+".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"},bind:function(){return"function(fn, me){ return function(){ return fn.apply(me, arguments); }; }"},indexOf:function(){return"[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"},hasProp:function(){return"{}.hasOwnProperty"},slice:function(){return"[].slice"}},k=1,C=2,T=3,x=4,N=5,S=6,X=" ",g="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",m=RegExp("^"+g+"$"),I=/^[+-]?\d+$/,A=RegExp("^(?:("+g+")\\.prototype(?:\\.("+g+")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|("+g+")$"),y=/^['"]/,lt=function(e){var t;return t="__"+e,R.root.assign(t,K[e]()),t},ot=function(e,t){return e=e.replace(/\n/g,"$&"+t),e.replace(/\s+$/,"")}}),define("ace/mode/coffee/scope",["require","exports","module","ace/mode/coffee/helpers"],function(e,t,n){var r,i,s,o;o=e("./helpers"),i=o.extend,s=o.last,t.Scope=r=function(){function e(t,n,r){this.parent=t,this.expressions=n,this.method=r,this.variables=[{name:"arguments",type:"arguments"}],this.positions={},this.parent||(e.root=this)}return e.root=null,e.prototype.add=function(e,t,n){return this.shared&&!n?this.parent.add(e,t,n):Object.prototype.hasOwnProperty.call(this.positions,e)?this.variables[this.positions[e]].type=t:this.positions[e]=this.variables.push({name:e,type:t})-1},e.prototype.namedMethod=function(){return this.method.name||!this.parent?this.method:this.parent.namedMethod()},e.prototype.find=function(e){return this.check(e)?!0:(this.add(e,"var"),!1)},e.prototype.parameter=function(e){if(this.shared&&this.parent.check(e,!0))return;return this.add(e,"param")},e.prototype.check=function(e){var t;return!!(this.type(e)||((t=this.parent)!=null?t.check(e):void 0))},e.prototype.temporary=function(e,t){return e.length>1?"_"+e+(t>1?t-1:""):"_"+(t+parseInt(e,36)).toString(36).replace(/\d/g,"a")},e.prototype.type=function(e){var t,n,r,i;i=this.variables;for(n=0,r=i.length;n1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function m(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError;var r=o.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e,u=n.apply(s,r.concat(o.call(arguments)));return u!==null&&Object(u)===u?u:s}return n.apply(t,r.concat(o.call(arguments)))};return i});var r=Function.prototype.call,i=Array.prototype,s=Object.prototype,o=i.slice,u=r.bind(s.toString),a=r.bind(s.hasOwnProperty),f,l,c,h,p;if(p=a(s,"__defineGetter__"))f=r.bind(s.__defineGetter__),l=r.bind(s.__defineSetter__),c=r.bind(s.__lookupGetter__),h=r.bind(s.__lookupSetter__);Array.isArray||(Array.isArray=function(t){return u(t)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=D(this),r=arguments[1],i=0,s=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;while(i>>0,i=Array(r),s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o>>0,i=[],s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i=0,s;if(arguments.length>=2)s=arguments[1];else do{if(i in n){s=n[i++];break}if(++i>=r)throw new TypeError}while(!0);for(;i>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i,s=r-1;if(arguments.length>=2)i=arguments[1];else do{if(s in n){i=n[s--];break}if(--s<0)throw new TypeError}while(!0);do s in this&&(i=t.call(void 0,i,n[s],s,n));while(s--);return i}),Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var n=D(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=M(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,M(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:s)});if(!Object.getOwnPropertyDescriptor){var d="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(d+t);if(!a(t,n))return;var r,i,o;r={enumerable:!0,configurable:!0};if(p){var u=t.__proto__;t.__proto__=s;var i=c(t,n),o=h(t,n);t.__proto__=u;if(i||o)return i&&(r.get=i),o&&(r.set=o),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var v;Object.prototype.__proto__===null?v=function(){return{__proto__:null}}:v=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=v();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var g=m({}),y=typeof document=="undefined"||m(document.createElement("div"));if(!g||!y)var b=Object.defineProperty}if(!Object.defineProperty||b){var w="Property description must be an object: ",E="Object.defineProperty called on non-object: ",S="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(E+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(w+r);if(b)try{return b.call(Object,t,n,r)}catch(i){}if(a(r,"value"))if(p&&(c(t,n)||h(t,n))){var o=t.__proto__;t.__proto__=s,delete t[n],t[n]=r.value,t.__proto__=o}else t[n]=r.value;else{if(!p)throw new TypeError(S);a(r,"get")&&f(t,n,r.get),a(r,"set")&&l(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)a(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(x){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(a(t,n))n+="?";t[n]=!0;var r=a(t,n);return delete t[n],r});if(!Object.keys){var T=!0,N=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],C=N.length;for(var k in{toString:null})T=!1;Object.keys=function P(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var P=[];for(var t in e)a(e,t)&&P.push(t);if(T)for(var n=0,r=C;n9999?"+":"")+("00000"+Math.abs(i)).slice(0<=i&&i<=9999?-4:-6),n=t.length;while(n--)r=t[n],r<10&&(t[n]="0"+r);return i+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(t){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(e){var t=function i(t,n,r,s,o,u,a){var f=arguments.length;if(this instanceof e){var l=f==1&&String(t)===t?new e(i.parse(t)):f>=7?new e(t,n,r,s,o,u,a):f>=6?new e(t,n,r,s,o,u):f>=5?new e(t,n,r,s,o):f>=4?new e(t,n,r,s):f>=3?new e(t,n,r):f>=2?new e(t,n):f>=1?new e(t):new e;return l.constructor=i,l}return e.apply(this,arguments)},n=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var r in e)t[r]=e[r];return t.now=e.now,t.UTC=e.UTC,t.prototype=e.prototype,t.prototype.constructor=t,t.parse=function(r){var i=n.exec(r);if(i){i.shift();for(var s=1;s<7;s++)i[s]=+(i[s]||(s<3?1:0)),s==1&&i[s]--;var o=+i.pop(),u=+i.pop(),a=i.pop(),f=0;if(a){if(u>23||o>59)return NaN;f=(u*60+o)*6e4*(a=="+"?-1:1)}var l=+i[0];return 0<=l&&l<=99?(i[0]=l+400,e.UTC.apply(this,i)+f-126227808e5):e.UTC.apply(this,i)+f}return e.parse.apply(this,arguments)},t}(Date));var L=" \n \f\r   ᠎ â€â€‚         âŸã€€\u2028\u2029";if(!String.prototype.trim||L.trim()){L="["+L+"]";var A=new RegExp("^"+L+L+"*"),O=new RegExp(L+L+"*$");String.prototype.trim=function(){return String(this).replace(A,"").replace(O,"")}}var M=function(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e},_="a"[0]!="a",D=function(e){if(e==null)throw new TypeError;return _&&typeof e=="string"&&e?e.split(""):Object(e)}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){var r={};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=function(){this.propagationStopped=!0}),t.preventDefault||(t.preventDefault=function(){this.defaultPrevented=!0});for(var i=0;i0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n=t&&(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this.insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this.insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this.removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this.insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};if(this.start.row>t)var i={row:t+1,column:0};if(this.start.rowthis.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column;t.action==="insertText"?n.start.row===r&&n.start.column<=i?n.start.row===n.end.row?i+=n.end.column-n.start.column:(i-=n.start.column,r+=n.end.row-n.start.row):n.start.row!==n.end.row&&n.start.row=i?i=n.start.column:i=Math.max(0,i-(n.end.column-n.start.column)):n.start.row!==n.end.row&&n.start.row=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/mode/css/csslint",["require","exports","module"],function(require,exports,module){function Reporter(e,t){this.messages=[],this.stats=[],this.lines=e,this.ruleset=t}var parserlib={};(function(){function e(){this._listeners={}}function t(e){this._input=e.replace(/\n\r?/g,"\n"),this._line=1,this._col=1,this._cursor=0}function n(e,t,n){this.col=n,this.line=t,this.message=e}function r(e,t,n,r){this.col=n,this.line=t,this.text=e,this.type=r}function i(e,n){this._reader=e?new t(e.toString()):null,this._token=null,this._tokenData=n,this._lt=[],this._ltIndex=0,this._ltIndexCache=[]}e.prototype={constructor:e,addListener:function(e,t){this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push(t)},fire:function(e){typeof e=="string"&&(e={type:e}),typeof e.target!="undefined"&&(e.target=this);if(typeof e.type=="undefined")throw new Error("Event object missing 'type' property.");if(this._listeners[e.type]){var t=this._listeners[e.type].concat();for(var n=0,r=t.length;n=0&&this._ltIndex-1&&!t[u.type].hide&&(u.channel=t[u.type].channel,this._token=u,this._lt.push(u),this._ltIndexCache.push(this._lt.length-this._ltIndex+i),this._lt.length>5&&this._lt.shift(),this._ltIndexCache.length>5&&this._ltIndexCache.shift(),this._ltIndex=this._lt.length),a=t[u.type],a&&(a.hide||a.channel!==undefined&&e!==a.channel)?this.get(e):u.type},LA:function(e){var t=e,n;if(e>0){if(e>5)throw new Error("Too much lookahead.");while(t)n=this.get(),t--;while(tthis._tokenData.length?"UNKNOWN_TOKEN":this._tokenData[e].name},tokenType:function(e){return this._tokenData[e]||-1},unget:function(){if(!this._ltIndexCache.length)throw new Error("Too much lookahead.");this._ltIndex-=this._ltIndexCache.pop(),this._token=this._lt[this._ltIndex-1]}},parserlib.util={StringReader:t,SyntaxError:n,SyntaxUnit:r,EventTarget:e,TokenStreamBase:i}})(),function(){function Combinator(e,t,n){SyntaxUnit.call(this,e,t,n,Parser.COMBINATOR_TYPE),this.type="unknown",/^\s+$/.test(e)?this.type="descendant":e==">"?this.type="child":e=="+"?this.type="adjacent-sibling":e=="~"&&(this.type="sibling")}function MediaFeature(e,t){SyntaxUnit.call(this,"("+e+(t!==null?":"+t:"")+")",e.startLine,e.startCol,Parser.MEDIA_FEATURE_TYPE),this.name=e,this.value=t}function MediaQuery(e,t,n,r,i){SyntaxUnit.call(this,(e?e+" ":"")+(t?t+" ":"")+n.join(" and "),r,i,Parser.MEDIA_QUERY_TYPE),this.modifier=e,this.mediaType=t,this.features=n}function Parser(e){EventTarget.call(this),this.options=e||{},this._tokenStream=null}function PropertyName(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.PROPERTY_NAME_TYPE),this.hack=t}function PropertyValue(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.PROPERTY_VALUE_TYPE),this.parts=e}function PropertyValueIterator(e){this._i=0,this._parts=e.parts,this._marks=[],this.value=e}function PropertyValuePart(text,line,col){SyntaxUnit.call(this,text,line,col,Parser.PROPERTY_VALUE_PART_TYPE),this.type="unknown";var temp;if(/^([+\-]?[\d\.]+)([a-z]+)$/i.test(text)){this.type="dimension",this.value=+RegExp.$1,this.units=RegExp.$2;switch(this.units.toLowerCase()){case"em":case"rem":case"ex":case"px":case"cm":case"mm":case"in":case"pt":case"pc":case"ch":this.type="length";break;case"deg":case"rad":case"grad":this.type="angle";break;case"ms":case"s":this.type="time";break;case"hz":case"khz":this.type="frequency";break;case"dpi":case"dpcm":this.type="resolution"}}else/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp.$1):/^([+\-]?\d+)$/i.test(text)?(this.type="integer",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)$/i.test(text)?(this.type="number",this.value=+RegExp.$1):/^#([a-f0-9]{3,6})/i.test(text)?(this.type="color",temp=RegExp.$1,temp.length==3?(this.red=parseInt(temp.charAt(0)+temp.charAt(0),16),this.green=parseInt(temp.charAt(1)+temp.charAt(1),16),this.blue=parseInt(temp.charAt(2)+temp.charAt(2),16)):(this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16))):/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3):/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100):/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3,this.alpha=+RegExp.$4):/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100,this.alpha=+RegExp.$4):/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100):/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100,this.alpha=+RegExp.$4):/^url\(["']?([^\)"']+)["']?\)/i.test(text)?(this.type="uri",this.uri=RegExp.$1):/^([^\(]+)\(/i.test(text)?(this.type="function",this.name=RegExp.$1,this.value=text):/^["'][^"']*["']/.test(text)?(this.type="string",this.value=eval(text)):Colors[text.toLowerCase()]?(this.type="color",temp=Colors[text.toLowerCase()].substring(1),this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16)):/^[\,\/]$/.test(text)?(this.type="operator",this.value=text):/^[a-z\-\u0080-\uFFFF][a-z0-9\-\u0080-\uFFFF]*$/i.test(text)&&(this.type="identifier",this.value=text)}function Selector(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.SELECTOR_TYPE),this.parts=e,this.specificity=Specificity.calculate(this)}function SelectorPart(e,t,n,r,i){SyntaxUnit.call(this,n,r,i,Parser.SELECTOR_PART_TYPE),this.elementName=e,this.modifiers=t}function SelectorSubPart(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.SELECTOR_SUB_PART_TYPE),this.type=t,this.args=[]}function Specificity(e,t,n,r){this.a=e,this.b=t,this.c=n,this.d=r}function isHexDigit(e){return e!==null&&h.test(e)}function isDigit(e){return e!==null&&/\d/.test(e)}function isWhitespace(e){return e!==null&&/\s/.test(e)}function isNewLine(e){return e!==null&&nl.test(e)}function isNameStart(e){return e!==null&&/[a-z_\u0080-\uFFFF\\]/i.test(e)}function isNameChar(e){return e!==null&&(isNameStart(e)||/[0-9\-\\]/.test(e))}function isIdentStart(e){return e!==null&&(isNameStart(e)||/\-\\/.test(e))}function mix(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function TokenStream(e){TokenStreamBase.call(this,e,Tokens)}function ValidationError(e,t,n){this.col=n,this.line=t,this.message=e}var EventTarget=parserlib.util.EventTarget,TokenStreamBase=parserlib.util.TokenStreamBase,StringReader=parserlib.util.StringReader,SyntaxError=parserlib.util.SyntaxError,SyntaxUnit=parserlib.util.SyntaxUnit,Colors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};Combinator.prototype=new SyntaxUnit,Combinator.prototype.constructor=Combinator,MediaFeature.prototype=new SyntaxUnit,MediaFeature.prototype.constructor=MediaFeature,MediaQuery.prototype=new SyntaxUnit,MediaQuery.prototype.constructor=MediaQuery,Parser.DEFAULT_TYPE=0,Parser.COMBINATOR_TYPE=1,Parser.MEDIA_FEATURE_TYPE=2,Parser.MEDIA_QUERY_TYPE=3,Parser.PROPERTY_NAME_TYPE=4,Parser.PROPERTY_VALUE_TYPE=5,Parser.PROPERTY_VALUE_PART_TYPE=6,Parser.SELECTOR_TYPE=7,Parser.SELECTOR_PART_TYPE=8,Parser.SELECTOR_SUB_PART_TYPE=9,Parser.prototype=function(){var e=new EventTarget,t,n={constructor:Parser,DEFAULT_TYPE:0,COMBINATOR_TYPE:1,MEDIA_FEATURE_TYPE:2,MEDIA_QUERY_TYPE:3,PROPERTY_NAME_TYPE:4,PROPERTY_VALUE_TYPE:5,PROPERTY_VALUE_PART_TYPE:6,SELECTOR_TYPE:7,SELECTOR_PART_TYPE:8,SELECTOR_SUB_PART_TYPE:9,_stylesheet:function(){var e=this._tokenStream,t=null,n,r,i;this.fire("startstylesheet"),this._charset(),this._skipCruft();while(e.peek()==Tokens.IMPORT_SYM)this._import(),this._skipCruft();while(e.peek()==Tokens.NAMESPACE_SYM)this._namespace(),this._skipCruft();i=e.peek();while(i>Tokens.EOF){try{switch(i){case Tokens.MEDIA_SYM:this._media(),this._skipCruft();break;case Tokens.PAGE_SYM:this._page(),this._skipCruft();break;case Tokens.FONT_FACE_SYM:this._font_face(),this._skipCruft();break;case Tokens.KEYFRAMES_SYM:this._keyframes(),this._skipCruft();break;case Tokens.UNKNOWN_SYM:e.get();if(!!this.options.strict)throw new SyntaxError("Unknown @ rule.",e.LT(0).startLine,e.LT(0).startCol);this.fire({type:"error",error:null,message:"Unknown @ rule: "+e.LT(0).value+".",line:e.LT(0).startLine,col:e.LT(0).startCol}),n=0;while(e.advance([Tokens.LBRACE,Tokens.RBRACE])==Tokens.LBRACE)n++;while(n)e.advance([Tokens.RBRACE]),n--;break;case Tokens.S:this._readWhitespace();break;default:if(!this._ruleset())switch(i){case Tokens.CHARSET_SYM:throw r=e.LT(1),this._charset(!1),new SyntaxError("@charset not allowed here.",r.startLine,r.startCol);case Tokens.IMPORT_SYM:throw r=e.LT(1),this._import(!1),new SyntaxError("@import not allowed here.",r.startLine,r.startCol);case Tokens.NAMESPACE_SYM:throw r=e.LT(1),this._namespace(!1),new SyntaxError("@namespace not allowed here.",r.startLine,r.startCol);default:e.get(),this._unexpectedToken(e.token())}}}catch(s){if(!(s instanceof SyntaxError&&!this.options.strict))throw s;this.fire({type:"error",error:s,message:s.message,line:s.line,col:s.col})}i=e.peek()}i!=Tokens.EOF&&this._unexpectedToken(e.token()),this.fire("endstylesheet")},_charset:function(e){var t=this._tokenStream,n,r,i,s;t.match(Tokens.CHARSET_SYM)&&(i=t.token().startLine,s=t.token().startCol,this._readWhitespace(),t.mustMatch(Tokens.STRING),r=t.token(),n=r.value,this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),e!==!1&&this.fire({type:"charset",charset:n,line:i,col:s}))},_import:function(e){var t=this._tokenStream,n,r,i,s=[];t.mustMatch(Tokens.IMPORT_SYM),i=t.token(),this._readWhitespace(),t.mustMatch([Tokens.STRING,Tokens.URI]),r=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this._readWhitespace(),s=this._media_query_list(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"import",uri:r,media:s,line:i.startLine,col:i.startCol})},_namespace:function(e){var t=this._tokenStream,n,r,i,s;t.mustMatch(Tokens.NAMESPACE_SYM),n=t.token().startLine,r=t.token().startCol,this._readWhitespace(),t.match(Tokens.IDENT)&&(i=t.token().value,this._readWhitespace()),t.mustMatch([Tokens.STRING,Tokens.URI]),s=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"namespace",prefix:i,uri:s,line:n,col:r})},_media:function(){var e=this._tokenStream,t,n,r;e.mustMatch(Tokens.MEDIA_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),r=this._media_query_list(),e.mustMatch(Tokens.LBRACE),this._readWhitespace(),this.fire({type:"startmedia",media:r,line:t,col:n});for(;;)if(e.peek()==Tokens.PAGE_SYM)this._page();else if(!this._ruleset())break;e.mustMatch(Tokens.RBRACE),this._readWhitespace(),this.fire({type:"endmedia",media:r,line:t,col:n})},_media_query_list:function(){var e=this._tokenStream,t=[];this._readWhitespace(),(e.peek()==Tokens.IDENT||e.peek()==Tokens.LPAREN)&&t.push(this._media_query());while(e.match(Tokens.COMMA))this._readWhitespace(),t.push(this._media_query());return t},_media_query:function(){var e=this._tokenStream,t=null,n=null,r=null,i=[];e.match(Tokens.IDENT)&&(n=e.token().value.toLowerCase(),n!="only"&&n!="not"?(e.unget(),n=null):r=e.token()),this._readWhitespace(),e.peek()==Tokens.IDENT?(t=this._media_type(),r===null&&(r=e.token())):e.peek()==Tokens.LPAREN&&(r===null&&(r=e.LT(1)),i.push(this._media_expression()));if(t===null&&i.length===0)return null;this._readWhitespace();while(e.match(Tokens.IDENT))e.token().value.toLowerCase()!="and"&&this._unexpectedToken(e.token()),this._readWhitespace(),i.push(this._media_expression());return new MediaQuery(n,t,i,r.startLine,r.startCol)},_media_type:function(){return this._media_feature()},_media_expression:function(){var e=this._tokenStream,t=null,n,r=null;return e.mustMatch(Tokens.LPAREN),t=this._media_feature(),this._readWhitespace(),e.match(Tokens.COLON)&&(this._readWhitespace(),n=e.LT(1),r=this._expression()),e.mustMatch(Tokens.RPAREN),this._readWhitespace(),new MediaFeature(t,r?new SyntaxUnit(r,n.startLine,n.startCol):null)},_media_feature:function(){var e=this._tokenStream;return e.mustMatch(Tokens.IDENT),SyntaxUnit.fromToken(e.token())},_page:function(){var e=this._tokenStream,t,n,r=null,i=null;e.mustMatch(Tokens.PAGE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),e.match(Tokens.IDENT)&&(r=e.token().value,r.toLowerCase()==="auto"&&this._unexpectedToken(e.token())),e.peek()==Tokens.COLON&&(i=this._pseudo_page()),this._readWhitespace(),this.fire({type:"startpage",id:r,pseudo:i,line:t,col:n}),this._readDeclarations(!0,!0),this.fire({type:"endpage",id:r,pseudo:i,line:t,col:n})},_margin:function(){var e=this._tokenStream,t,n,r=this._margin_sym();return r?(t=e.token().startLine,n=e.token().startCol,this.fire({type:"startpagemargin",margin:r,line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endpagemargin",margin:r,line:t,col:n}),!0):!1},_margin_sym:function(){var e=this._tokenStream;return e.match([Tokens.TOPLEFTCORNER_SYM,Tokens.TOPLEFT_SYM,Tokens.TOPCENTER_SYM,Tokens.TOPRIGHT_SYM,Tokens.TOPRIGHTCORNER_SYM,Tokens.BOTTOMLEFTCORNER_SYM,Tokens.BOTTOMLEFT_SYM,Tokens.BOTTOMCENTER_SYM,Tokens.BOTTOMRIGHT_SYM,Tokens.BOTTOMRIGHTCORNER_SYM,Tokens.LEFTTOP_SYM,Tokens.LEFTMIDDLE_SYM,Tokens.LEFTBOTTOM_SYM,Tokens.RIGHTTOP_SYM,Tokens.RIGHTMIDDLE_SYM,Tokens.RIGHTBOTTOM_SYM])?SyntaxUnit.fromToken(e.token()):null},_pseudo_page:function(){var e=this._tokenStream;return e.mustMatch(Tokens.COLON),e.mustMatch(Tokens.IDENT),e.token().value},_font_face:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.FONT_FACE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type:"startfontface",line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endfontface",line:t,col:n})},_operator:function(){var e=this._tokenStream,t=null;return e.match([Tokens.SLASH,Tokens.COMMA])&&(t=e.token(),this._readWhitespace()),t?PropertyValuePart.fromToken(t):null},_combinator:function(){var e=this._tokenStream,t=null,n;return e.match([Tokens.PLUS,Tokens.GREATER,Tokens.TILDE])&&(n=e.token(),t=new Combinator(n.value,n.startLine,n.startCol),this._readWhitespace()),t},_unary_operator:function(){var e=this._tokenStream;return e.match([Tokens.MINUS,Tokens.PLUS])?e.token().value:null},_property:function(){var e=this._tokenStream,t=null,n=null,r,i,s,o;return e.peek()==Tokens.STAR&&this.options.starHack&&(e.get(),i=e.token(),n=i.value,s=i.startLine,o=i.startCol),e.match(Tokens.IDENT)&&(i=e.token(),r=i.value,r.charAt(0)=="_"&&this.options.underscoreHack&&(n="_",r=r.substring(1)),t=new PropertyName(r,n,s||i.startLine,o||i.startCol),this._readWhitespace()),t},_ruleset:function(){var e=this._tokenStream,t,n;try{n=this._selectors_group()}catch(r){if(r instanceof SyntaxError&&!this.options.strict){this.fire({type:"error",error:r,message:r.message,line:r.line,col:r.col}),t=e.advance([Tokens.RBRACE]);if(t!=Tokens.RBRACE)throw r;return!0}throw r}return n&&(this.fire({type:"startrule",selectors:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endrule",selectors:n,line:n[0].line,col:n[0].col})),n},_selectors_group:function(){var e=this._tokenStream,t=[],n;n=this._selector();if(n!==null){t.push(n);while(e.match(Tokens.COMMA))this._readWhitespace(),n=this._selector(),n!==null?t.push(n):this._unexpectedToken(e.LT(1))}return t.length?t:null},_selector:function(){var e=this._tokenStream,t=[],n=null,r=null,i=null;n=this._simple_selector_sequence();if(n===null)return null;t.push(n);do{r=this._combinator();if(r!==null)t.push(r),n=this._simple_selector_sequence(),n===null?this._unexpectedToken(e.LT(1)):t.push(n);else{if(!this._readWhitespace())break;i=new Combinator(e.token().value,e.token().startLine,e.token().startCol),r=this._combinator(),n=this._simple_selector_sequence(),n===null?r!==null&&this._unexpectedToken(e.LT(1)):(r!==null?t.push(r):t.push(i),t.push(n))}}while(!0);return new Selector(t,t[0].line,t[0].col)},_simple_selector_sequence:function(){var e=this._tokenStream,t=null,n=[],r="",i=[function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo,this._negation],s=0,o=i.length,u=null,a=!1,f,l;f=e.LT(1).startLine,l=e.LT(1).startCol,t=this._type_selector(),t||(t=this._universal()),t!==null&&(r+=t);for(;;){if(e.peek()===Tokens.S)break;while(s1&&e.unget()),null)},_class:function(){var e=this._tokenStream,t;return e.match(Tokens.DOT)?(e.mustMatch(Tokens.IDENT),t=e.token(),new SelectorSubPart("."+t.value,"class",t.startLine,t.startCol-1)):null},_element_name:function(){var e=this._tokenStream,t;return e.match(Tokens.IDENT)?(t=e.token(),new SelectorSubPart(t.value,"elementName",t.startLine,t.startCol)):null},_namespace_prefix:function(){var e=this._tokenStream,t="";if(e.LA(1)===Tokens.PIPE||e.LA(2)===Tokens.PIPE)e.match([Tokens.IDENT,Tokens.STAR])&&(t+=e.token().value),e.mustMatch(Tokens.PIPE),t+="|";return t.length?t:null},_universal:function(){var e=this._tokenStream,t="",n;return n=this._namespace_prefix(),n&&(t+=n),e.match(Tokens.STAR)&&(t+="*"),t.length?t:null},_attrib:function(){var e=this._tokenStream,t=null,n,r;return e.match(Tokens.LBRACKET)?(r=e.token(),t=r.value,t+=this._readWhitespace(),n=this._namespace_prefix(),n&&(t+=n),e.mustMatch(Tokens.IDENT),t+=e.token().value,t+=this._readWhitespace(),e.match([Tokens.PREFIXMATCH,Tokens.SUFFIXMATCH,Tokens.SUBSTRINGMATCH,Tokens.EQUALS,Tokens.INCLUDES,Tokens.DASHMATCH])&&(t+=e.token().value,t+=this._readWhitespace(),e.mustMatch([Tokens.IDENT,Tokens.STRING]),t+=e.token().value,t+=this._readWhitespace()),e.mustMatch(Tokens.RBRACKET),new SelectorSubPart(t+"]","attribute",r.startLine,r.startCol)):null},_pseudo:function(){var e=this._tokenStream,t=null,n=":",r,i;return e.match(Tokens.COLON)&&(e.match(Tokens.COLON)&&(n+=":"),e.match(Tokens.IDENT)?(t=e.token().value,r=e.token().startLine,i=e.token().startCol-n.length):e.peek()==Tokens.FUNCTION&&(r=e.LT(1).startLine,i=e.LT(1).startCol-n.length,t=this._functional_pseudo()),t&&(t=new SelectorSubPart(n+t,"pseudo",r,i))),t},_functional_pseudo:function(){var e=this._tokenStream,t=null;return e.match(Tokens.FUNCTION)&&(t=e.token().value,t+=this._readWhitespace(),t+=this._expression(),e.mustMatch(Tokens.RPAREN),t+=")"),t},_expression:function(){var e=this._tokenStream,t="";while(e.match([Tokens.PLUS,Tokens.MINUS,Tokens.DIMENSION,Tokens.NUMBER,Tokens.STRING,Tokens.IDENT,Tokens.LENGTH,Tokens.FREQ,Tokens.ANGLE,Tokens.TIME,Tokens.RESOLUTION]))t+=e.token().value,t+=this._readWhitespace();return t.length?t:null},_negation:function(){var e=this._tokenStream,t,n,r="",i,s=null;return e.match(Tokens.NOT)&&(r=e.token().value,t=e.token().startLine,n=e.token().startCol,r+=this._readWhitespace(),i=this._negation_arg(),r+=i,r+=this._readWhitespace(),e.match(Tokens.RPAREN),r+=e.token().value,s=new SelectorSubPart(r,"not",t,n),s.args.push(i)),s},_negation_arg:function(){var e=this._tokenStream,t=[this._type_selector,this._universal,function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo],n=null,r=0,i=t.length,s,o,u,a;o=e.LT(1).startLine,u=e.LT(1).startCol;while(r0?new PropertyValue(t,t[0].line,t[0].col):null},_term:function(){var e=this._tokenStream,t=null,n=null,r,i,s;return t=this._unary_operator(),t!==null&&(i=e.token().startLine,s=e.token().startCol),e.peek()==Tokens.IE_FUNCTION&&this.options.ieFilters?(n=this._ie_function(),t===null&&(i=e.token().startLine,s=e.token().startCol)):e.match([Tokens.NUMBER,Tokens.PERCENTAGE,Tokens.LENGTH,Tokens.ANGLE,Tokens.TIME,Tokens.FREQ,Tokens.STRING,Tokens.IDENT,Tokens.URI,Tokens.UNICODE_RANGE])?(n=e.token().value,t===null&&(i=e.token().startLine,s=e.token().startCol),this._readWhitespace()):(r=this._hexcolor(),r===null?(t===null&&(i=e.LT(1).startLine,s=e.LT(1).startCol),n===null&&(e.LA(3)==Tokens.EQUALS&&this.options.ieFilters?n=this._ie_function():n=this._function())):(n=r.value,t===null&&(i=r.startLine,s=r.startCol))),n!==null?new PropertyValuePart(t!==null?t+n:n,i,s):null},_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match(Tokens.FUNCTION)){t=e.token().value,this._readWhitespace(),n=this._expr(),t+=n;if(this.options.ieFilters&&e.peek()==Tokens.EQUALS)do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_ie_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match([Tokens.IE_FUNCTION,Tokens.FUNCTION])){t=e.token().value;do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_hexcolor:function(){var e=this._tokenStream,t=null,n;if(e.match(Tokens.HASH)){t=e.token(),n=t.value;if(!/#[a-f0-9]{3,6}/i.test(n))throw new SyntaxError("Expected a hex color but found '"+n+"' at line "+t.startLine+", col "+t.startCol+".",t.startLine,t.startCol);this._readWhitespace()}return t},_keyframes:function(){var e=this._tokenStream,t,n,r,i="";e.mustMatch(Tokens.KEYFRAMES_SYM),t=e.token(),/^@\-([^\-]+)\-/.test(t.value)&&(i=RegExp.$1),this._readWhitespace(),r=this._keyframe_name(),this._readWhitespace(),e.mustMatch(Tokens.LBRACE),this.fire({type:"startkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),n=e.peek();while(n==Tokens.IDENT||n==Tokens.PERCENTAGE)this._keyframe_rule(),this._readWhitespace(),n=e.peek();this.fire({type:"endkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),e.mustMatch(Tokens.RBRACE)},_keyframe_name:function(){var e=this._tokenStream,t;return e.mustMatch([Tokens.IDENT,Tokens.STRING]),SyntaxUnit.fromToken(e.token())},_keyframe_rule:function(){var e=this._tokenStream,t,n=this._key_list();this.fire({type:"startkeyframerule",keys:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endkeyframerule",keys:n,line:n[0].line,col:n[0].col})},_key_list:function(){var e=this._tokenStream,t,n,r=[];r.push(this._key()),this._readWhitespace();while(e.match(Tokens.COMMA))this._readWhitespace(),r.push(this._key()),this._readWhitespace();return r},_key:function(){var e=this._tokenStream,t;if(e.match(Tokens.PERCENTAGE))return SyntaxUnit.fromToken(e.token());if(e.match(Tokens.IDENT)){t=e.token();if(/from|to/i.test(t.value))return SyntaxUnit.fromToken(t);e.unget()}this._unexpectedToken(e.LT(1))},_skipCruft:function(){while(this._tokenStream.match([Tokens.S,Tokens.CDO,Tokens.CDC]));},_readDeclarations:function(e,t){var n=this._tokenStream,r;this._readWhitespace(),e&&n.mustMatch(Tokens.LBRACE),this._readWhitespace();try{for(;;){if(!(n.match(Tokens.SEMICOLON)||t&&this._margin())){if(!this._declaration())break;if(!n.match(Tokens.SEMICOLON))break}this._readWhitespace()}n.mustMatch(Tokens.RBRACE),this._readWhitespace()}catch(i){if(!(i instanceof SyntaxError&&!this.options.strict))throw i;this.fire({type:"error",error:i,message:i.message,line:i.line,col:i.col}),r=n.advance([Tokens.SEMICOLON,Tokens.RBRACE]);if(r==Tokens.SEMICOLON)this._readDeclarations(!1,t);else if(r!=Tokens.RBRACE)throw i}},_readWhitespace:function(){var e=this._tokenStream,t="";while(e.match(Tokens.S))t+=e.token().value;return t},_unexpectedToken:function(e){throw new SyntaxError("Unexpected token '"+e.value+"' at line "+e.startLine+", col "+e.startCol+".",e.startLine,e.startCol)},_verifyEnd:function(){this._tokenStream.LA(1)!=Tokens.EOF&&this._unexpectedToken(this._tokenStream.LT(1))},_validateProperty:function(e,t){Validation.validate(e,t)},parse:function(e){this._tokenStream=new TokenStream(e,Tokens),this._stylesheet()},parseStyleSheet:function(e){return this.parse(e)},parseMediaQuery:function(e){this._tokenStream=new TokenStream(e,Tokens);var t=this._media_query();return this._verifyEnd(),t},parsePropertyValue:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._expr();return this._readWhitespace(),this._verifyEnd(),t},parseRule:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._ruleset();return this._readWhitespace(),this._verifyEnd(),t},parseSelector:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._selector();return this._readWhitespace(),this._verifyEnd(),t},parseStyleAttribute:function(e){e+="}",this._tokenStream=new TokenStream(e,Tokens),this._readDeclarations()}};for(t in n)n.hasOwnProperty(t)&&(e[t]=n[t]);return e}();var Properties={"alignment-adjust":"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ","alignment-baseline":"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",animation:1,"animation-delay":{multi:"
    \ No newline at end of file diff --git a/common/static/sass/_mixins.scss b/common/static/sass/_mixins.scss index 375ce20b92..a10d4bdcdd 100644 --- a/common/static/sass/_mixins.scss +++ b/common/static/sass/_mixins.scss @@ -7,12 +7,25 @@ @return $body-line-height * $amount; } -@mixin hide-text() { +// image-replacement hidden text +@mixin text-hide() { text-indent: -100%; white-space: nowrap; overflow: hidden; } +// hidden elems - screenreaders +@mixin text-sr() { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + @mixin vertically-and-horizontally-centered ( $height, $width ) { left: 50%; margin-left: -$width / 2; @@ -21,4 +34,4 @@ min-width: $width; position: absolute; top: 150px; -} +} \ No newline at end of file From 22444f6dfe94c9dfbfc075e4ea6849f14b124e19 Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Fri, 1 Feb 2013 20:50:29 -0500 Subject: [PATCH 0492/1392] studio - revised course nav: fixed placeholder login link text --- cms/templates/widgets/header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/templates/widgets/header.html b/cms/templates/widgets/header.html index d0f172ad55..e420c7e661 100644 --- a/cms/templates/widgets/header.html +++ b/cms/templates/widgets/header.html @@ -85,7 +85,7 @@

    You're not currently logged in

    1. - +
    From fcbd4bd1cd5ed1b83cd000f3f58fa4d45beeddcc Mon Sep 17 00:00:00 2001 From: Kevin Chugh Date: Sat, 2 Feb 2013 05:46:11 -0500 Subject: [PATCH 0493/1392] produce and consume group_id from dropdowns --- .../django_comment_client/base/views.py | 23 +++++++++++-------- .../django_comment_client/forum/views.py | 2 -- lms/djangoapps/django_comment_client/utils.py | 2 +- lms/templates/discussion/_new_post.html | 2 +- .../discussion/_underscore_templates.html | 2 +- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index ce53a8efbb..604fe60282 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -86,27 +86,32 @@ def create_thread(request, course_id, commentable_id): 'anonymous_to_peers' : anonymous_to_peers, 'commentable_id' : commentable_id, 'course_id' : course_id, - 'user_id' : request.user.id, + 'user_id' : request.user.id }) user = cc.User.from_django_user(request.user) + #kevinchugh because the new requirement is that all groups will be determined + #by the group id in the request this all goes away + # Cohort the thread if the commentable is cohorted. - if is_commentable_cohorted(course_id, commentable_id): - user_group_id = get_cohort_id(user, course_id) + #if is_commentable_cohorted(course_id, commentable_id): + # user_group_id = get_cohort_id(user, course_id) # TODO (vshnayder): once we have more than just cohorts, we'll want to # change this to a single get_group_for_user_and_commentable function # that can do different things depending on the commentable_id - if cached_has_permission(request.user, "see_all_cohorts", course_id): + # if cached_has_permission(request.user, "see_all_cohorts", course_id): # admins can optionally choose what group to post as - group_id = post.get('group_id', user_group_id) - else: + # group_id = post.get('group_id', user_group_id) + # else: # regular users always post with their own id. - group_id = user_group_id - thread.update_attributes(group_id=group_id) - + # group_id = user_group_id + if post['group_id']: + thread.update_attributes(group_id=post['group_id']) + thread.save() + print thread if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(thread) diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index c92324cbbb..fa07394c90 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -178,8 +178,6 @@ def forum_form_discussion(request, course_id): 'is_course_cohorted': is_course_cohorted(course_id) } # print "start rendering.." - print "\n\n\n\n*******************************" - print context return render_to_response('discussion/index.html', context) @login_required diff --git a/lms/djangoapps/django_comment_client/utils.py b/lms/djangoapps/django_comment_client/utils.py index 3c9669ac37..07d8ef9660 100644 --- a/lms/djangoapps/django_comment_client/utils.py +++ b/lms/djangoapps/django_comment_client/utils.py @@ -374,7 +374,7 @@ def safe_content(content): 'updated_at', 'depth', 'type', 'commentable_id', 'comments_count', 'at_position_list', 'children', 'highlighted_title', 'highlighted_body', 'courseware_title', 'courseware_url', 'tags', 'unread_comments_count', - 'read', + 'read', 'group_id' ] if (content.get('anonymous') is False) and (content.get('anonymous_to_peers') is False): diff --git a/lms/templates/discussion/_new_post.html b/lms/templates/discussion/_new_post.html index 5b55d409df..a009f19350 100644 --- a/lms/templates/discussion/_new_post.html +++ b/lms/templates/discussion/_new_post.html @@ -52,7 +52,7 @@
    Make visible to: -
    -
    - - -
    -
    - - or - -
    - - +
    +
    +
    +
    + +
    + Required Information to Sign into edX Studio + +
      +
    1. + + +
    2. + +
    3. + Forgot password? + + +
    4. +
    +
    + +
    + +
    + + + +
    +
    + + +
    + + + +<%block name="jsextra"> - - + \ No newline at end of file diff --git a/cms/templates/signup.html b/cms/templates/signup.html index 1c542fb437..3ff6ca953e 100644 --- a/cms/templates/signup.html +++ b/cms/templates/signup.html @@ -10,13 +10,13 @@

    Sign Up for edX Studio

    - +

    Ready to start creating online courses? Sign up below and start creating your first edX course today.

    -
    +
    @@ -67,6 +67,9 @@
    + + +
    diff --git a/cms/templates/widgets/header.html b/cms/templates/widgets/header.html index 9f0d5d1cff..62954b8211 100644 --- a/cms/templates/widgets/header.html +++ b/cms/templates/widgets/header.html @@ -2,6 +2,11 @@
    - - + + + +% else: +<%block name="title">Welcome to edX Studio +<%block name="bodyclass">not-signedin index howitworks <%block name="content"> -
    -
    -

    My Courses

    -
    - % if user.is_active: - New Course - - % else: -
    -

    - In order to start authoring courses using edX studio, please click on the activation link in your email. -

    -
    - % endif -
    -
    -
    + +
    +
    + +
    +
    +% endif \ No newline at end of file From 69225f643524e56a977331ba3e31a6bb2896efeb Mon Sep 17 00:00:00 2001 From: Kevin Chugh Date: Mon, 4 Feb 2013 08:33:33 -0500 Subject: [PATCH 0510/1392] cohort ID showing, have to translate to display text --- lms/djangoapps/django_comment_client/forum/views.py | 3 +++ lms/templates/discussion/_underscore_templates.html | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index fa07394c90..2f2809d89a 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -189,6 +189,9 @@ def single_thread(request, course_id, discussion_id, thread_id): try: thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id) + print("\n\n\n\n\n\n***************************") + print("thread.get('group_id','NONE')") + print(thread) except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError) as err: log.error("Error loading single thread.") raise Http404 diff --git a/lms/templates/discussion/_underscore_templates.html b/lms/templates/discussion/_underscore_templates.html index 9903da4c30..4acb6138b9 100644 --- a/lms/templates/discussion/_underscore_templates.html +++ b/lms/templates/discussion/_underscore_templates.html @@ -26,9 +26,11 @@
    - %if group_id: -
    This post visible only to Group ${cohort_dictionary[thread['group_id']]}.
    - %endif + + ${"<% if (obj.group_id) { %>"} +
    This post visible only to Group ${"<%- obj.group_id%>"}.
    + ${"<% } %>"} + + ${'<%- votes["up_count"] %>'}

    ${'<%- title %>'}

    From ecbe297936d28c8ca326d70b1c131428c8073ab7 Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Mon, 4 Feb 2013 09:39:36 -0500 Subject: [PATCH 0511/1392] studio - soft landing UI: how it works pathing, html and basic layout styling --- cms/djangoapps/contentstore/views.py | 2 + cms/static/img/pl-1x1-000.png | Bin 0 -> 924 bytes cms/static/img/pl-1x1-fff.png | Bin 0 -> 925 bytes cms/static/sass/_footer.scss | 2 +- cms/static/sass/_header.scss | 2 +- cms/static/sass/_index.scss | 252 ++++++++++++++++++++------- cms/static/sass/base-style.scss | 1 + cms/templates/howitworks.html | 139 +++++++++++++++ cms/templates/widgets/footer.html | 2 +- cms/urls.py | 1 + 10 files changed, 338 insertions(+), 63 deletions(-) create mode 100644 cms/static/img/pl-1x1-000.png create mode 100644 cms/static/img/pl-1x1-fff.png create mode 100644 cms/templates/howitworks.html diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index 14f96e312a..d8090cf68b 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -93,6 +93,8 @@ def login_page(request): 'forgot_password_link': "//{base}/#forgot-password-modal".format(base=settings.LMS_BASE), }) +def howitworks(request): + return render_to_response('howitworks.html', {}) # ==== Views for any logged-in user ================================== diff --git a/cms/static/img/pl-1x1-000.png b/cms/static/img/pl-1x1-000.png new file mode 100644 index 0000000000000000000000000000000000000000..b94b7a97467528a7b57b62a189428888464b2d0b GIT binary patch literal 924 zcmaJ=&yJHo9A;e)>n7`cJxy2-YAi6cU^^*pxC0!UCrb2u4=1K3q zgD>F0v#;R62k_!6IMXd%4^{%q%rD>f{r=8}e(%-U>7!FglFqzqXTaAZ@txe`|4+s6 zCtuE)J7z;NV?{u*)QQLx11|~Ycz}aw{q{Ro*z1ktM$|e9g~nyoj$i6c0DOQMg%#tw_Fn3ECy%0tsdTD3hBs zN2MiibrIhSvnqovge@)kHmI@R2R5M?7)resY7hd`RA9p}P52z>8q`&dzh(_KkYOVI z1=u|@_eP@`8aUmZFMhJ*1!Eaf)uJerqOK4+S7EEw5*oT*d zIAbwMflv&lWW_9*M|zt=lI>;Fd{-u3FtrRa6)KuYsRH``|Dj2;N9SyS@8bQZa6VdR zSRLS;tZ2v^H@gt7GGtR6FhWO!+*DQUF9;*~f@HuRn&62agmEeiPqz%;M_!tN4M)u+wB?+S8wVrthf#dR|!s8#f|Q`je}e<3`xd4 zJDA4raMYzF0o$Zed^i?(P;bYL4#%P&?Ws}klGHlgrg{lL`EF@(paf|=6u0UCdAf_ zU&0^gz{J494`ARYz{=Ecm&7Rp!LogKuioc*pZDXgd)=4EM~{yLK{$3V>^@r$`1jzD z{Xgb|A8dI@23C(?igm#F>2)MC-iTcP77jM6!rXbvV5)DUm-HFMd}ALM8OzcMu{o@y7?@EC^W^_x>xa13r(YoB|(E_cNi>ZK_e7f&q1?*j37qT z2St39WUw&BH7{g)ZdOFFcA+y<+=v=^Jz!yifG$_1prWe4Fl4o+8;1G}XcbjcD(p2R zwFY$qYG+{kh%6cjC$MjKwz1gB6sMG?P*L(cm-DKO$)%z;8V$~&X%h30vPDAuLQ1le zlEFq|4Jf+gn^ZxG|$2;$g_R*c* ze-dZIMT(R@%J7^7tZ|bQ9x8jv({ptM8hd(4u9rXYJ literal 0 HcmV?d00001 diff --git a/cms/static/sass/_footer.scss b/cms/static/sass/_footer.scss index f15eb1c54a..66a9ce0e95 100644 --- a/cms/static/sass/_footer.scss +++ b/cms/static/sass/_footer.scss @@ -5,7 +5,7 @@ position: relative; width: 100%; - footer { + footer.primary { @include clearfix(); @include font-size(13); max-width: $fg-max-width; diff --git a/cms/static/sass/_header.scss b/cms/static/sass/_header.scss index 518c4bb701..b65d9098e4 100644 --- a/cms/static/sass/_header.scss +++ b/cms/static/sass/_header.scss @@ -19,7 +19,7 @@ } } - header { + header.primary { @include clearfix(); max-width: $fg-max-width; min-width: $fg-min-width; diff --git a/cms/static/sass/_index.scss b/cms/static/sass/_index.scss index a3e210b558..e80f2727ef 100644 --- a/cms/static/sass/_index.scss +++ b/cms/static/sass/_index.scss @@ -1,78 +1,210 @@ -body.index { - > header { - display: none; - } +// how it works/not signed in index +.index { - > h1 { - font-weight: 300; - color: lighten($dark-blue, 40%); - text-shadow: 0 1px 0 #fff; - -webkit-font-smoothing: antialiased; - max-width: 600px; - text-align: center; - margin: 80px auto 30px; - } + &.not-signedin { - section.main-container { - border-right: 3px; - background: #FFF; - max-width: 600px; - margin: 0 auto; - display: block; - @include box-sizing(border-box); - border: 1px solid lighten( $dark-blue , 30% ); - @include border-radius(3px); - overflow: hidden; - @include bounce-in-animation(.8s); + .wrapper-header { + margin-bottom: 0; + } - header { - border-bottom: 1px solid lighten($dark-blue, 50%); - @include linear-gradient(#fff, lighten($dark-blue, 62%)); - @include clearfix(); - @include box-shadow( 0 2px 0 $light-blue, inset 0 -1px 0 #fff); - text-shadow: 0 1px 0 #fff; + .wrapper-footer { - h1 { - font-size: 14px; - padding: 8px 20px; - float: left; - color: $dark-blue; - margin: 0; - } - - a { - float: right; - padding: 8px 20px; - border-left: 1px solid lighten($dark-blue, 50%); - @include box-shadow( inset -1px 0 0 #fff); - font-weight: bold; - font-size: 22px; - line-height: 1; - color: $dark-blue; + footer.primary { + border: none; + margin-top: 0; + padding-top: 0; } } - ol { - list-style: none; + .wrapper-content-header, .wrapper-content-features, .wrapper-content-cta { margin: 0; - padding: 0; + padding: 0 $baseline; + position: relative; + width: 100%; + } - li { - border-bottom: 1px solid lighten($dark-blue, 50%); + .content { + @include clearfix(); + @include font-size(16); + max-width: $fg-max-width; + min-width: $fg-min-width; + width: flex-grid(12); + margin: 0 auto; + color: $gray-d2; + + header { - a { - display: block; - padding: 10px 20px; + } - &:hover { - color: $dark-blue; - background: lighten($yellow, 10%); - text-shadow: 0 1px 0 #fff; + h2 { + + } + + h3 { + + } + + h4 { + + } + } + + // welcome content + .wrapper-content-header { + padding-bottom: ($baseline*3); + padding-top: ($baseline*3); + background: $blue; + } + + .content-header { + text-align: center; + color: $white; + + h1 { + @include font-size(52); + float: none; + margin: 0 0 ($baseline/2) 0; + border-bottom: 1px solid $blue-l1; + padding: 0; + font-weight: 600; + } + + .tagline { + @include font-size(24); + margin: 0; + color: $white; + } + } + + // feature content + .wrapper-content-features { + padding-bottom: ($baseline*2); + padding-top: ($baseline*2); + background: $white; + } + + .content-features { + + .list-features { + + } + + // indiv features + .feature { + @include clearfix(); + margin: 0 0 ($baseline*2) 0; + border-bottom: 1px solid $gray-l4; + padding: 0 0 ($baseline*2) 0; + + .img { + float: left; + width: flex-grid(3, 12); + margin-right: flex-gutter(); + + img { + display: block; + width: 100%; + height: 100%; + background: $black; + } + } + + .copy { + float: left; + width: flex-grid(8, 12); + margin-top: -($baseline/4); + + h3 { + margin: 0 0 ($baseline) 0; + @include font-size(24); + font-weight: 600; + } + + > p { + @include font-size(18); + } + + .list-proofpoints { + @include clearfix(); + @include font-size(14); + width: flex-grid(8, 8); + margin: ($baseline*1.5) 0 0 0; + + .proofpoint { + float: left; + width: flex-grid(3, 8); + margin-right: flex-gutter(); + + &:last-child { + margin-right: 0; + } + + .title { + @include font-size(16); + margin: 0 0 ($baseline/4) 0; + font-weight: 600; + } + } + } + } + + &:nth-child(even) { + + .img { + float: right; + margin-right: 0; + margin-left: flex-gutter(); + } + + .copy { + float: right; + text-align: right; } } &:last-child { - border-bottom: none; + margin-bottom: 0; + border: none; + padding-bottom: 0; + } + } + } + + // call to action content + .wrapper-content-cta { + padding-bottom: ($baseline*2); + padding-top: ($baseline*2); + background: $white; + } + + .content-cta { + + .list-actions { + + li { + width: flex-grid(6, 12); + margin: 0 auto; + } + + .action { + display: block; + width: 100%; + text-align: center; + } + + .action-primary { + @include blue-button; + @include transition(all .15s); + @include font-size(18); + padding: ($baseline*0.75) ($baseline/2); + font-weight: 600; + text-align: center; + text-transform: uppercase; + } + + .action-secondary { + @include font-size(14); + margin-top: ($baseline/2); } } } diff --git a/cms/static/sass/base-style.scss b/cms/static/sass/base-style.scss index f77b5ca15b..dceac4233d 100644 --- a/cms/static/sass/base-style.scss +++ b/cms/static/sass/base-style.scss @@ -30,6 +30,7 @@ @import "alerts"; @import "login"; @import "account"; +@import "index"; @import 'jquery-ui-calendar'; @import 'content-types'; diff --git a/cms/templates/howitworks.html b/cms/templates/howitworks.html new file mode 100644 index 0000000000..8f7349d476 --- /dev/null +++ b/cms/templates/howitworks.html @@ -0,0 +1,139 @@ +<%inherit file="base.html" /> +<%! from django.core.urlresolvers import reverse %> + +<%block name="title">Welcome to edX Studio +<%block name="bodyclass">not-signedin index howitworks + +<%block name="content"> + +

    +
    +
    +

    Welcome to edX Studio

    +

    Studio helps manage your courses online, so you can focus on teaching them

    +
    +
    +
    + +
    +
    +
    +

    Studio's Many Features

    +
    + +
      +
    1. +
      + Studio Helps You Keep Your Courses Organized +
      Studio Helps You Keep Your Courses Organized
      +
      + +
      +

      Keeping Your Course Organized

      +

      The backbone of your course is how it is organized. Studio offers an Outline Mode, providing a simple hierarchy and easy drag and drop to help you and your students stay organized.

      + +
        +
      • +

        Simple Organization For Content

        +

        Studio uses Sections and Learning Sequences to organize your content into a simple hierarchy.

        +
      • + +
      • +

        Change Your Mind Anytime

        +

        Draft your outline and build content anywhere. Simple drag and drop tools let your reorganize quickly.

        +
      • + +
      • +

        Go A Week Or A Semester At A Time

        +

        Build and release Sections to your students incrementally. You don't have to have it all done at once.

        +
      • +
      +
      +
    2. + +
    3. +
      + Studio Keeps Your Learning Sequences and Lectures, Together +
      Studio Keeps Your Learning Sequences and Lectures, Together
      +
      + +
      +

      Learning Sequences: Lectures and Exercises, Together

      +

      The heart of the student experience is being immersed in Learning Sequences — short video lectures interleaved with exercises. Studio allows you to insert videos and author a wide variety of exercise types with just a few clicks.

      + +
        +
      • +

        Create Learning Pathways

        +

        Help your students understand a small interactive piece at a time. Learning Sequences are built from Learning Units.

        +
      • + +
      • +

        Work Visually, Organize Quickly

        +

        Work visually and see exactly what your students will see. Reorganize your Learning Units with drag and drop.

        +
      • + +
      • +

        A Broad Library of Problem Types

        +

        It's more than just multiple choice. Studio has nearly a dozen types of problems to challenge your learners.

        +
      • +
      +
      +
    4. + +
    5. +
      + Studio Gives You Simple, Fast, and Incremental Publishing. With Friends. +
      Studio Gives You Simple, Fast, and Incremental Publishing. With Friends.
      +
      + +
      +

      Simple, Fast, and Incremental Publishing. With Friends.

      +

      Studio works like web applications you already know, yet understands how you build curriculum. Instant publishing to the web when you want it, incremental release when it makes sense. And with co-authors, you can have a whole team building a course, together.

      + +
        +
      • +

        Instant Changes

        +

        Caught a bug? No problem. When you want, your changes to live when you hit Save.

        +
      • + +
      • +

        Release-On Date Publishing

        +

        When you've finished a Section, pick when you want it to go live and Studio takes care of the rest. Build your course incrementally.

        +
      • + +
      • +

        Work in Teams

        +

        Co-authors have full access to all the same authoring tools. Make your course better through a team effort.

        +
      • +
      +
      +
    6. +
    +
    +
    + +
    +
    +
    +

    Sign Up for Studio Today!

    +
    + + +
    +
    + + +<%block name="jsextra"> + + \ No newline at end of file diff --git a/cms/templates/widgets/footer.html b/cms/templates/widgets/footer.html index 1cd387f7ed..e0db473864 100644 --- a/cms/templates/widgets/footer.html +++ b/cms/templates/widgets/footer.html @@ -1,7 +1,7 @@ <%! from django.core.urlresolvers import reverse %> <%block name="jsextra"> diff --git a/cms/templates/howitworks.html b/cms/templates/howitworks.html index e799143287..28b67142df 100644 --- a/cms/templates/howitworks.html +++ b/cms/templates/howitworks.html @@ -59,7 +59,7 @@
  • - Studio Keeps Your Learning Sequences and Lectures, Together + Studio Keeps Your Learning Sequences and Lectures, Together
    Studio Keeps Your Learning Sequences and Lectures, Together
    @@ -93,7 +93,7 @@
  • - Studio Gives You Simple, Fast, and Incremental Publishing. With Friends. + Studio Gives You Simple, Fast, and Incremental Publishing. With Friends.
    Studio Gives You Simple, Fast, and Incremental Publishing. With Friends.
    @@ -144,27 +144,55 @@
  • - +

    Feature #3

    +
    + +
    Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
    +
    + +
    + + close modal + + <%block name="jsextra"> diff --git a/cms/templates/widgets/header.html b/cms/templates/widgets/header.html index 62954b8211..8c3ea9fc72 100644 --- a/cms/templates/widgets/header.html +++ b/cms/templates/widgets/header.html @@ -78,6 +78,7 @@ \ No newline at end of file From 96eb16cd729ce65df69b3f70d4b8d95341d8a650 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Wed, 6 Feb 2013 10:08:20 -0500 Subject: [PATCH 0667/1392] Make local dev work by trying checking staticfiles_storage for both the course_prefixed and non-course_prefixed urls --- common/djangoapps/static_replace/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/common/djangoapps/static_replace/__init__.py b/common/djangoapps/static_replace/__init__.py index cfef798bdf..4833f5ef96 100644 --- a/common/djangoapps/static_replace/__init__.py +++ b/common/djangoapps/static_replace/__init__.py @@ -76,18 +76,19 @@ def replace_static_urls(text, data_directory, course_namespace=None): # course_namespace is not None, then use studio style urls if course_namespace is not None and not isinstance(modulestore(), XMLModuleStore): url = StaticContent.convert_legacy_static_url(rest, course_namespace) - # If we're in debug mode, and the file as requested exists, then don't change the links - elif (settings.DEBUG and finders.find(rest, True)): - return original - # Otherwise, look the file up in staticfiles_storage without the data directory + # Otherwise, look the file up in staticfiles_storage, and append the data directory if needed else: + course_path = "/".join((data_directory, rest)) try: - url = staticfiles_storage.url(rest) + if staticfiles_storage.exists(rest): + url = staticfiles_storage.url(rest) + else: + url = staticfiles_storage.url(course_path) # And if that fails, assume that it's course content, and add manually data directory except Exception as err: log.warning("staticfiles_storage couldn't find path {0}: {1}".format( rest, str(err))) - url = "".join([prefix, data_directory, '/', rest]) + url = "".join([prefix, course_path]) return "".join([quote, url, quote]) From 1cc62fae7504f8851444e2e15b8f4a13e3e18cf8 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Wed, 6 Feb 2013 10:23:29 -0500 Subject: [PATCH 0668/1392] Catch null pointer for uninitialized dates --- cms/static/js/views/settings/main_settings_view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/static/js/views/settings/main_settings_view.js b/cms/static/js/views/settings/main_settings_view.js index 15762eaeac..377fe587f5 100644 --- a/cms/static/js/views/settings/main_settings_view.js +++ b/cms/static/js/views/settings/main_settings_view.js @@ -242,7 +242,7 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({ time = 0; } var newVal = new Date(date.getTime() + time * 1000); - if (cacheModel.get(fieldName).getTime() !== newVal.getTime()) { + if (!cacheModel.has(fieldName) || cacheModel.get(fieldName).getTime() !== newVal.getTime()) { cacheModel.save(fieldName, newVal, { error: CMS.ServerError}); } } From 2302b40022384b37a82c59824f9c313920d7a6cb Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Wed, 6 Feb 2013 10:33:36 -0500 Subject: [PATCH 0669/1392] Fix static_replace tests --- .../test/test_static_replace.py | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/common/djangoapps/static_replace/test/test_static_replace.py b/common/djangoapps/static_replace/test/test_static_replace.py index e08c66c59f..63fc3eaa6a 100644 --- a/common/djangoapps/static_replace/test/test_static_replace.py +++ b/common/djangoapps/static_replace/test/test_static_replace.py @@ -24,15 +24,24 @@ def test_multi_replace(): ) -@patch('static_replace.finders') -@patch('static_replace.settings') -def test_debug_no_modify(mock_settings, mock_finders): - mock_settings.DEBUG = True - mock_finders.find.return_value = True +@patch('static_replace.staticfiles_storage') +def test_storage_url_exists(mock_storage): + mock_storage.exists.return_value = True + mock_storage.url.return_value = '/static/file.png' - assert_equals(STATIC_SOURCE, replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) + assert_equals('"/static/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) + mock_storage.exists.called_once_with('file.png') + mock_storage.url.called_once_with('data_dir/file.png') - mock_finders.find.assert_called_once_with('file.png', True) + +@patch('static_replace.staticfiles_storage') +def test_storage_url_not_exists(mock_storage): + mock_storage.exists.return_value = False + mock_storage.url.return_value = '/static/data_dir/file.png' + + assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) + mock_storage.exists.called_once_with('file.png') + mock_storage.url.called_once_with('file.png') @patch('static_replace.StaticContent') @@ -58,7 +67,10 @@ def test_mongo_filestore(mock_modulestore, mock_static_content): @patch('static_replace.staticfiles_storage') def test_data_dir_fallback(mock_storage, mock_modulestore, mock_settings): mock_modulestore.return_value = Mock(XMLModuleStore) - mock_settings.DEBUG = False mock_storage.url.side_effect = Exception + mock_storage.exists.return_value = True + assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) + + mock_storage.exists.return_value = False assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) From b63c3c5a676242e6a9c42cc2ca094136d72143a0 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Fri, 1 Feb 2013 17:09:37 -0500 Subject: [PATCH 0670/1392] Change modulestore name and subclass TestCase --- .../contentstore/tests/factories.py | 46 ++++++++- .../contentstore/tests/test_contentstore.py | 94 +++++++++++++++++++ cms/envs/test.py | 7 +- 3 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 cms/djangoapps/contentstore/tests/test_contentstore.py diff --git a/cms/djangoapps/contentstore/tests/factories.py b/cms/djangoapps/contentstore/tests/factories.py index cb9f451d38..e9a535f372 100644 --- a/cms/djangoapps/contentstore/tests/factories.py +++ b/cms/djangoapps/contentstore/tests/factories.py @@ -1,10 +1,52 @@ from factory import Factory -from xmodule.modulestore import Location -from xmodule.modulestore.django import modulestore +from datetime import datetime from time import gmtime from uuid import uuid4 +from student.models import (User, UserProfile, Registration, + CourseEnrollmentAllowed) +from django.contrib.auth.models import Group +from xmodule.modulestore import Location +from xmodule.modulestore.django import modulestore from xmodule.timeparse import stringify_time +class UserProfileFactory(Factory): + FACTORY_FOR = UserProfile + + user = None + name = 'Robot Studio' + courseware = 'course.xml' + +class RegistrationFactory(Factory): + FACTORY_FOR = Registration + + user = None + activation_key = uuid4().hex + +class UserFactory(Factory): + FACTORY_FOR = User + + username = 'robot' + email = 'robot@edx.org' + password = 'test' + first_name = 'Robot' + last_name = 'Tester' + is_staff = False + is_active = True + is_superuser = False + last_login = datetime.now() + date_joined = datetime.now() + +class GroupFactory(Factory): + FACTORY_FOR = Group + + name = 'test_group' + +class CourseEnrollmentAllowedFactory(Factory): + FACTORY_FOR = CourseEnrollmentAllowed + + email = 'test@edx.org' + course_id = 'edX/test/2012_Fall' + def XMODULE_COURSE_CREATION(class_to_create, **kwargs): return XModuleCourseFactory._create(class_to_create, **kwargs) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py new file mode 100644 index 0000000000..cc37d201a1 --- /dev/null +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -0,0 +1,94 @@ +import json +import shutil +from django.test import TestCase +from django.test.client import Client +from override_settings import override_settings +from django.conf import settings +from django.core.urlresolvers import reverse +from path import path +import json +from fs.osfs import OSFS +import copy +from mock import Mock + +import xmodule.modulestore.django +from factories import * + +# Subclass TestCase and use to initialize the contentstore +class CmsTestCase(TestCase): + + def _pre_setup(self): + super(CmsTestCase, self)._pre_setup() + # Flush and initialize the module store + # It needs the templates because it creates new records + # by cloning from the template. + # Note that if your test module gets in some weird state + # (though it shouldn't), do this manually + # from the bash shell to drop it: + # $ mongo test_xmodule --eval "db.dropDatabase()" + xmodule.modulestore.django._MODULESTORES = {} + xmodule.modulestore.django.modulestore().collection.drop() + xmodule.templates.update_templates() + + def _post_teardown(self): + # Make sure you flush out the test modulestore after the end + # of the last test because otherwise on the next run + # cms/djangoapps/contentstore/__init__.py + # update_templates() will try to update the templates + # via upsert and it sometimes seems to be messing things up. + xmodule.modulestore.django._MODULESTORES = {} + xmodule.modulestore.django.modulestore().collection.drop() + super(CmsTestCase, self)._post_teardown() + +def parse_json(response): + """Parse response, which is assumed to be json""" + return json.loads(response.content) + +TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) +TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') +TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') + +@override_settings(MODULESTORE=TEST_DATA_MODULESTORE) +class NewContentStoreTest(CmsTestCase): + + def setUp(self): + # super(NewContentStoreTest, self).setUp() + uname = 'testuser' + email = 'test+courses@edx.org' + password = 'foo' + + # Create the use so we can log them in. + self.user = User.objects.create_user(uname, email, password) + + # Note that we do not actually need to do anything + # for registration if we directly mark them active. + self.user.is_active = True + # Staff has access to view all courses + self.user.is_staff = True + self.user.save() + + # user = UserFactory(username=uname, email=email, password=password, + # is_staff=True, is_active=True) + # user.is_authenticated= Mock(return_value=True) + + + self.client = Client() + self.client.login(username=uname, password=password) + + self.course_data = { + 'template': 'i4x://edx/templates/course/Empty', + 'org': 'MITx', + 'number': '999', + 'display_name': 'Robot Super Course', + } + + def tearDown(self): + # super(NewContentStoreTest, self).tearDown() + pass + + def test_create_course(self): + """Test new course creation - happy path""" + resp = self.client.post(reverse('create_new_course'), self.course_data) + self.assertEqual(resp.status_code, 200) + data = parse_json(resp) + self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') diff --git a/cms/envs/test.py b/cms/envs/test.py index d9a2597cbb..436aa2189e 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -10,7 +10,7 @@ sessions. Assumes structure: from .common import * import os from path import path - +from time import time # Nose Test Runner INSTALLED_APPS += ('django_nose',) @@ -39,11 +39,14 @@ STATICFILES_DIRS += [ if os.path.isdir(COMMON_TEST_DATA_ROOT / course_dir) ] +# Use the current seconds since epoch to differentiate +# the mongo collections on jenkins. +sec_since_epoch = '%s' % int(time()*100) modulestore_options = { 'default_class': 'xmodule.raw_module.RawDescriptor', 'host': 'localhost', 'db': 'test_xmodule', - 'collection': 'modulestore', + 'collection': 'modulestore_%s' % sec_since_epoch, 'fs_root': GITHUB_REPO_ROOT, 'render_template': 'mitxmako.shortcuts.render_to_string', } From b329b0ea42447cfb23a082a0860bfabdb46155af Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Sat, 2 Feb 2013 15:53:30 -0500 Subject: [PATCH 0671/1392] Remove toy dbs from CMS test settings.py file as they are not used. --- cms/envs/test.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/cms/envs/test.py b/cms/envs/test.py index 436aa2189e..c22965d748 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -75,17 +75,6 @@ DATABASES = { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ENV_ROOT / "db" / "cms.db", }, - - # The following are for testing purposes... - 'edX/toy/2012_Fall': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ENV_ROOT / "db" / "course1.db", - }, - - 'edx/full/6.002_Spring_2012': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ENV_ROOT / "db" / "course2.db", - } } LMS_BASE = "localhost:8000" From 2c5a7ccdf701aca7890b9b8cbf8fde1669912d1a Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Sat, 2 Feb 2013 16:39:46 -0500 Subject: [PATCH 0672/1392] Rearrange factories and clean up imports --- .../contentstore/tests/factories.py | 115 ----------------- cms/djangoapps/contentstore/tests/tests.py | 33 ++--- .../xmodule/modulestore/tests/factories.py | 117 ++++++++++++++++++ 3 files changed, 135 insertions(+), 130 deletions(-) create mode 100644 common/lib/xmodule/xmodule/modulestore/tests/factories.py diff --git a/cms/djangoapps/contentstore/tests/factories.py b/cms/djangoapps/contentstore/tests/factories.py index e9a535f372..f9c505d68f 100644 --- a/cms/djangoapps/contentstore/tests/factories.py +++ b/cms/djangoapps/contentstore/tests/factories.py @@ -1,13 +1,9 @@ from factory import Factory from datetime import datetime -from time import gmtime from uuid import uuid4 from student.models import (User, UserProfile, Registration, CourseEnrollmentAllowed) from django.contrib.auth.models import Group -from xmodule.modulestore import Location -from xmodule.modulestore.django import modulestore -from xmodule.timeparse import stringify_time class UserProfileFactory(Factory): FACTORY_FOR = UserProfile @@ -46,114 +42,3 @@ class CourseEnrollmentAllowedFactory(Factory): email = 'test@edx.org' course_id = 'edX/test/2012_Fall' - - -def XMODULE_COURSE_CREATION(class_to_create, **kwargs): - return XModuleCourseFactory._create(class_to_create, **kwargs) - -def XMODULE_ITEM_CREATION(class_to_create, **kwargs): - return XModuleItemFactory._create(class_to_create, **kwargs) - -class XModuleCourseFactory(Factory): - """ - Factory for XModule courses. - """ - - ABSTRACT_FACTORY = True - _creation_function = (XMODULE_COURSE_CREATION,) - - @classmethod - def _create(cls, target_class, *args, **kwargs): - - template = Location('i4x', 'edx', 'templates', 'course', 'Empty') - org = kwargs.get('org') - number = kwargs.get('number') - display_name = kwargs.get('display_name') - location = Location('i4x', org, number, - 'course', Location.clean(display_name)) - - store = modulestore('direct') - - # Write the data to the mongo datastore - new_course = store.clone_item(template, location) - - # This metadata code was copied from cms/djangoapps/contentstore/views.py - if display_name is not None: - new_course.metadata['display_name'] = display_name - - new_course.metadata['data_dir'] = uuid4().hex - new_course.metadata['start'] = stringify_time(gmtime()) - new_course.tabs = [{"type": "courseware"}, - {"type": "course_info", "name": "Course Info"}, - {"type": "discussion", "name": "Discussion"}, - {"type": "wiki", "name": "Wiki"}, - {"type": "progress", "name": "Progress"}] - - # Update the data in the mongo datastore - store.update_metadata(new_course.location.url(), new_course.own_metadata) - - return new_course - -class Course: - pass - -class CourseFactory(XModuleCourseFactory): - FACTORY_FOR = Course - - template = 'i4x://edx/templates/course/Empty' - org = 'MITx' - number = '999' - display_name = 'Robot Super Course' - -class XModuleItemFactory(Factory): - """ - Factory for XModule items. - """ - - ABSTRACT_FACTORY = True - _creation_function = (XMODULE_ITEM_CREATION,) - - @classmethod - def _create(cls, target_class, *args, **kwargs): - """ - kwargs must include parent_location, template. Can contain display_name - target_class is ignored - """ - - DETACHED_CATEGORIES = ['about', 'static_tab', 'course_info'] - - parent_location = Location(kwargs.get('parent_location')) - template = Location(kwargs.get('template')) - display_name = kwargs.get('display_name') - - store = modulestore('direct') - - # This code was based off that in cms/djangoapps/contentstore/views.py - parent = store.get_item(parent_location) - dest_location = parent_location._replace(category=template.category, name=uuid4().hex) - - new_item = store.clone_item(template, dest_location) - - # TODO: This needs to be deleted when we have proper storage for static content - new_item.metadata['data_dir'] = parent.metadata['data_dir'] - - # replace the display name with an optional parameter passed in from the caller - if display_name is not None: - new_item.metadata['display_name'] = display_name - - store.update_metadata(new_item.location.url(), new_item.own_metadata) - - if new_item.location.category not in DETACHED_CATEGORIES: - store.update_children(parent_location, parent.definition.get('children', []) + [new_item.location.url()]) - - return new_item - -class Item: - pass - -class ItemFactory(XModuleItemFactory): - FACTORY_FOR = Item - - parent_location = 'i4x://MITx/999/course/Robot_Super_Course' - template = 'i4x://edx/templates/chapter/Empty' - display_name = 'Section One' \ No newline at end of file diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 085ecebff1..0727cb68dd 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -9,23 +9,26 @@ from path import path from tempfile import mkdtemp import json from fs.osfs import OSFS - +import copy from student.models import Registration from django.contrib.auth.models import User -import xmodule.modulestore.django -from xmodule.modulestore.xml_importer import import_from_xml -import copy -from factories import * +from cms.djangoapps.contentstore.utils import get_modulestore +from xmodule.modulestore import Location from xmodule.modulestore.store_utilities import clone_course from xmodule.modulestore.store_utilities import delete_course -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.django import modulestore, _MODULESTORES from xmodule.contentstore.django import contentstore -from xmodule.course_module import CourseDescriptor +from xmodule.templates import update_templates from xmodule.modulestore.xml_exporter import export_to_xml -from cms.djangoapps.contentstore.utils import get_modulestore +from xmodule.modulestore.xml_importer import import_from_xml + from xmodule.capa_module import CapaDescriptor +from xmodule.course_module import CourseDescriptor +from xmodule.seq_module import SequenceDescriptor + +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory def parse_json(response): """Parse response, which is assumed to be json""" @@ -217,9 +220,9 @@ class ContentStoreTest(TestCase): # (though it shouldn't), do this manually # from the bash shell to drop it: # $ mongo test_xmodule --eval "db.dropDatabase()" - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() - xmodule.templates.update_templates() + _MODULESTORES = {} + modulestore().collection.drop() + update_templates() self.client = Client() self.client.login(username=uname, password=password) @@ -237,8 +240,8 @@ class ContentStoreTest(TestCase): # cms/djangoapps/contentstore/__init__.py # update_templates() will try to update the templates # via upsert and it sometimes seems to be messing things up. - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() + _MODULESTORES = {} + modulestore().collection.drop() def test_create_course(self): """Test new course creation - happy path""" @@ -288,12 +291,12 @@ class ContentStoreTest(TestCase): def test_course_factory(self): course = CourseFactory.create() - self.assertIsInstance(course, xmodule.course_module.CourseDescriptor) + self.assertIsInstance(course, CourseDescriptor) def test_item_factory(self): course = CourseFactory.create() item = ItemFactory.create(parent_location=course.location) - self.assertIsInstance(item, xmodule.seq_module.SequenceDescriptor) + self.assertIsInstance(item, SequenceDescriptor) def test_course_index_view_with_course(self): """Test viewing the index page with an existing course""" diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py new file mode 100644 index 0000000000..987dbca09b --- /dev/null +++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py @@ -0,0 +1,117 @@ +from factory import Factory +# from datetime import datetime +from time import gmtime +from uuid import uuid4 +from xmodule.modulestore import Location +from xmodule.modulestore.django import modulestore +from xmodule.timeparse import stringify_time + +def XMODULE_COURSE_CREATION(class_to_create, **kwargs): + return XModuleCourseFactory._create(class_to_create, **kwargs) + +def XMODULE_ITEM_CREATION(class_to_create, **kwargs): + return XModuleItemFactory._create(class_to_create, **kwargs) + +class XModuleCourseFactory(Factory): + """ + Factory for XModule courses. + """ + + ABSTRACT_FACTORY = True + _creation_function = (XMODULE_COURSE_CREATION,) + + @classmethod + def _create(cls, target_class, *args, **kwargs): + + template = Location('i4x', 'edx', 'templates', 'course', 'Empty') + org = kwargs.get('org') + number = kwargs.get('number') + display_name = kwargs.get('display_name') + location = Location('i4x', org, number, + 'course', Location.clean(display_name)) + + store = modulestore('direct') + + # Write the data to the mongo datastore + new_course = store.clone_item(template, location) + + # This metadata code was copied from cms/djangoapps/contentstore/views.py + if display_name is not None: + new_course.metadata['display_name'] = display_name + + new_course.metadata['data_dir'] = uuid4().hex + new_course.metadata['start'] = stringify_time(gmtime()) + new_course.tabs = [{"type": "courseware"}, + {"type": "course_info", "name": "Course Info"}, + {"type": "discussion", "name": "Discussion"}, + {"type": "wiki", "name": "Wiki"}, + {"type": "progress", "name": "Progress"}] + + # Update the data in the mongo datastore + store.update_metadata(new_course.location.url(), new_course.own_metadata) + + return new_course + +class Course: + pass + +class CourseFactory(XModuleCourseFactory): + FACTORY_FOR = Course + + template = 'i4x://edx/templates/course/Empty' + org = 'MITx' + number = '999' + display_name = 'Robot Super Course' + +class XModuleItemFactory(Factory): + """ + Factory for XModule items. + """ + + ABSTRACT_FACTORY = True + _creation_function = (XMODULE_ITEM_CREATION,) + + @classmethod + def _create(cls, target_class, *args, **kwargs): + """ + kwargs must include parent_location, template. Can contain display_name + target_class is ignored + """ + + DETACHED_CATEGORIES = ['about', 'static_tab', 'course_info'] + + parent_location = Location(kwargs.get('parent_location')) + template = Location(kwargs.get('template')) + display_name = kwargs.get('display_name') + + store = modulestore('direct') + + # This code was based off that in cms/djangoapps/contentstore/views.py + parent = store.get_item(parent_location) + dest_location = parent_location._replace(category=template.category, name=uuid4().hex) + + new_item = store.clone_item(template, dest_location) + + # TODO: This needs to be deleted when we have proper storage for static content + new_item.metadata['data_dir'] = parent.metadata['data_dir'] + + # replace the display name with an optional parameter passed in from the caller + if display_name is not None: + new_item.metadata['display_name'] = display_name + + store.update_metadata(new_item.location.url(), new_item.own_metadata) + + if new_item.location.category not in DETACHED_CATEGORIES: + store.update_children(parent_location, parent.definition.get('children', []) + [new_item.location.url()]) + + return new_item + +class Item: + pass + +class ItemFactory(XModuleItemFactory): + FACTORY_FOR = Item + + parent_location = 'i4x://MITx/999/course/Robot_Super_Course' + template = 'i4x://edx/templates/chapter/Empty' + display_name = 'Section One' \ No newline at end of file From 5a6b03920806fa83575238930cd9eb7bdc2a2abe Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Sat, 2 Feb 2013 22:29:40 -0500 Subject: [PATCH 0673/1392] Reorganize the CmsTestCase subclass --- cms/djangoapps/contentstore/tests/tests.py | 23 ++-------------- cms/djangoapps/contentstore/tests/utils.py | 32 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 21 deletions(-) create mode 100644 cms/djangoapps/contentstore/tests/utils.py diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 0727cb68dd..f41492a56e 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -29,6 +29,7 @@ from xmodule.course_module import CourseDescriptor from xmodule.seq_module import SequenceDescriptor from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from .utils import CmsTestCase def parse_json(response): """Parse response, which is assumed to be json""" @@ -196,7 +197,7 @@ TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data' TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') @override_settings(MODULESTORE=TEST_DATA_MODULESTORE) -class ContentStoreTest(TestCase): +class ContentStoreTest(CmsTestCase): def setUp(self): uname = 'testuser' @@ -213,17 +214,6 @@ class ContentStoreTest(TestCase): self.user.is_staff = True self.user.save() - # Flush and initialize the module store - # It needs the templates because it creates new records - # by cloning from the template. - # Note that if your test module gets in some weird state - # (though it shouldn't), do this manually - # from the bash shell to drop it: - # $ mongo test_xmodule --eval "db.dropDatabase()" - _MODULESTORES = {} - modulestore().collection.drop() - update_templates() - self.client = Client() self.client.login(username=uname, password=password) @@ -234,15 +224,6 @@ class ContentStoreTest(TestCase): 'display_name': 'Robot Super Course', } - def tearDown(self): - # Make sure you flush out the test modulestore after the end - # of the last test because otherwise on the next run - # cms/djangoapps/contentstore/__init__.py - # update_templates() will try to update the templates - # via upsert and it sometimes seems to be messing things up. - _MODULESTORES = {} - modulestore().collection.drop() - def test_create_course(self): """Test new course creation - happy path""" resp = self.client.post(reverse('create_new_course'), self.course_data) diff --git a/cms/djangoapps/contentstore/tests/utils.py b/cms/djangoapps/contentstore/tests/utils.py new file mode 100644 index 0000000000..c800ee936c --- /dev/null +++ b/cms/djangoapps/contentstore/tests/utils.py @@ -0,0 +1,32 @@ +from django.test import TestCase +from xmodule.modulestore.django import modulestore, _MODULESTORES +from xmodule.templates import update_templates + +# Subclass TestCase and use to initialize the contentstore +class CmsTestCase(TestCase): + """ Subclass for any test case that uses the mongodb + module store. This clears it out before running the TestCase + and reinitilizes it with the templates afterwards. """ + + def _pre_setup(self): + super(CmsTestCase, self)._pre_setup() + # Flush and initialize the module store + # It needs the templates because it creates new records + # by cloning from the template. + # Note that if your test module gets in some weird state + # (though it shouldn't), do this manually + # from the bash shell to drop it: + # $ mongo test_xmodule --eval "db.dropDatabase()" + _MODULESTORES = {} + modulestore().collection.drop() + update_templates() + + def _post_teardown(self): + # Make sure you flush out the test modulestore after the end + # of the last test because otherwise on the next run + # cms/djangoapps/contentstore/__init__.py + # update_templates() will try to update the templates + # via upsert and it sometimes seems to be messing things up. + _MODULESTORES = {} + modulestore().collection.drop() + super(CmsTestCase, self)._post_teardown() \ No newline at end of file From 3324615270cee928055148a64b579dbb06e43129 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Mon, 4 Feb 2013 08:26:21 -0500 Subject: [PATCH 0674/1392] Reorganize test cases --- .../contentstore/tests/test_contentstore.py | 334 +++++++++++++++--- cms/djangoapps/contentstore/tests/tests.py | 333 ----------------- 2 files changed, 293 insertions(+), 374 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index cc37d201a1..a417418410 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -13,46 +13,16 @@ from mock import Mock import xmodule.modulestore.django from factories import * - -# Subclass TestCase and use to initialize the contentstore -class CmsTestCase(TestCase): - - def _pre_setup(self): - super(CmsTestCase, self)._pre_setup() - # Flush and initialize the module store - # It needs the templates because it creates new records - # by cloning from the template. - # Note that if your test module gets in some weird state - # (though it shouldn't), do this manually - # from the bash shell to drop it: - # $ mongo test_xmodule --eval "db.dropDatabase()" - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() - xmodule.templates.update_templates() - - def _post_teardown(self): - # Make sure you flush out the test modulestore after the end - # of the last test because otherwise on the next run - # cms/djangoapps/contentstore/__init__.py - # update_templates() will try to update the templates - # via upsert and it sometimes seems to be messing things up. - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() - super(CmsTestCase, self)._post_teardown() - -def parse_json(response): - """Parse response, which is assumed to be json""" - return json.loads(response.content) +from utils import CmsTestCase TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') @override_settings(MODULESTORE=TEST_DATA_MODULESTORE) -class NewContentStoreTest(CmsTestCase): +class ContentStoreTest(CmsTestCase): def setUp(self): - # super(NewContentStoreTest, self).setUp() uname = 'testuser' email = 'test+courses@edx.org' password = 'foo' @@ -67,11 +37,6 @@ class NewContentStoreTest(CmsTestCase): self.user.is_staff = True self.user.save() - # user = UserFactory(username=uname, email=email, password=password, - # is_staff=True, is_active=True) - # user.is_authenticated= Mock(return_value=True) - - self.client = Client() self.client.login(username=uname, password=password) @@ -82,13 +47,300 @@ class NewContentStoreTest(CmsTestCase): 'display_name': 'Robot Super Course', } - def tearDown(self): - # super(NewContentStoreTest, self).tearDown() - pass - def test_create_course(self): """Test new course creation - happy path""" resp = self.client.post(reverse('create_new_course'), self.course_data) self.assertEqual(resp.status_code, 200) data = parse_json(resp) self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') + + def test_create_course_duplicate_course(self): + """Test new course creation - error path""" + resp = self.client.post(reverse('create_new_course'), self.course_data) + resp = self.client.post(reverse('create_new_course'), self.course_data) + data = parse_json(resp) + self.assertEqual(resp.status_code, 200) + self.assertEqual(data['ErrMsg'], 'There is already a course defined with this name.') + + def test_create_course_duplicate_number(self): + """Test new course creation - error path""" + resp = self.client.post(reverse('create_new_course'), self.course_data) + self.course_data['display_name'] = 'Robot Super Course Two' + + resp = self.client.post(reverse('create_new_course'), self.course_data) + data = parse_json(resp) + + self.assertEqual(resp.status_code, 200) + self.assertEqual(data['ErrMsg'], + 'There is already a course defined with the same organization and course number.') + + def test_create_course_with_bad_organization(self): + """Test new course creation - error path for bad organization name""" + self.course_data['org'] = 'University of California, Berkeley' + resp = self.client.post(reverse('create_new_course'), self.course_data) + data = parse_json(resp) + + self.assertEqual(resp.status_code, 200) + self.assertEqual(data['ErrMsg'], + "Unable to create course 'Robot Super Course'.\n\nInvalid characters in 'University of California, Berkeley'.") + + def test_course_index_view_with_no_courses(self): + """Test viewing the index page with no courses""" + # Create a course so there is something to view + resp = self.client.get(reverse('index')) + self.assertContains(resp, + '

    My Courses

    ', + status_code=200, + html=True) + + def test_course_factory(self): + course = CourseFactory.create() + self.assertIsInstance(course, CourseDescriptor) + + def test_item_factory(self): + course = CourseFactory.create() + item = ItemFactory.create(parent_location=course.location) + self.assertIsInstance(item, SequenceDescriptor) + + def test_course_index_view_with_course(self): + """Test viewing the index page with an existing course""" + CourseFactory.create(display_name='Robot Super Educational Course') + resp = self.client.get(reverse('index')) + self.assertContains(resp, + 'Robot Super Educational Course', + status_code=200, + html=True) + + def test_course_overview_view_with_course(self): + """Test viewing the course overview page with an existing course""" + CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') + + data = { + 'org': 'MITx', + 'course': '999', + 'name': Location.clean('Robot Super Course'), + } + + resp = self.client.get(reverse('course_index', kwargs=data)) + self.assertContains(resp, + 'Robot Super Course', + status_code=200, + html=True) + + def test_clone_item(self): + """Test cloning an item. E.g. creating a new section""" + CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') + + section_data = { + 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', + 'template' : 'i4x://edx/templates/chapter/Empty', + 'display_name': 'Section One', + } + + resp = self.client.post(reverse('clone_item'), section_data) + + self.assertEqual(resp.status_code, 200) + data = parse_json(resp) + self.assertRegexpMatches(data['id'], + '^i4x:\/\/MITx\/999\/chapter\/([0-9]|[a-f]){32}$') + + def check_edit_unit(self, test_course_name): + import_from_xml(modulestore(), 'common/test/data/', [test_course_name]) + + for descriptor in modulestore().get_items(Location(None, None, 'vertical', None, None)): + print "Checking ", descriptor.location.url() + print descriptor.__class__, descriptor.location + resp = self.client.get(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) + self.assertEqual(resp.status_code, 200) + + def test_edit_unit_toy(self): + self.check_edit_unit('toy') + + def test_edit_unit_full(self): + self.check_edit_unit('full') + + def test_static_tab_reordering(self): + import_from_xml(modulestore(), 'common/test/data/', ['full']) + + ms = modulestore('direct') + course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None])) + + # reverse the ordering + reverse_tabs = [] + for tab in course.tabs: + if tab['type'] == 'static_tab': + reverse_tabs.insert(0, 'i4x://edX/full/static_tab/{0}'.format(tab['url_slug'])) + + resp = self.client.post(reverse('reorder_static_tabs'), json.dumps({'tabs':reverse_tabs}), "application/json") + + course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None])) + + # compare to make sure that the tabs information is in the expected order after the server call + course_tabs = [] + for tab in course.tabs: + if tab['type'] == 'static_tab': + course_tabs.append('i4x://edX/full/static_tab/{0}'.format(tab['url_slug'])) + + self.assertEqual(reverse_tabs, course_tabs) + + + + + def test_about_overrides(self): + ''' + This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html + while there is a base definition in /about/effort.html + ''' + import_from_xml(modulestore(), 'common/test/data/', ['full']) + ms = modulestore('direct') + effort = ms.get_item(Location(['i4x','edX','full','about','effort', None])) + self.assertEqual(effort.definition['data'],'6 hours') + + # this one should be in a non-override folder + effort = ms.get_item(Location(['i4x','edX','full','about','end_date', None])) + self.assertEqual(effort.definition['data'],'TBD') + + def test_remove_hide_progress_tab(self): + import_from_xml(modulestore(), 'common/test/data/', ['full']) + + ms = modulestore('direct') + cs = contentstore() + + source_location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') + course = ms.get_item(source_location) + self.assertNotIn('hide_progress_tab', course.metadata) + + + def test_clone_course(self): + import_from_xml(modulestore(), 'common/test/data/', ['full']) + + resp = self.client.post(reverse('create_new_course'), self.course_data) + self.assertEqual(resp.status_code, 200) + data = parse_json(resp) + self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') + + ms = modulestore('direct') + cs = contentstore() + + source_location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') + dest_location = CourseDescriptor.id_to_location('MITx/999/Robot_Super_Course') + + clone_course(ms, cs, source_location, dest_location) + + # now loop through all the units in the course and verify that the clone can render them, which + # means the objects are at least present + items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) + self.assertGreater(len(items), 0) + clone_items = ms.get_items(Location(['i4x', 'MITx','999','vertical', None])) + self.assertGreater(len(clone_items), 0) + for descriptor in items: + new_loc = descriptor.location._replace(org = 'MITx', course='999') + print "Checking {0} should now also be at {1}".format(descriptor.location.url(), new_loc.url()) + resp = self.client.get(reverse('edit_unit', kwargs={'location': new_loc.url()})) + self.assertEqual(resp.status_code, 200) + + def test_delete_course(self): + import_from_xml(modulestore(), 'common/test/data/', ['full']) + + ms = modulestore('direct') + cs = contentstore() + + location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') + + delete_course(ms, cs, location) + + items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) + self.assertEqual(len(items), 0) + + def verify_content_existence(self, modulestore, root_dir, location, dirname, category_name, filename_suffix=''): + fs = OSFS(root_dir / 'test_export') + self.assertTrue(fs.exists(dirname)) + + query_loc = Location('i4x', location.org, location.course, category_name, None) + items = modulestore.get_items(query_loc) + + for item in items: + fs = OSFS(root_dir / ('test_export/' + dirname)) + self.assertTrue(fs.exists(item.location.name + filename_suffix)) + + def test_export_course(self): + ms = modulestore('direct') + cs = contentstore() + + import_from_xml(ms, 'common/test/data/', ['full']) + location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') + + root_dir = path(mkdtemp()) + + print 'Exporting to tempdir = {0}'.format(root_dir) + + # export out to a tempdir + export_to_xml(ms, cs, location, root_dir, 'test_export') + + # check for static tabs + self.verify_content_existence(ms, root_dir, location, 'tabs', 'static_tab', '.html') + + # check for custom_tags + self.verify_content_existence(ms, root_dir, location, 'info', 'course_info', '.html') + + # check for custom_tags + self.verify_content_existence(ms, root_dir, location, 'custom_tags', 'custom_tag_template') + + + # remove old course + delete_course(ms, cs, location) + + # reimport + import_from_xml(ms, root_dir, ['test_export']) + + items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) + self.assertGreater(len(items), 0) + for descriptor in items: + print "Checking {0}....".format(descriptor.location.url()) + resp = self.client.get(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) + self.assertEqual(resp.status_code, 200) + + shutil.rmtree(root_dir) + + + def test_course_handouts_rewrites(self): + ms = modulestore('direct') + cs = contentstore() + + # import a test course + import_from_xml(ms, 'common/test/data/', ['full']) + + handout_location= Location(['i4x', 'edX', 'full', 'course_info', 'handouts']) + + # get module info + resp = self.client.get(reverse('module_info', kwargs={'module_location': handout_location})) + + # make sure we got a successful response + self.assertEqual(resp.status_code, 200) + + # check that /static/ has been converted to the full path + # note, we know the link it should be because that's what in the 'full' course in the test data + self.assertContains(resp, '/c4x/edX/full/asset/handouts_schematic_tutorial.pdf') + + + def test_capa_module(self): + """Test that a problem treats markdown specially.""" + CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') + + problem_data = { + 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', + 'template' : 'i4x://edx/templates/problem/Empty' + } + + resp = self.client.post(reverse('clone_item'), problem_data) + + self.assertEqual(resp.status_code, 200) + payload = parse_json(resp) + problem_loc = payload['id'] + problem = get_modulestore(problem_loc).get_item(problem_loc) + # should be a CapaDescriptor + self.assertIsInstance(problem, CapaDescriptor, "New problem is not a CapaDescriptor") + context = problem.get_context() + self.assertIn('markdown', context, "markdown is missing from context") + self.assertIn('markdown', problem.metadata, "markdown is missing from metadata") + self.assertNotIn('markdown', problem.editable_metadata_fields, "Markdown slipped into the editable metadata fields") diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index f41492a56e..8c8ee07264 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -191,336 +191,3 @@ class AuthTestCase(ContentStoreTestCase): self.assertEqual(resp.status_code, 302) # Logged in should work. - -TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) -TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') -TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') - -@override_settings(MODULESTORE=TEST_DATA_MODULESTORE) -class ContentStoreTest(CmsTestCase): - - def setUp(self): - uname = 'testuser' - email = 'test+courses@edx.org' - password = 'foo' - - # Create the use so we can log them in. - self.user = User.objects.create_user(uname, email, password) - - # Note that we do not actually need to do anything - # for registration if we directly mark them active. - self.user.is_active = True - # Staff has access to view all courses - self.user.is_staff = True - self.user.save() - - self.client = Client() - self.client.login(username=uname, password=password) - - self.course_data = { - 'template': 'i4x://edx/templates/course/Empty', - 'org': 'MITx', - 'number': '999', - 'display_name': 'Robot Super Course', - } - - def test_create_course(self): - """Test new course creation - happy path""" - resp = self.client.post(reverse('create_new_course'), self.course_data) - self.assertEqual(resp.status_code, 200) - data = parse_json(resp) - self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') - - def test_create_course_duplicate_course(self): - """Test new course creation - error path""" - resp = self.client.post(reverse('create_new_course'), self.course_data) - resp = self.client.post(reverse('create_new_course'), self.course_data) - data = parse_json(resp) - self.assertEqual(resp.status_code, 200) - self.assertEqual(data['ErrMsg'], 'There is already a course defined with this name.') - - def test_create_course_duplicate_number(self): - """Test new course creation - error path""" - resp = self.client.post(reverse('create_new_course'), self.course_data) - self.course_data['display_name'] = 'Robot Super Course Two' - - resp = self.client.post(reverse('create_new_course'), self.course_data) - data = parse_json(resp) - - self.assertEqual(resp.status_code, 200) - self.assertEqual(data['ErrMsg'], - 'There is already a course defined with the same organization and course number.') - - def test_create_course_with_bad_organization(self): - """Test new course creation - error path for bad organization name""" - self.course_data['org'] = 'University of California, Berkeley' - resp = self.client.post(reverse('create_new_course'), self.course_data) - data = parse_json(resp) - - self.assertEqual(resp.status_code, 200) - self.assertEqual(data['ErrMsg'], - "Unable to create course 'Robot Super Course'.\n\nInvalid characters in 'University of California, Berkeley'.") - - def test_course_index_view_with_no_courses(self): - """Test viewing the index page with no courses""" - # Create a course so there is something to view - resp = self.client.get(reverse('index')) - self.assertContains(resp, - '

    My Courses

    ', - status_code=200, - html=True) - - def test_course_factory(self): - course = CourseFactory.create() - self.assertIsInstance(course, CourseDescriptor) - - def test_item_factory(self): - course = CourseFactory.create() - item = ItemFactory.create(parent_location=course.location) - self.assertIsInstance(item, SequenceDescriptor) - - def test_course_index_view_with_course(self): - """Test viewing the index page with an existing course""" - CourseFactory.create(display_name='Robot Super Educational Course') - resp = self.client.get(reverse('index')) - self.assertContains(resp, - 'Robot Super Educational Course', - status_code=200, - html=True) - - def test_course_overview_view_with_course(self): - """Test viewing the course overview page with an existing course""" - CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') - - data = { - 'org': 'MITx', - 'course': '999', - 'name': Location.clean('Robot Super Course'), - } - - resp = self.client.get(reverse('course_index', kwargs=data)) - self.assertContains(resp, - 'Robot Super Course', - status_code=200, - html=True) - - def test_clone_item(self): - """Test cloning an item. E.g. creating a new section""" - CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') - - section_data = { - 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', - 'template' : 'i4x://edx/templates/chapter/Empty', - 'display_name': 'Section One', - } - - resp = self.client.post(reverse('clone_item'), section_data) - - self.assertEqual(resp.status_code, 200) - data = parse_json(resp) - self.assertRegexpMatches(data['id'], - '^i4x:\/\/MITx\/999\/chapter\/([0-9]|[a-f]){32}$') - - def check_edit_unit(self, test_course_name): - import_from_xml(modulestore(), 'common/test/data/', [test_course_name]) - - for descriptor in modulestore().get_items(Location(None, None, 'vertical', None, None)): - print "Checking ", descriptor.location.url() - print descriptor.__class__, descriptor.location - resp = self.client.get(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) - self.assertEqual(resp.status_code, 200) - - def test_edit_unit_toy(self): - self.check_edit_unit('toy') - - def test_edit_unit_full(self): - self.check_edit_unit('full') - - def test_static_tab_reordering(self): - import_from_xml(modulestore(), 'common/test/data/', ['full']) - - ms = modulestore('direct') - course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None])) - - # reverse the ordering - reverse_tabs = [] - for tab in course.tabs: - if tab['type'] == 'static_tab': - reverse_tabs.insert(0, 'i4x://edX/full/static_tab/{0}'.format(tab['url_slug'])) - - resp = self.client.post(reverse('reorder_static_tabs'), json.dumps({'tabs':reverse_tabs}), "application/json") - - course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None])) - - # compare to make sure that the tabs information is in the expected order after the server call - course_tabs = [] - for tab in course.tabs: - if tab['type'] == 'static_tab': - course_tabs.append('i4x://edX/full/static_tab/{0}'.format(tab['url_slug'])) - - self.assertEqual(reverse_tabs, course_tabs) - - - - - def test_about_overrides(self): - ''' - This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html - while there is a base definition in /about/effort.html - ''' - import_from_xml(modulestore(), 'common/test/data/', ['full']) - ms = modulestore('direct') - effort = ms.get_item(Location(['i4x','edX','full','about','effort', None])) - self.assertEqual(effort.definition['data'],'6 hours') - - # this one should be in a non-override folder - effort = ms.get_item(Location(['i4x','edX','full','about','end_date', None])) - self.assertEqual(effort.definition['data'],'TBD') - - def test_remove_hide_progress_tab(self): - import_from_xml(modulestore(), 'common/test/data/', ['full']) - - ms = modulestore('direct') - cs = contentstore() - - source_location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') - course = ms.get_item(source_location) - self.assertNotIn('hide_progress_tab', course.metadata) - - - def test_clone_course(self): - import_from_xml(modulestore(), 'common/test/data/', ['full']) - - resp = self.client.post(reverse('create_new_course'), self.course_data) - self.assertEqual(resp.status_code, 200) - data = parse_json(resp) - self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') - - ms = modulestore('direct') - cs = contentstore() - - source_location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') - dest_location = CourseDescriptor.id_to_location('MITx/999/Robot_Super_Course') - - clone_course(ms, cs, source_location, dest_location) - - # now loop through all the units in the course and verify that the clone can render them, which - # means the objects are at least present - items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) - self.assertGreater(len(items), 0) - clone_items = ms.get_items(Location(['i4x', 'MITx','999','vertical', None])) - self.assertGreater(len(clone_items), 0) - for descriptor in items: - new_loc = descriptor.location._replace(org = 'MITx', course='999') - print "Checking {0} should now also be at {1}".format(descriptor.location.url(), new_loc.url()) - resp = self.client.get(reverse('edit_unit', kwargs={'location': new_loc.url()})) - self.assertEqual(resp.status_code, 200) - - def test_delete_course(self): - import_from_xml(modulestore(), 'common/test/data/', ['full']) - - ms = modulestore('direct') - cs = contentstore() - - location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') - - delete_course(ms, cs, location) - - items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) - self.assertEqual(len(items), 0) - - def verify_content_existence(self, modulestore, root_dir, location, dirname, category_name, filename_suffix=''): - fs = OSFS(root_dir / 'test_export') - self.assertTrue(fs.exists(dirname)) - - query_loc = Location('i4x', location.org, location.course, category_name, None) - items = modulestore.get_items(query_loc) - - for item in items: - fs = OSFS(root_dir / ('test_export/' + dirname)) - self.assertTrue(fs.exists(item.location.name + filename_suffix)) - - def test_export_course(self): - ms = modulestore('direct') - cs = contentstore() - - import_from_xml(ms, 'common/test/data/', ['full']) - location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') - - root_dir = path(mkdtemp()) - - print 'Exporting to tempdir = {0}'.format(root_dir) - - # export out to a tempdir - export_to_xml(ms, cs, location, root_dir, 'test_export') - - # check for static tabs - self.verify_content_existence(ms, root_dir, location, 'tabs', 'static_tab', '.html') - - # check for custom_tags - self.verify_content_existence(ms, root_dir, location, 'info', 'course_info', '.html') - - # check for custom_tags - self.verify_content_existence(ms, root_dir, location, 'custom_tags', 'custom_tag_template') - - - # remove old course - delete_course(ms, cs, location) - - # reimport - import_from_xml(ms, root_dir, ['test_export']) - - items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) - self.assertGreater(len(items), 0) - for descriptor in items: - print "Checking {0}....".format(descriptor.location.url()) - resp = self.client.get(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) - self.assertEqual(resp.status_code, 200) - - shutil.rmtree(root_dir) - - - def test_course_handouts_rewrites(self): - ms = modulestore('direct') - cs = contentstore() - - # import a test course - import_from_xml(ms, 'common/test/data/', ['full']) - - handout_location= Location(['i4x', 'edX', 'full', 'course_info', 'handouts']) - - # get module info - resp = self.client.get(reverse('module_info', kwargs={'module_location': handout_location})) - - # make sure we got a successful response - self.assertEqual(resp.status_code, 200) - - # check that /static/ has been converted to the full path - # note, we know the link it should be because that's what in the 'full' course in the test data - self.assertContains(resp, '/c4x/edX/full/asset/handouts_schematic_tutorial.pdf') - - def test_missing_static_content(self): - resp = self.client.get("/c4x/asd/asd/asd/asd") - self.assertEqual(resp.status_code, 404) - - def test_capa_module(self): - """Test that a problem treats markdown specially.""" - CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') - - problem_data = { - 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', - 'template' : 'i4x://edx/templates/problem/Empty' - } - - resp = self.client.post(reverse('clone_item'), problem_data) - - self.assertEqual(resp.status_code, 200) - payload = parse_json(resp) - problem_loc = payload['id'] - problem = get_modulestore(problem_loc).get_item(problem_loc) - # should be a CapaDescriptor - self.assertIsInstance(problem, CapaDescriptor, "New problem is not a CapaDescriptor") - context = problem.get_context() - self.assertIn('markdown', context, "markdown is missing from context") - self.assertIn('markdown', problem.metadata, "markdown is missing from metadata") - self.assertNotIn('markdown', problem.editable_metadata_fields, "Markdown slipped into the editable metadata fields") \ No newline at end of file From fde6d1ba1ca9c1f6005bacf032f3e0fd7fac8f89 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Mon, 4 Feb 2013 10:57:20 -0500 Subject: [PATCH 0675/1392] Refactor tests for cms contentstore. --- .../contentstore/tests/test_contentstore.py | 284 +++++++++++------- .../tests/test_course_settings.py | 71 ++--- cms/djangoapps/contentstore/tests/tests.py | 19 +- cms/djangoapps/contentstore/tests/utils.py | 40 ++- cms/djangoapps/contentstore/views.py | 12 +- .../xmodule/modulestore/tests/factories.py | 7 +- 6 files changed, 242 insertions(+), 191 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index a417418410..ce7d9e757c 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -1,27 +1,46 @@ import json import shutil -from django.test import TestCase from django.test.client import Client from override_settings import override_settings from django.conf import settings from django.core.urlresolvers import reverse from path import path +from tempfile import mkdtemp import json from fs.osfs import OSFS import copy from mock import Mock -import xmodule.modulestore.django -from factories import * -from utils import CmsTestCase +from student.models import Registration +from django.contrib.auth.models import User +from cms.djangoapps.contentstore.utils import get_modulestore + +from utils import ModuleStoreTestCase, parse_json +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory + +from xmodule.modulestore import Location +from xmodule.modulestore.store_utilities import clone_course +from xmodule.modulestore.store_utilities import delete_course +from xmodule.modulestore.django import modulestore, _MODULESTORES +from xmodule.contentstore.django import contentstore +from xmodule.templates import update_templates +from xmodule.modulestore.xml_exporter import export_to_xml +from xmodule.modulestore.xml_importer import import_from_xml + +from xmodule.capa_module import CapaDescriptor +from xmodule.course_module import CourseDescriptor +from xmodule.seq_module import SequenceDescriptor TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') @override_settings(MODULESTORE=TEST_DATA_MODULESTORE) -class ContentStoreTest(CmsTestCase): - +class ContentStoreToyCourseTest(ModuleStoreTestCase): + """ + Tests that rely on the toy courses. + TODO: refactor using CourseFactory so they do not. + """ def setUp(self): uname = 'testuser' email = 'test+courses@edx.org' @@ -40,109 +59,6 @@ class ContentStoreTest(CmsTestCase): self.client = Client() self.client.login(username=uname, password=password) - self.course_data = { - 'template': 'i4x://edx/templates/course/Empty', - 'org': 'MITx', - 'number': '999', - 'display_name': 'Robot Super Course', - } - - def test_create_course(self): - """Test new course creation - happy path""" - resp = self.client.post(reverse('create_new_course'), self.course_data) - self.assertEqual(resp.status_code, 200) - data = parse_json(resp) - self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') - - def test_create_course_duplicate_course(self): - """Test new course creation - error path""" - resp = self.client.post(reverse('create_new_course'), self.course_data) - resp = self.client.post(reverse('create_new_course'), self.course_data) - data = parse_json(resp) - self.assertEqual(resp.status_code, 200) - self.assertEqual(data['ErrMsg'], 'There is already a course defined with this name.') - - def test_create_course_duplicate_number(self): - """Test new course creation - error path""" - resp = self.client.post(reverse('create_new_course'), self.course_data) - self.course_data['display_name'] = 'Robot Super Course Two' - - resp = self.client.post(reverse('create_new_course'), self.course_data) - data = parse_json(resp) - - self.assertEqual(resp.status_code, 200) - self.assertEqual(data['ErrMsg'], - 'There is already a course defined with the same organization and course number.') - - def test_create_course_with_bad_organization(self): - """Test new course creation - error path for bad organization name""" - self.course_data['org'] = 'University of California, Berkeley' - resp = self.client.post(reverse('create_new_course'), self.course_data) - data = parse_json(resp) - - self.assertEqual(resp.status_code, 200) - self.assertEqual(data['ErrMsg'], - "Unable to create course 'Robot Super Course'.\n\nInvalid characters in 'University of California, Berkeley'.") - - def test_course_index_view_with_no_courses(self): - """Test viewing the index page with no courses""" - # Create a course so there is something to view - resp = self.client.get(reverse('index')) - self.assertContains(resp, - '

    My Courses

    ', - status_code=200, - html=True) - - def test_course_factory(self): - course = CourseFactory.create() - self.assertIsInstance(course, CourseDescriptor) - - def test_item_factory(self): - course = CourseFactory.create() - item = ItemFactory.create(parent_location=course.location) - self.assertIsInstance(item, SequenceDescriptor) - - def test_course_index_view_with_course(self): - """Test viewing the index page with an existing course""" - CourseFactory.create(display_name='Robot Super Educational Course') - resp = self.client.get(reverse('index')) - self.assertContains(resp, - 'Robot Super Educational Course', - status_code=200, - html=True) - - def test_course_overview_view_with_course(self): - """Test viewing the course overview page with an existing course""" - CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') - - data = { - 'org': 'MITx', - 'course': '999', - 'name': Location.clean('Robot Super Course'), - } - - resp = self.client.get(reverse('course_index', kwargs=data)) - self.assertContains(resp, - 'Robot Super Course', - status_code=200, - html=True) - - def test_clone_item(self): - """Test cloning an item. E.g. creating a new section""" - CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') - - section_data = { - 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', - 'template' : 'i4x://edx/templates/chapter/Empty', - 'display_name': 'Section One', - } - - resp = self.client.post(reverse('clone_item'), section_data) - - self.assertEqual(resp.status_code, 200) - data = parse_json(resp) - self.assertRegexpMatches(data['id'], - '^i4x:\/\/MITx\/999\/chapter\/([0-9]|[a-f]){32}$') def check_edit_unit(self, test_course_name): import_from_xml(modulestore(), 'common/test/data/', [test_course_name]) @@ -183,9 +99,6 @@ class ContentStoreTest(CmsTestCase): self.assertEqual(reverse_tabs, course_tabs) - - - def test_about_overrides(self): ''' This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html @@ -210,11 +123,18 @@ class ContentStoreTest(CmsTestCase): course = ms.get_item(source_location) self.assertNotIn('hide_progress_tab', course.metadata) - def test_clone_course(self): + + course_data = { + 'template': 'i4x://edx/templates/course/Empty', + 'org': 'MITx', + 'number': '999', + 'display_name': 'Robot Super Course', + } + import_from_xml(modulestore(), 'common/test/data/', ['full']) - resp = self.client.post(reverse('create_new_course'), self.course_data) + resp = self.client.post(reverse('create_new_course'), course_data) self.assertEqual(resp.status_code, 200) data = parse_json(resp) self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') @@ -302,7 +222,6 @@ class ContentStoreTest(CmsTestCase): shutil.rmtree(root_dir) - def test_course_handouts_rewrites(self): ms = modulestore('direct') cs = contentstore() @@ -323,6 +242,141 @@ class ContentStoreTest(CmsTestCase): self.assertContains(resp, '/c4x/edX/full/asset/handouts_schematic_tutorial.pdf') +class ContentStoreTest(ModuleStoreTestCase): + """ + Tests for the CMS ContentStore application. + """ + def setUp(self): + """ + These tests need a user in the DB so that the django Test Client + can log them in. + They inherit from the ModuleStoreTestCase class so that the mongodb collection + will be cleared out before each test case execution and deleted + afterwards. + """ + uname = 'testuser' + email = 'test+courses@edx.org' + password = 'foo' + + # Create the use so we can log them in. + self.user = User.objects.create_user(uname, email, password) + + # Note that we do not actually need to do anything + # for registration if we directly mark them active. + self.user.is_active = True + # Staff has access to view all courses + self.user.is_staff = True + self.user.save() + + self.client = Client() + self.client.login(username=uname, password=password) + + self.course_data = { + 'template': 'i4x://edx/templates/course/Empty', + 'org': 'MITx', + 'number': '999', + 'display_name': 'Robot Super Course', + } + + def test_create_course(self): + """Test new course creation - happy path""" + resp = self.client.post(reverse('create_new_course'), self.course_data) + self.assertEqual(resp.status_code, 200) + data = parse_json(resp) + self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') + + def test_create_course_duplicate_course(self): + """Test new course creation - error path""" + resp = self.client.post(reverse('create_new_course'), self.course_data) + resp = self.client.post(reverse('create_new_course'), self.course_data) + data = parse_json(resp) + self.assertEqual(resp.status_code, 200) + self.assertEqual(data['ErrMsg'], 'There is already a course defined with this name.') + + def test_create_course_duplicate_number(self): + """Test new course creation - error path""" + resp = self.client.post(reverse('create_new_course'), self.course_data) + self.course_data['display_name'] = 'Robot Super Course Two' + + resp = self.client.post(reverse('create_new_course'), self.course_data) + data = parse_json(resp) + + self.assertEqual(resp.status_code, 200) + self.assertEqual(data['ErrMsg'], + 'There is already a course defined with the same organization and course number.') + + def test_create_course_with_bad_organization(self): + """Test new course creation - error path for bad organization name""" + self.course_data['org'] = 'University of California, Berkeley' + resp = self.client.post(reverse('create_new_course'), self.course_data) + data = parse_json(resp) + + self.assertEqual(resp.status_code, 200) + self.assertEqual(data['ErrMsg'], + "Unable to create course 'Robot Super Course'.\n\nInvalid characters in 'University of California, Berkeley'.") + + def test_course_index_view_with_no_courses(self): + """Test viewing the index page with no courses""" + # Create a course so there is something to view + resp = self.client.get(reverse('index')) + self.assertContains(resp, + '

    My Courses

    ', + status_code=200, + html=True) + + def test_course_factory(self): + """Test that the course factory works correctly.""" + course = CourseFactory.create() + self.assertIsInstance(course, CourseDescriptor) + + def test_item_factory(self): + """Test that the item factory works correctly.""" + course = CourseFactory.create() + item = ItemFactory.create(parent_location=course.location) + self.assertIsInstance(item, SequenceDescriptor) + + def test_course_index_view_with_course(self): + """Test viewing the index page with an existing course""" + CourseFactory.create(display_name='Robot Super Educational Course') + resp = self.client.get(reverse('index')) + self.assertContains(resp, + 'Robot Super Educational Course', + status_code=200, + html=True) + + def test_course_overview_view_with_course(self): + """Test viewing the course overview page with an existing course""" + CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') + + data = { + 'org': 'MITx', + 'course': '999', + 'name': Location.clean('Robot Super Course'), + } + + resp = self.client.get(reverse('course_index', kwargs=data)) + self.assertContains(resp, + 'Robot Super Course', + status_code=200, + html=True) + + def test_clone_item(self): + """Test cloning an item. E.g. creating a new section""" + CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') + + section_data = { + 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', + 'template' : 'i4x://edx/templates/chapter/Empty', + 'display_name': 'Section One', + } + + resp = self.client.post(reverse('clone_item'), section_data) + + self.assertEqual(resp.status_code, 200) + data = parse_json(resp) + self.assertRegexpMatches(data['id'], + '^i4x:\/\/MITx\/999\/chapter\/([0-9]|[a-f]){32}$') + def test_capa_module(self): """Test that a problem treats markdown specially.""" CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index 74eff6e9cc..0191a97f6c 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -1,21 +1,27 @@ -from django.test.testcases import TestCase import datetime import time +import json +import calendar +import copy +from util import converters +from util.converters import jsdate_to_time + +from django.test.testcases import TestCase from django.contrib.auth.models import User -import xmodule from django.test.client import Client from django.core.urlresolvers import reverse -from xmodule.modulestore import Location -from cms.djangoapps.models.settings.course_details import CourseDetails,\ - CourseSettingsEncoder -import json -from util import converters -import calendar -from util.converters import jsdate_to_time from django.utils.timezone import UTC + +import xmodule +from xmodule.modulestore import Location +from cms.djangoapps.models.settings.course_details import (CourseDetails, + CourseSettingsEncoder) from cms.djangoapps.models.settings.course_grading import CourseGradingModel from cms.djangoapps.contentstore.utils import get_modulestore -import copy + +from utils import ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory + # YYYY-MM-DDThh:mm:ss.s+/-HH:MM class ConvertersTestCase(TestCase): @@ -36,8 +42,15 @@ class ConvertersTestCase(TestCase): self.compare_dates(converters.jsdate_to_time("2013-01-01T00:00:00"), converters.jsdate_to_time("2012-12-31T23:59:59"), datetime.timedelta(seconds=1)) -class CourseTestCase(TestCase): +class CourseTestCase(ModuleStoreTestCase): def setUp(self): + """ + These tests need a user in the DB so that the django Test Client + can log them in. + They inherit from the ModuleStoreTestCase class so that the mongodb collection + will be cleared out before each test case execution and deleted + afterwards. + """ uname = 'testuser' email = 'test+courses@edx.org' password = 'foo' @@ -52,36 +65,15 @@ class CourseTestCase(TestCase): self.user.is_staff = True self.user.save() - # Flush and initialize the module store - # It needs the templates because it creates new records - # by cloning from the template. - # Note that if your test module gets in some weird state - # (though it shouldn't), do this manually - # from the bash shell to drop it: - # $ mongo test_xmodule --eval "db.dropDatabase()" - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() - xmodule.templates.update_templates() - self.client = Client() self.client.login(username=uname, password=password) - self.course_data = { - 'template': 'i4x://edx/templates/course/Empty', - 'org': 'MITx', - 'number': '999', - 'display_name': 'Robot Super Course', - } - self.course_location = Location('i4x', 'MITx', '999', 'course', 'Robot_Super_Course') - self.create_course() - - def tearDown(self): - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() - - def create_course(self): - """Create new course""" - self.client.post(reverse('create_new_course'), self.course_data) + t='i4x://edx/templates/course/Empty' + o='MITx' + n='999' + dn='Robot Super Course' + self.course_location = Location('i4x', o, n, 'course', 'Robot_Super_Course') + CourseFactory.create(template=t, org=o, number=n, display_name=dn) class CourseDetailsTestCase(CourseTestCase): def test_virgin_fetch(self): @@ -145,7 +137,6 @@ class CourseDetailsViewTest(CourseTestCase): return datetime.isoformat("T") else: return None - def test_update_and_fetch(self): details = CourseDetails.fetch(self.course_location) @@ -271,5 +262,3 @@ class CourseGradingTest(CourseTestCase): test_grader.graders[1]['drop_count'] = test_grader.graders[1].get('drop_count') + 1 altered_grader = CourseGradingModel.update_grader_from_json(test_grader.course_location, test_grader.graders[1]) self.assertDictEqual(test_grader.graders[1], altered_grader, "drop_count[1] + 2") - - diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 8c8ee07264..1f09aee578 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -11,8 +11,6 @@ import json from fs.osfs import OSFS import copy -from student.models import Registration -from django.contrib.auth.models import User from cms.djangoapps.contentstore.utils import get_modulestore from xmodule.modulestore import Location @@ -29,22 +27,7 @@ from xmodule.course_module import CourseDescriptor from xmodule.seq_module import SequenceDescriptor from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -from .utils import CmsTestCase - -def parse_json(response): - """Parse response, which is assumed to be json""" - return json.loads(response.content) - - -def user(email): - """look up a user by email""" - return User.objects.get(email=email) - - -def registration(email): - """look up registration object by email""" - return Registration.objects.get(user__email=email) - +from utils import ModuleStoreTestCase, parse_json, user, registration class ContentStoreTestCase(TestCase): def _login(self, email, pw): diff --git a/cms/djangoapps/contentstore/tests/utils.py b/cms/djangoapps/contentstore/tests/utils.py index c800ee936c..bcf0471820 100644 --- a/cms/djangoapps/contentstore/tests/utils.py +++ b/cms/djangoapps/contentstore/tests/utils.py @@ -1,15 +1,20 @@ from django.test import TestCase -from xmodule.modulestore.django import modulestore, _MODULESTORES +import json + +from student.models import Registration +from django.contrib.auth.models import User + +import xmodule.modulestore.django from xmodule.templates import update_templates # Subclass TestCase and use to initialize the contentstore -class CmsTestCase(TestCase): +class ModuleStoreTestCase(TestCase): """ Subclass for any test case that uses the mongodb module store. This clears it out before running the TestCase and reinitilizes it with the templates afterwards. """ def _pre_setup(self): - super(CmsTestCase, self)._pre_setup() + super(ModuleStoreTestCase, self)._pre_setup() # Flush and initialize the module store # It needs the templates because it creates new records # by cloning from the template. @@ -17,16 +22,27 @@ class CmsTestCase(TestCase): # (though it shouldn't), do this manually # from the bash shell to drop it: # $ mongo test_xmodule --eval "db.dropDatabase()" - _MODULESTORES = {} - modulestore().collection.drop() + xmodule.modulestore.django._MODULESTORES = {} + xmodule.modulestore.django.modulestore().collection.drop() update_templates() def _post_teardown(self): # Make sure you flush out the test modulestore after the end - # of the last test because otherwise on the next run - # cms/djangoapps/contentstore/__init__.py - # update_templates() will try to update the templates - # via upsert and it sometimes seems to be messing things up. - _MODULESTORES = {} - modulestore().collection.drop() - super(CmsTestCase, self)._post_teardown() \ No newline at end of file + # of the last test so the collection will be deleted. + # Otherwise there will be lingering collections leftover + # from executing the tests. + xmodule.modulestore.django._MODULESTORES = {} + xmodule.modulestore.django.modulestore().collection.drop() + super(ModuleStoreTestCase, self)._post_teardown() + +def parse_json(response): + """Parse response, which is assumed to be json""" + return json.loads(response.content) + +def user(email): + """look up a user by email""" + return User.objects.get(email=email) + +def registration(email): + """look up registration object by email""" + return Registration.objects.get(user__email=email) diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index 7ebb2648ec..fb63cb34ed 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -1240,6 +1240,11 @@ def edge(request): @login_required @expect_json def create_new_course(request): + # This logic is repeated in xmodule/modulestore/tests/factories.py + # so if you change anything here, you need to also change it there. + # TODO: write a test that creates two courses, one with the factory and + # the other with this method, then compare them to make sure they are + # equivalent. template = Location(request.POST['template']) org = request.POST.get('org') number = request.POST.get('number') @@ -1289,8 +1294,11 @@ def initialize_course_tabs(course): # at least a list populated with the minimal times # @TODO: I don't like the fact that the presentation tier is away of these data related constraints, let's find a better # place for this. Also rather than using a simple list of dictionaries a nice class model would be helpful here - course.tabs = [{"type": "courseware"}, - {"type": "course_info", "name": "Course Info"}, + + # This logic is repeated in xmodule/modulestore/tests/factories.py + # so if you change anything here, you need to also change it there. + course.tabs = [{"type": "courseware"}, + {"type": "course_info", "name": "Course Info"}, {"type": "discussion", "name": "Discussion"}, {"type": "wiki", "name": "Wiki"}, {"type": "progress", "name": "Progress"}] diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py index 987dbca09b..b4264b30c9 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py @@ -1,5 +1,4 @@ from factory import Factory -# from datetime import datetime from time import gmtime from uuid import uuid4 from xmodule.modulestore import Location @@ -22,7 +21,8 @@ class XModuleCourseFactory(Factory): @classmethod def _create(cls, target_class, *args, **kwargs): - + # This logic was taken from the create_new_course method in + # cms/djangoapps/contentstore/views.py template = Location('i4x', 'edx', 'templates', 'course', 'Empty') org = kwargs.get('org') number = kwargs.get('number') @@ -41,6 +41,7 @@ class XModuleCourseFactory(Factory): new_course.metadata['data_dir'] = uuid4().hex new_course.metadata['start'] = stringify_time(gmtime()) + new_course.tabs = [{"type": "courseware"}, {"type": "course_info", "name": "Course Info"}, {"type": "discussion", "name": "Discussion"}, @@ -114,4 +115,4 @@ class ItemFactory(XModuleItemFactory): parent_location = 'i4x://MITx/999/course/Robot_Super_Course' template = 'i4x://edx/templates/chapter/Empty' - display_name = 'Section One' \ No newline at end of file + display_name = 'Section One' From abf4ad36f48f664d0a3f64afe4b5d59127bd2b28 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Mon, 4 Feb 2013 17:01:38 -0500 Subject: [PATCH 0676/1392] Move modulestore unique naming in tests from the settings.py file into the ModuleStoreTestCase class. --- .../contentstore/tests/test_core_caching.py | 6 +---- .../tests/test_course_settings.py | 2 +- .../contentstore/tests/test_utils.py | 2 +- cms/djangoapps/contentstore/tests/tests.py | 3 +-- cms/djangoapps/contentstore/tests/utils.py | 27 ++++++++++++++----- cms/envs/test.py | 6 +---- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_core_caching.py b/cms/djangoapps/contentstore/tests/test_core_caching.py index 0cb4a4930c..ed41e5cc64 100644 --- a/cms/djangoapps/contentstore/tests/test_core_caching.py +++ b/cms/djangoapps/contentstore/tests/test_core_caching.py @@ -1,7 +1,7 @@ -from django.test.testcases import TestCase from cache_toolbox.core import get_cached_content, set_cached_content, del_cached_content from xmodule.modulestore import Location from xmodule.contentstore.content import StaticContent +from django.test import TestCase class Content: def __init__(self, location, content): @@ -32,7 +32,3 @@ class CachingTestCase(TestCase): 'should not be stored in cache with unicodeLocation') self.assertEqual(None, get_cached_content(self.nonUnicodeLocation), 'should not be stored in cache with nonUnicodeLocation') - - - - diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index 0191a97f6c..f47733b32c 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -6,7 +6,6 @@ import copy from util import converters from util.converters import jsdate_to_time -from django.test.testcases import TestCase from django.contrib.auth.models import User from django.test.client import Client from django.core.urlresolvers import reverse @@ -19,6 +18,7 @@ from cms.djangoapps.models.settings.course_details import (CourseDetails, from cms.djangoapps.models.settings.course_grading import CourseGradingModel from cms.djangoapps.contentstore.utils import get_modulestore +from django.test import TestCase from utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory diff --git a/cms/djangoapps/contentstore/tests/test_utils.py b/cms/djangoapps/contentstore/tests/test_utils.py index 13f6189cc5..6811d64c12 100644 --- a/cms/djangoapps/contentstore/tests/test_utils.py +++ b/cms/djangoapps/contentstore/tests/test_utils.py @@ -1,6 +1,6 @@ -from django.test.testcases import TestCase from cms.djangoapps.contentstore import utils import mock +from django.test import TestCase class LMSLinksTestCase(TestCase): def about_page_test(self): diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 1f09aee578..df2e4dcc79 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -1,6 +1,5 @@ import json import shutil -from django.test import TestCase from django.test.client import Client from override_settings import override_settings from django.conf import settings @@ -29,7 +28,7 @@ from xmodule.seq_module import SequenceDescriptor from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from utils import ModuleStoreTestCase, parse_json, user, registration -class ContentStoreTestCase(TestCase): +class ContentStoreTestCase(ModuleStoreTestCase): def _login(self, email, pw): """Login. View should always return 200. The success/fail is in the returned json""" diff --git a/cms/djangoapps/contentstore/tests/utils.py b/cms/djangoapps/contentstore/tests/utils.py index bcf0471820..7ed2b33e63 100644 --- a/cms/djangoapps/contentstore/tests/utils.py +++ b/cms/djangoapps/contentstore/tests/utils.py @@ -1,5 +1,9 @@ -from django.test import TestCase import json +import copy +from time import time +from django.test import TestCase +from override_settings import override_settings +from django.conf import settings from student.models import Registration from django.contrib.auth.models import User @@ -7,14 +11,23 @@ from django.contrib.auth.models import User import xmodule.modulestore.django from xmodule.templates import update_templates -# Subclass TestCase and use to initialize the contentstore class ModuleStoreTestCase(TestCase): """ Subclass for any test case that uses the mongodb module store. This clears it out before running the TestCase and reinitilizes it with the templates afterwards. """ def _pre_setup(self): - super(ModuleStoreTestCase, self)._pre_setup() + super(ModuleStoreTestCase, self)._pre_setup() + + # Use the current seconds since epoch to differentiate + # the mongo collections on jenkins. + sec_since_epoch = '%s' % int(time()*100) + self.orig_MODULESTORE = copy.deepcopy(settings.MODULESTORE) + self.test_MODULESTORE = self.orig_MODULESTORE + self.test_MODULESTORE['default']['OPTIONS']['collection'] = 'modulestore_%s' % sec_since_epoch + self.test_MODULESTORE['direct']['OPTIONS']['collection'] = 'modulestore_%s' % sec_since_epoch + settings.MODULESTORE = self.test_MODULESTORE + # Flush and initialize the module store # It needs the templates because it creates new records # by cloning from the template. @@ -27,12 +40,14 @@ class ModuleStoreTestCase(TestCase): update_templates() def _post_teardown(self): - # Make sure you flush out the test modulestore after the end - # of the last test so the collection will be deleted. - # Otherwise there will be lingering collections leftover + # Make sure you flush out the modulestore. + # Drop the collection at the end of the test, + # otherwise there will be lingering collections leftover # from executing the tests. xmodule.modulestore.django._MODULESTORES = {} xmodule.modulestore.django.modulestore().collection.drop() + settings.MODULESTORE = self.orig_MODULESTORE + super(ModuleStoreTestCase, self)._post_teardown() def parse_json(response): diff --git a/cms/envs/test.py b/cms/envs/test.py index c22965d748..74c3e349a4 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -10,7 +10,6 @@ sessions. Assumes structure: from .common import * import os from path import path -from time import time # Nose Test Runner INSTALLED_APPS += ('django_nose',) @@ -39,14 +38,11 @@ STATICFILES_DIRS += [ if os.path.isdir(COMMON_TEST_DATA_ROOT / course_dir) ] -# Use the current seconds since epoch to differentiate -# the mongo collections on jenkins. -sec_since_epoch = '%s' % int(time()*100) modulestore_options = { 'default_class': 'xmodule.raw_module.RawDescriptor', 'host': 'localhost', 'db': 'test_xmodule', - 'collection': 'modulestore_%s' % sec_since_epoch, + 'collection': 'modulestore', 'fs_root': GITHUB_REPO_ROOT, 'render_template': 'mitxmako.shortcuts.render_to_string', } From 72023cb5d2f45a85f406225a64ce2b57d95e6b19 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Mon, 4 Feb 2013 17:15:54 -0500 Subject: [PATCH 0677/1392] Improve docstring wording for ModuleStoreTestCase class. --- cms/djangoapps/contentstore/tests/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/utils.py b/cms/djangoapps/contentstore/tests/utils.py index 7ed2b33e63..7fa5b76685 100644 --- a/cms/djangoapps/contentstore/tests/utils.py +++ b/cms/djangoapps/contentstore/tests/utils.py @@ -13,8 +13,9 @@ from xmodule.templates import update_templates class ModuleStoreTestCase(TestCase): """ Subclass for any test case that uses the mongodb - module store. This clears it out before running the TestCase - and reinitilizes it with the templates afterwards. """ + module store. This populates a uniquely named modulestore + collection with templates before running the TestCase + and drops it they are finished. """ def _pre_setup(self): super(ModuleStoreTestCase, self)._pre_setup() @@ -36,7 +37,6 @@ class ModuleStoreTestCase(TestCase): # from the bash shell to drop it: # $ mongo test_xmodule --eval "db.dropDatabase()" xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() update_templates() def _post_teardown(self): From 0b650122fb97139206e798f39a2daf7340fb769b Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 5 Feb 2013 07:39:53 -0500 Subject: [PATCH 0678/1392] Config changes to make pep8 autofixes easier --- .pep8 | 2 ++ rakefile | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .pep8 diff --git a/.pep8 b/.pep8 new file mode 100644 index 0000000000..25d0edbcb4 --- /dev/null +++ b/.pep8 @@ -0,0 +1,2 @@ +[pep8] +ignore=E501 \ No newline at end of file diff --git a/rakefile b/rakefile index bf80b4a87a..05652edbba 100644 --- a/rakefile +++ b/rakefile @@ -134,7 +134,7 @@ end desc "Run pep8 on all #{system} code" task "pep8_#{system}" => report_dir do - sh("pep8 --ignore=E501 #{system}/djangoapps #{system}/lib | tee #{report_dir}/pep8.report") + sh("pep8 #{system} | tee #{report_dir}/pep8.report") end task :pep8 => "pep8_#{system}" From 7fc4081495d7e825447c5889a52a3ef3293f754a Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Tue, 5 Feb 2013 11:17:40 -0500 Subject: [PATCH 0679/1392] Make pylint work on bare .py files from rake --- rakefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rakefile b/rakefile index 05652edbba..5647b5b13a 100644 --- a/rakefile +++ b/rakefile @@ -147,6 +147,11 @@ end pythonpath_prefix = "PYTHONPATH=#{File.dirname(app)}" end app = File.basename(app) + if app =~ /.py$/ + app = app.gsub('.py', '') + elsif app =~ /.pyc$/ + next + end sh("#{pythonpath_prefix} pylint --rcfile=.pylintrc -f parseable #{app} | tee #{report_dir}/#{app}.pylint.report") end end From cfae1cdf62fb74307b88bd091cd4ba927af6b1fc Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Wed, 6 Feb 2013 11:13:50 -0500 Subject: [PATCH 0680/1392] Pep8 autofixes --- cms/__init__.py | 1 - cms/djangoapps/auth/authz.py | 21 +- .../contentstore/course_info_model.py | 49 +++-- .../contentstore/features/common.py | 35 +++- .../contentstore/features/courses.py | 20 +- .../contentstore/features/factories.py | 5 +- .../contentstore/features/section.py | 26 ++- .../contentstore/features/signup.py | 6 +- .../features/studio-overview-togglesection.py | 31 ++- .../contentstore/features/subsection.py | 16 +- .../contentstore/management/commands/clone.py | 1 + .../management/commands/delete_course.py | 4 +- .../management/commands/prompt.py | 3 +- .../contentstore/module_info_model.py | 4 +- .../contentstore/tests/factories.py | 5 + .../contentstore/tests/test_contentstore.py | 65 +++--- .../contentstore/tests/test_core_caching.py | 2 + .../tests/test_course_settings.py | 87 ++++---- .../contentstore/tests/test_course_updates.py | 29 +-- .../contentstore/tests/test_utils.py | 5 +- cms/djangoapps/contentstore/tests/tests.py | 1 + cms/djangoapps/contentstore/tests/utils.py | 8 +- cms/djangoapps/contentstore/utils.py | 11 +- cms/djangoapps/contentstore/views.py | 131 +++++++----- .../models/settings/course_details.py | 50 ++--- .../models/settings/course_grading.py | 134 ++++++------ cms/envs/acceptance.py | 6 +- cms/envs/common.py | 6 +- cms/envs/dev.py | 4 +- cms/envs/dev_ike.py | 6 +- cms/envs/test.py | 8 +- cms/manage.py | 2 +- cms/urls.py | 4 +- common/djangoapps/cache_toolbox/core.py | 4 + common/djangoapps/contentserver/middleware.py | 2 +- common/djangoapps/course_groups/cohorts.py | 7 +- common/djangoapps/course_groups/models.py | 3 +- .../djangoapps/course_groups/tests/tests.py | 7 +- common/djangoapps/course_groups/views.py | 3 + common/djangoapps/external_auth/admin.py | 3 +- common/djangoapps/external_auth/models.py | 14 +- .../tests/test_openid_provider.py | 68 +++--- common/djangoapps/external_auth/views.py | 16 +- common/djangoapps/mitxmako/makoloader.py | 26 +-- common/djangoapps/mitxmako/template.py | 12 +- .../mitxmako/templatetag_helpers.py | 19 +- common/djangoapps/static_replace/__init__.py | 1 + .../test/test_static_replace.py | 1 + common/djangoapps/status/__init__.py | 1 - common/djangoapps/status/status.py | 1 + .../management/commands/6002exportusers.py | 2 +- .../management/commands/add_to_group.py | 1 + .../commands/create_random_users.py | 2 + .../management/commands/pearson_dump.py | 33 ++- .../management/commands/pearson_export_cdd.py | 6 +- .../commands/pearson_import_conf_zip.py | 1 - .../commands/pearson_make_tc_registration.py | 63 +++--- .../commands/pearson_make_tc_user.py | 54 ++--- .../management/commands/pearson_transfer.py | 20 +- .../management/commands/tests/test_pearson.py | 193 +++++++++--------- .../migrations/0020_add_test_center_user.py | 2 +- .../student/migrations/0021_remove_askbot.py | 2 +- ...ed__add_unique_courseenrollmentallowed_.py | 2 +- .../0023_add_test_center_registration.py | 2 +- .../migrations/0024_add_allow_certificate.py | 2 +- common/djangoapps/student/models.py | 32 +-- common/djangoapps/student/tests.py | 3 +- common/djangoapps/student/views.py | 57 ++++-- .../track/migrations/0001_initial.py | 2 +- ...t__chg_field_trackinglog_event_type__ch.py | 2 +- common/djangoapps/track/models.py | 17 +- common/djangoapps/track/views.py | 18 +- common/djangoapps/util/cache.py | 1 - common/djangoapps/util/converters.py | 9 +- common/djangoapps/util/json_request.py | 2 +- common/djangoapps/util/views.py | 1 + common/djangoapps/xmodule_modifiers.py | 26 +-- common/lib/capa/capa/calc.py | 4 +- common/lib/capa/capa/capa_problem.py | 6 +- common/lib/capa/capa/chem/__init__.py | 1 - common/lib/capa/capa/chem/chemcalc.py | 24 +-- common/lib/capa/capa/correctmap.py | 4 +- common/lib/capa/capa/customrender.py | 4 +- common/lib/capa/capa/inputtypes.py | 23 ++- common/lib/capa/capa/responsetypes.py | 8 +- common/lib/capa/capa/tests/__init__.py | 5 +- .../lib/capa/capa/tests/test_customrender.py | 10 +- common/lib/capa/capa/tests/test_inputtypes.py | 17 +- .../lib/capa/capa/tests/test_responsetypes.py | 17 +- common/lib/capa/capa/util.py | 7 +- common/lib/capa/capa/xqueue_interface.py | 13 +- common/lib/supertrace.py | 5 +- common/lib/xmodule/setup.py | 2 +- common/lib/xmodule/xmodule/abtest_module.py | 6 +- common/lib/xmodule/xmodule/capa_module.py | 16 +- .../xmodule/combined_open_ended_module.py | 8 +- .../xmodule/combined_open_ended_rubric.py | 18 +- .../lib/xmodule/xmodule/conditional_module.py | 19 +- .../xmodule/xmodule/contentstore/content.py | 43 ++-- .../xmodule/xmodule/contentstore/django.py | 1 + .../lib/xmodule/xmodule/contentstore/mongo.py | 43 ++-- common/lib/xmodule/xmodule/course_module.py | 69 +++---- .../lib/xmodule/xmodule/discussion_module.py | 2 + common/lib/xmodule/xmodule/errortracker.py | 3 + common/lib/xmodule/xmodule/graders.py | 35 ++-- .../xmodule/xmodule/grading_service_module.py | 6 +- common/lib/xmodule/xmodule/html_checker.py | 1 + common/lib/xmodule/xmodule/html_module.py | 4 +- common/lib/xmodule/xmodule/mako_module.py | 3 +- .../xmodule/xmodule/modulestore/__init__.py | 2 +- .../lib/xmodule/xmodule/modulestore/draft.py | 2 +- .../lib/xmodule/xmodule/modulestore/mongo.py | 4 +- .../lib/xmodule/xmodule/modulestore/search.py | 4 +- .../xmodule/modulestore/store_utilities.py | 32 +-- .../xmodule/modulestore/tests/__init__.py | 2 - .../xmodule/modulestore/tests/factories.py | 18 +- .../modulestore/tests/test_location.py | 8 +- .../modulestore/tests/test_modulestore.py | 2 +- .../xmodule/modulestore/tests/test_mongo.py | 1 - .../xmodule/modulestore/tests/test_xml.py | 3 +- common/lib/xmodule/xmodule/modulestore/xml.py | 14 +- .../xmodule/modulestore/xml_exporter.py | 7 +- .../xmodule/modulestore/xml_importer.py | 80 ++++---- .../xmodule/open_ended_image_submission.py | 7 +- .../lib/xmodule/xmodule/open_ended_module.py | 5 +- common/lib/xmodule/xmodule/openendedchild.py | 10 +- .../xmodule/xmodule/peer_grading_module.py | 32 +-- .../xmodule/xmodule/peer_grading_service.py | 26 ++- .../lib/xmodule/xmodule/randomize_module.py | 4 +- common/lib/xmodule/xmodule/raw_module.py | 3 +- .../xmodule/xmodule/self_assessment_module.py | 1 + common/lib/xmodule/xmodule/seq_module.py | 7 +- common/lib/xmodule/xmodule/stringify.py | 1 + common/lib/xmodule/xmodule/template_module.py | 2 +- common/lib/xmodule/xmodule/tests/__init__.py | 5 +- .../xmodule/xmodule/tests/test_capa_module.py | 8 +- .../xmodule/tests/test_combined_open_ended.py | 45 ++-- .../xmodule/xmodule/tests/test_conditional.py | 15 +- .../lib/xmodule/xmodule/tests/test_content.py | 4 +- .../lib/xmodule/xmodule/tests/test_export.py | 7 +- .../lib/xmodule/xmodule/tests/test_graders.py | 2 +- .../lib/xmodule/xmodule/tests/test_import.py | 5 +- .../xmodule/xmodule/tests/test_progress.py | 1 + .../xmodule/tests/test_randomize_module.py | 1 - .../xmodule/tests/test_self_assessment.py | 4 +- .../xmodule/xmodule/tests/test_stringify.py | 2 + common/lib/xmodule/xmodule/timeparse.py | 2 + common/lib/xmodule/xmodule/util/decorators.py | 10 +- common/lib/xmodule/xmodule/vertical_module.py | 2 +- common/lib/xmodule/xmodule/video_module.py | 2 +- common/lib/xmodule/xmodule/x_module.py | 8 +- common/lib/xmodule/xmodule/xml_module.py | 32 +-- .../docs/source/conf.py | 3 +- common/xml_cleanup.py | 12 +- ...el_field_generatedcertificate_name__add.py | 2 +- ...icate_graded_download_url__del_field_ge.py | 2 +- ...icate_enabled__add_field_generatedcerti.py | 2 +- ...icate_certificate_id__add_field_generat.py | 2 +- ...icate_name__add_field_generatedcertific.py | 2 +- ...field_generatedcertificate_error_reason.py | 2 +- .../migrations/0014_adding_whitelist.py | 2 +- lms/djangoapps/certificates/models.py | 2 + lms/djangoapps/certificates/queue.py | 2 +- lms/djangoapps/course_wiki/course_nav.py | 62 +++--- lms/djangoapps/course_wiki/editors.py | 9 +- .../plugins/markdownedx/__init__.py | 2 +- .../plugins/markdownedx/mdx_mathjax.py | 1 - .../plugins/markdownedx/wiki_plugin.py | 6 +- lms/djangoapps/course_wiki/tests/__init__.py | 1 - lms/djangoapps/course_wiki/tests/tests.py | 100 +++++---- lms/djangoapps/course_wiki/views.py | 34 +-- lms/djangoapps/courseware/access.py | 6 +- lms/djangoapps/courseware/admin.py | 1 - lms/djangoapps/courseware/courses.py | 7 +- lms/djangoapps/courseware/features/courses.py | 20 +- .../courseware/features/courseware.py | 3 +- .../courseware/features/courseware_common.py | 9 +- .../courseware/features/openended.py | 21 +- .../courseware/features/smart-accordion.py | 15 +- lms/djangoapps/courseware/grades.py | 54 ++--- .../management/commands/clean_xml.py | 1 + .../management/commands/metadata_to_json.py | 3 + ..._add_unique_offlinecomputedgrade_user_c.py | 2 +- lms/djangoapps/courseware/models.py | 4 +- lms/djangoapps/courseware/module_render.py | 40 ++-- lms/djangoapps/courseware/tabs.py | 25 ++- lms/djangoapps/courseware/tests/__init__.py | 1 - lms/djangoapps/courseware/tests/factories.py | 5 + .../courseware/tests/test_access.py | 11 +- lms/djangoapps/courseware/tests/tests.py | 52 ++--- lms/djangoapps/courseware/views.py | 26 ++- lms/djangoapps/dashboard/views.py | 10 +- .../django_comment_client/base/urls.py | 2 +- .../django_comment_client/base/views.py | 52 +++-- .../django_comment_client/forum/views.py | 35 ++-- .../django_comment_client/helpers.py | 5 + .../commands/assign_roles_for_course.py | 1 + .../commands/create_roles_for_existing.py | 1 + .../commands/seed_permissions_roles.py | 2 +- .../django_comment_client/middleware.py | 3 +- .../migrations/0001_initial.py | 2 +- .../django_comment_client/models.py | 4 +- .../django_comment_client/mustache_helpers.py | 7 +- .../django_comment_client/permissions.py | 10 +- .../django_comment_client/settings.py | 2 +- .../tests/test_helpers.py | 3 +- .../tests/test_middleware.py | 33 +-- .../tests/test_mustache_helpers.py | 32 +-- .../django_comment_client/tests/test_utils.py | 18 +- lms/djangoapps/django_comment_client/utils.py | 43 +++- .../management/commands/compute_grades.py | 11 +- .../management/commands/dump_grades.py | 24 +-- .../instructor/offline_gradecalc.py | 20 +- lms/djangoapps/instructor/tests.py | 33 ++- lms/djangoapps/instructor/views.py | 132 ++++++------ .../licenses/migrations/0001_initial.py | 2 +- .../management/commands/create_groups.py | 14 +- .../management/commands/create_user.py | 68 +++--- .../commands/manage_course_groups.py | 39 ++-- lms/djangoapps/lms_migration/migrate.py | 52 ++--- .../controller_query_service.py | 36 ++-- .../open_ended_notifications.py | 50 +++-- .../open_ended_grading/open_ended_util.py | 5 +- .../open_ended_grading/staff_grading.py | 1 - .../staff_grading_service.py | 9 +- lms/djangoapps/open_ended_grading/tests.py | 13 +- lms/djangoapps/open_ended_grading/views.py | 54 ++--- lms/djangoapps/portal/features/common.py | 20 +- lms/djangoapps/portal/features/factories.py | 3 + lms/djangoapps/portal/features/homepage.py | 1 + lms/djangoapps/portal/features/login.py | 10 +- .../portal/features/registration.py | 3 + lms/djangoapps/portal/features/signup.py | 5 +- .../management/commands/init_psychometrics.py | 26 +-- lms/djangoapps/psychometrics/models.py | 6 +- lms/djangoapps/psychometrics/psychoanalyze.py | 12 +- lms/djangoapps/simplewiki/mdx_mathjax.py | 1 - lms/djangoapps/simplewiki/views.py | 1 + lms/djangoapps/static_template_view/views.py | 1 - lms/djangoapps/staticbook/views.py | 6 +- lms/djangoapps/terrain/__init__.py | 2 +- lms/djangoapps/terrain/browser.py | 7 +- lms/djangoapps/terrain/factories.py | 23 ++- lms/djangoapps/terrain/steps.py | 40 +++- lms/envs/acceptance.py | 6 +- lms/envs/common.py | 52 ++--- lms/envs/content.py | 6 +- lms/envs/dev.py | 2 +- lms/envs/dev_edx4edx.py | 10 +- lms/envs/dev_ike.py | 16 +- lms/envs/dev_int.py | 6 +- lms/envs/devgroups/courses.py | 25 +-- lms/envs/devgroups/portal.py | 1 - lms/envs/devplus.py | 10 +- lms/envs/edx4edx_aws.py | 14 +- lms/envs/static.py | 4 +- lms/envs/test.py | 4 +- lms/envs/test_ike.py | 6 +- lms/lib/comment_client/comment.py | 3 + lms/lib/comment_client/comment_client.py | 8 + lms/lib/comment_client/commentable.py | 1 + lms/lib/comment_client/legacy.py | 52 ++++- lms/lib/comment_client/models.py | 11 +- lms/lib/comment_client/thread.py | 3 +- lms/lib/comment_client/user.py | 6 + lms/lib/comment_client/utils.py | 9 +- lms/lib/dogfood/check.py | 2 - lms/lib/loncapa/loncapa_check.py | 2 - lms/lib/symmath/symmath_check.py | 8 +- lms/static/admin/js/compress.py | 1 + lms/urls.py | 16 +- 271 files changed, 2395 insertions(+), 1826 deletions(-) diff --git a/cms/__init__.py b/cms/__init__.py index 8b13789179..e69de29bb2 100644 --- a/cms/__init__.py +++ b/cms/__init__.py @@ -1 +0,0 @@ - diff --git a/cms/djangoapps/auth/authz.py b/cms/djangoapps/auth/authz.py index 22bbc4bc1c..281e3f46b2 100644 --- a/cms/djangoapps/auth/authz.py +++ b/cms/djangoapps/auth/authz.py @@ -18,6 +18,8 @@ STAFF_ROLE_NAME = 'staff' # we're just making a Django group for each location/role combo # to do this we're just creating a Group name which is a formatted string # of those two variables + + def get_course_groupname_for_role(location, role): loc = Location(location) # hack: check for existence of a group name in the legacy LMS format _ @@ -25,11 +27,12 @@ def get_course_groupname_for_role(location, role): # more information groupname = '{0}_{1}'.format(role, loc.course) - if len(Group.objects.filter(name = groupname)) == 0: - groupname = '{0}_{1}'.format(role,loc.course_id) + if len(Group.objects.filter(name=groupname)) == 0: + groupname = '{0}_{1}'.format(role, loc.course_id) return groupname + def get_users_in_course_group_by_role(location, role): groupname = get_course_groupname_for_role(location, role) (group, created) = Group.objects.get_or_create(name=groupname) @@ -39,6 +42,8 @@ def get_users_in_course_group_by_role(location, role): ''' Create all permission groups for a new course and subscribe the caller into those roles ''' + + def create_all_course_groups(creator, location): create_new_course_group(creator, location, INSTRUCTOR_ROLE_NAME) create_new_course_group(creator, location, STAFF_ROLE_NAME) @@ -46,7 +51,7 @@ def create_all_course_groups(creator, location): def create_new_course_group(creator, location, role): groupname = get_course_groupname_for_role(location, role) - (group, created) =Group.objects.get_or_create(name=groupname) + (group, created) = Group.objects.get_or_create(name=groupname) if created: group.save() @@ -59,6 +64,8 @@ def create_new_course_group(creator, location, role): This is to be called only by either a command line code path or through a app which has already asserted permissions ''' + + def _delete_course_group(location): # remove all memberships instructors = Group.objects.get(name=get_course_groupname_for_role(location, INSTRUCTOR_ROLE_NAME)) @@ -75,6 +82,8 @@ def _delete_course_group(location): This is to be called only by either a command line code path or through an app which has already asserted permissions to do this action ''' + + def _copy_course_group(source, dest): instructors = Group.objects.get(name=get_course_groupname_for_role(source, INSTRUCTOR_ROLE_NAME)) new_instructors_group = Group.objects.get(name=get_course_groupname_for_role(dest, INSTRUCTOR_ROLE_NAME)) @@ -86,7 +95,7 @@ def _copy_course_group(source, dest): new_staff_group = Group.objects.get(name=get_course_groupname_for_role(dest, STAFF_ROLE_NAME)) for user in staff.user_set.all(): user.groups.add(new_staff_group) - user.save() + user.save() def add_user_to_course_group(caller, user, location, role): @@ -133,8 +142,6 @@ def remove_user_from_course_group(caller, user, location, role): def is_user_in_course_group_role(user, location, role): if user.is_active and user.is_authenticated: # all "is_staff" flagged accounts belong to all groups - return user.is_staff or user.groups.filter(name=get_course_groupname_for_role(location,role)).count() > 0 + return user.is_staff or user.groups.filter(name=get_course_groupname_for_role(location, role)).count() > 0 return False - - diff --git a/cms/djangoapps/contentstore/course_info_model.py b/cms/djangoapps/contentstore/course_info_model.py index 6995df06a8..153d13dd13 100644 --- a/cms/djangoapps/contentstore/course_info_model.py +++ b/cms/djangoapps/contentstore/course_info_model.py @@ -8,6 +8,8 @@ import logging ## TODO store as array of { date, content } and override course_info_module.definition_from_xml ## This should be in a class which inherits from XmlDescriptor + + def get_course_updates(location): """ Retrieve the relevant course_info updates and unpack into the model which the client expects: @@ -21,13 +23,13 @@ def get_course_updates(location): # current db rep: {"_id" : locationjson, "definition" : { "data" : "
      [
    1. date

      content
    2. ]
    "} "metadata" : ignored} location_base = course_updates.location.url() - + # purely to handle free formed updates not done via editor. Actually kills them, but at least doesn't break. try: course_html_parsed = html.fromstring(course_updates.definition['data']) except: course_html_parsed = html.fromstring("
      ") - + # Confirm that root is
        , iterate over
      1. , pull out

        subs and then rest of val course_upd_collection = [] if course_html_parsed.tag == 'ol': @@ -40,25 +42,26 @@ def get_course_updates(location): content = update[0].tail else: content = "\n".join([html.tostring(ele) for ele in update[1:]]) - + # make the id on the client be 1..len w/ 1 being the oldest and len being the newest - course_upd_collection.append({"id" : location_base + "/" + str(len(course_html_parsed) - idx), - "date" : update.findtext("h2"), - "content" : content}) - + course_upd_collection.append({"id": location_base + "/" + str(len(course_html_parsed) - idx), + "date": update.findtext("h2"), + "content": content}) + return course_upd_collection + def update_course_updates(location, update, passed_id=None): """ Either add or update the given course update. It will add it if the passed_id is absent or None. It will update it if it has an passed_id which has a valid value. Until updates have distinct values, the passed_id is the location url + an index - into the html structure. + into the html structure. """ try: course_updates = modulestore('direct').get_item(location) except ItemNotFoundError: return HttpResponseBadRequest - + # purely to handle free formed updates not done via editor. Actually kills them, but at least doesn't break. try: course_html_parsed = html.fromstring(course_updates.definition['data']) @@ -67,7 +70,7 @@ def update_course_updates(location, update, passed_id=None): # No try/catch b/c failure generates an error back to client new_html_parsed = html.fromstring('
      2. ' + update['date'] + '

        ' + update['content'] + '
      3. ') - + # Confirm that root is
          , iterate over
        1. , pull out

          subs and then rest of val if course_html_parsed.tag == 'ol': # ??? Should this use the id in the json or in the url or does it matter? @@ -80,14 +83,15 @@ def update_course_updates(location, update, passed_id=None): idx = len(course_html_parsed) passed_id = course_updates.location.url() + "/" + str(idx) - + # update db record course_updates.definition['data'] = html.tostring(course_html_parsed) modulestore('direct').update_item(location, course_updates.definition['data']) - - return {"id" : passed_id, - "date" : update['date'], - "content" :update['content']} + + return {"id": passed_id, + "date": update['date'], + "content": update['content']} + def delete_course_update(location, update, passed_id): """ @@ -96,19 +100,19 @@ def delete_course_update(location, update, passed_id): """ if not passed_id: return HttpResponseBadRequest - + try: course_updates = modulestore('direct').get_item(location) except ItemNotFoundError: return HttpResponseBadRequest - + # TODO use delete_blank_text parser throughout and cache as a static var in a class # purely to handle free formed updates not done via editor. Actually kills them, but at least doesn't break. try: course_html_parsed = html.fromstring(course_updates.definition['data']) except: course_html_parsed = html.fromstring("
            ") - + if course_html_parsed.tag == 'ol': # ??? Should this use the id in the json or in the url or does it matter? idx = get_idx(passed_id) @@ -120,10 +124,11 @@ def delete_course_update(location, update, passed_id): # update db record course_updates.definition['data'] = html.tostring(course_html_parsed) store = modulestore('direct') - store.update_item(location, course_updates.definition['data']) - + store.update_item(location, course_updates.definition['data']) + return get_course_updates(location) - + + def get_idx(passed_id): """ From the url w/ idx appended, get the idx. @@ -131,4 +136,4 @@ def get_idx(passed_id): # TODO compile this regex into a class static and reuse for each call idx_matcher = re.search(r'.*/(\d+)$', passed_id) if idx_matcher: - return int(idx_matcher.group(1)) \ No newline at end of file + return int(idx_matcher.group(1)) diff --git a/cms/djangoapps/contentstore/features/common.py b/cms/djangoapps/contentstore/features/common.py index d910d73085..f868b598a8 100644 --- a/cms/djangoapps/contentstore/features/common.py +++ b/cms/djangoapps/contentstore/features/common.py @@ -12,6 +12,8 @@ from logging import getLogger logger = getLogger(__name__) ########### STEP HELPERS ############## + + @step('I (?:visit|access|open) the Studio homepage$') def i_visit_the_studio_homepage(step): # To make this go to port 8001, put @@ -20,32 +22,37 @@ def i_visit_the_studio_homepage(step): world.browser.visit(django_url('/')) assert world.browser.is_element_present_by_css('body.no-header', 10) + @step('I am logged into Studio$') def i_am_logged_into_studio(step): log_into_studio() + @step('I confirm the alert$') def i_confirm_with_ok(step): world.browser.get_alert().accept() + @step(u'I press the "([^"]*)" delete icon$') def i_press_the_category_delete_icon(step, category): if category == 'section': css = 'a.delete-button.delete-section-button span.delete-icon' elif category == 'subsection': - css='a.delete-button.delete-subsection-button span.delete-icon' + css = 'a.delete-button.delete-subsection-button span.delete-icon' else: assert False, 'Invalid category: %s' % category css_click(css) ####### HELPER FUNCTIONS ############## + + def create_studio_user( uname='robot', email='robot+studio@edx.org', password='test', - is_staff=False): + is_staff=False): studio_user = UserFactory.build( - username=uname, + username=uname, email=email, password=password, is_staff=is_staff) @@ -58,6 +65,7 @@ def create_studio_user( user_profile = UserProfileFactory(user=studio_user) + def flush_xmodule_store(): # Flush and initialize the module store # It needs the templates because it creates new records @@ -70,26 +78,32 @@ def flush_xmodule_store(): xmodule.modulestore.django.modulestore().collection.drop() xmodule.templates.update_templates() -def assert_css_with_text(css,text): + +def assert_css_with_text(css, text): assert_true(world.browser.is_element_present_by_css(css, 5)) assert_equal(world.browser.find_by_css(css).text, text) + def css_click(css): world.browser.find_by_css(css).first.click() + def css_fill(css, value): world.browser.find_by_css(css).first.fill(value) + def clear_courses(): flush_xmodule_store() + def fill_in_course_info( name='Robot Super Course', org='MITx', num='101'): - css_fill('.new-course-name',name) - css_fill('.new-course-org',org) - css_fill('.new-course-number',num) + css_fill('.new-course-name', name) + css_fill('.new-course-org', org) + css_fill('.new-course-number', num) + def log_into_studio( uname='robot', @@ -108,24 +122,27 @@ def log_into_studio( assert_true(world.browser.is_element_present_by_css('.new-course-button', 5)) + def create_a_course(): css_click('a.new-course-button') fill_in_course_info() css_click('input.new-course-save') assert_true(world.browser.is_element_present_by_css('a#courseware-tab', 5)) + def add_section(name='My Section'): link_css = 'a.new-courseware-section-button' css_click(link_css) name_css = '.new-section-name' save_css = '.new-section-name-save' - css_fill(name_css,name) + css_fill(name_css, name) css_click(save_css) + def add_subsection(name='Subsection One'): css = 'a.new-subsection-item' css_click(css) name_css = 'input.new-subsection-name-input' save_css = 'input.new-subsection-name-save' css_fill(name_css, name) - css_click(save_css) \ No newline at end of file + css_click(save_css) diff --git a/cms/djangoapps/contentstore/features/courses.py b/cms/djangoapps/contentstore/features/courses.py index 2c1cf6281a..d2d038a928 100644 --- a/cms/djangoapps/contentstore/features/courses.py +++ b/cms/djangoapps/contentstore/features/courses.py @@ -2,49 +2,61 @@ from lettuce import world, step from common import * ############### ACTIONS #################### + + @step('There are no courses$') def no_courses(step): clear_courses() + @step('I click the New Course button$') def i_click_new_course(step): css_click('.new-course-button') + @step('I fill in the new course information$') def i_fill_in_a_new_course_information(step): fill_in_course_info() + @step('I create a new course$') def i_create_a_course(step): create_a_course() + @step('I click the course link in My Courses$') def i_click_the_course_link_in_my_courses(step): course_css = 'span.class-name' css_click(course_css) ############ ASSERTIONS ################### + + @step('the Courseware page has loaded in Studio$') def courseware_page_has_loaded_in_studio(step): courseware_css = 'a#courseware-tab' assert world.browser.is_element_present_by_css(courseware_css) + @step('I see the course listed in My Courses$') def i_see_the_course_in_my_courses(step): course_css = 'span.class-name' - assert_css_with_text(course_css,'Robot Super Course') + assert_css_with_text(course_css, 'Robot Super Course') + @step('the course is loaded$') def course_is_loaded(step): class_css = 'a.class-name' - assert_css_with_text(class_css,'Robot Super Course') + assert_css_with_text(class_css, 'Robot Super Course') + @step('I am on the "([^"]*)" tab$') def i_am_on_tab(step, tab_name): header_css = 'div.inner-wrapper h1' - assert_css_with_text(header_css,tab_name) + assert_css_with_text(header_css, tab_name) + @step('I see a link for adding a new section$') def i_see_new_section_link(step): link_css = 'a.new-courseware-section-button' - assert_css_with_text(link_css,'New Section') + assert_css_with_text(link_css, 'New Section') diff --git a/cms/djangoapps/contentstore/features/factories.py b/cms/djangoapps/contentstore/features/factories.py index 389f2bac49..087ceaaa2d 100644 --- a/cms/djangoapps/contentstore/features/factories.py +++ b/cms/djangoapps/contentstore/features/factories.py @@ -3,6 +3,7 @@ from student.models import User, UserProfile, Registration from datetime import datetime import uuid + class UserProfileFactory(factory.Factory): FACTORY_FOR = UserProfile @@ -10,12 +11,14 @@ class UserProfileFactory(factory.Factory): name = 'Robot Studio' courseware = 'course.xml' + class RegistrationFactory(factory.Factory): FACTORY_FOR = Registration user = None activation_key = uuid.uuid4().hex + class UserFactory(factory.Factory): FACTORY_FOR = User @@ -28,4 +31,4 @@ class UserFactory(factory.Factory): is_active = True is_superuser = False last_login = datetime.now() - date_joined = datetime.now() \ No newline at end of file + date_joined = datetime.now() diff --git a/cms/djangoapps/contentstore/features/section.py b/cms/djangoapps/contentstore/features/section.py index 8ac30e2170..3bcaeab6c4 100644 --- a/cms/djangoapps/contentstore/features/section.py +++ b/cms/djangoapps/contentstore/features/section.py @@ -2,54 +2,65 @@ from lettuce import world, step from common import * ############### ACTIONS #################### + + @step('I have opened a new course in Studio$') def i_have_opened_a_new_course(step): clear_courses() log_into_studio() create_a_course() + @step('I click the new section link$') def i_click_new_section_link(step): link_css = 'a.new-courseware-section-button' css_click(link_css) + @step('I enter the section name and click save$') def i_save_section_name(step): name_css = '.new-section-name' save_css = '.new-section-name-save' - css_fill(name_css,'My Section') + css_fill(name_css, 'My Section') css_click(save_css) + @step('I have added a new section$') def i_have_added_new_section(step): add_section() - + + @step('I click the Edit link for the release date$') def i_click_the_edit_link_for_the_release_date(step): button_css = 'div.section-published-date a.edit-button' css_click(button_css) + @step('I save a new section release date$') def i_save_a_new_section_release_date(step): date_css = 'input.start-date.date.hasDatepicker' time_css = 'input.start-time.time.ui-timepicker-input' - css_fill(date_css,'12/25/2013') + css_fill(date_css, '12/25/2013') # click here to make the calendar go away css_click(time_css) - css_fill(time_css,'12:00am') + css_fill(time_css, '12:00am') css_click('a.save-button') ############ ASSERTIONS ################### + + @step('I see my section on the Courseware page$') def i_see_my_section_on_the_courseware_page(step): section_css = 'span.section-name-span' - assert_css_with_text(section_css,'My Section') + assert_css_with_text(section_css, 'My Section') + @step('the section does not exist$') def section_does_not_exist(step): css = 'span.section-name-span' assert world.browser.is_element_not_present_by_css(css) + @step('I see a release date for my section$') def i_see_a_release_date_for_my_section(step): import re @@ -63,18 +74,21 @@ def i_see_a_release_date_for_my_section(step): date_regex = '[01][0-9]\/[0-3][0-9]\/[12][0-9][0-9][0-9]' time_regex = '[0-2][0-9]:[0-5][0-9]' match_string = '%s %s at %s' % (msg, date_regex, time_regex) - assert re.match(match_string,status_text) + assert re.match(match_string, status_text) + @step('I see a link to create a new subsection$') def i_see_a_link_to_create_a_new_subsection(step): css = 'a.new-subsection-item' assert world.browser.is_element_present_by_css(css) + @step('the section release date picker is not visible$') def the_section_release_date_picker_not_visible(step): css = 'div.edit-subsection-publish-settings' assert False, world.browser.find_by_css(css).visible + @step('the section release date is updated$') def the_section_release_date_is_updated(step): css = 'span.published-status' diff --git a/cms/djangoapps/contentstore/features/signup.py b/cms/djangoapps/contentstore/features/signup.py index 7794511f94..e105b674f7 100644 --- a/cms/djangoapps/contentstore/features/signup.py +++ b/cms/djangoapps/contentstore/features/signup.py @@ -1,5 +1,6 @@ from lettuce import world, step + @step('I fill in the registration form$') def i_fill_in_the_registration_form(step): register_form = world.browser.find_by_css('form#register_form') @@ -9,15 +10,18 @@ def i_fill_in_the_registration_form(step): register_form.find_by_name('name').fill('Robot Studio') register_form.find_by_name('terms_of_service').check() + @step('I press the "([^"]*)" button on the registration form$') def i_press_the_button_on_the_registration_form(step, button): register_form = world.browser.find_by_css('form#register_form') register_form.find_by_value(button).click() + @step('I should see be on the studio home page$') def i_should_see_be_on_the_studio_home_page(step): assert world.browser.find_by_css('div.inner-wrapper') + @step(u'I should see the message "([^"]*)"$') def i_should_see_the_message(step, msg): - assert world.browser.is_text_present(msg, 5) \ No newline at end of file + assert world.browser.is_text_present(msg, 5) diff --git a/cms/djangoapps/contentstore/features/studio-overview-togglesection.py b/cms/djangoapps/contentstore/features/studio-overview-togglesection.py index 010678c0e8..00aa39455d 100644 --- a/cms/djangoapps/contentstore/features/studio-overview-togglesection.py +++ b/cms/djangoapps/contentstore/features/studio-overview-togglesection.py @@ -6,11 +6,13 @@ from nose.tools import assert_true, assert_false, assert_equal from logging import getLogger logger = getLogger(__name__) + @step(u'I have a course with no sections$') def have_a_course(step): clear_courses() course = CourseFactory.create() + @step(u'I have a course with 1 section$') def have_a_course_with_1_section(step): clear_courses() @@ -18,8 +20,9 @@ def have_a_course_with_1_section(step): section = ItemFactory.create(parent_location=course.location) subsection1 = ItemFactory.create( parent_location=section.location, - template = 'i4x://edx/templates/sequential/Empty', - display_name = 'Subsection One',) + template='i4x://edx/templates/sequential/Empty', + display_name='Subsection One',) + @step(u'I have a course with multiple sections$') def have_a_course_with_two_sections(step): @@ -28,19 +31,20 @@ def have_a_course_with_two_sections(step): section = ItemFactory.create(parent_location=course.location) subsection1 = ItemFactory.create( parent_location=section.location, - template = 'i4x://edx/templates/sequential/Empty', - display_name = 'Subsection One',) + template='i4x://edx/templates/sequential/Empty', + display_name='Subsection One',) section2 = ItemFactory.create( parent_location=course.location, display_name='Section Two',) subsection2 = ItemFactory.create( parent_location=section2.location, - template = 'i4x://edx/templates/sequential/Empty', - display_name = 'Subsection Alpha',) + template='i4x://edx/templates/sequential/Empty', + display_name='Subsection Alpha',) subsection3 = ItemFactory.create( parent_location=section2.location, - template = 'i4x://edx/templates/sequential/Empty', - display_name = 'Subsection Beta',) + template='i4x://edx/templates/sequential/Empty', + display_name='Subsection Beta',) + @step(u'I navigate to the course overview page$') def navigate_to_the_course_overview_page(step): @@ -48,15 +52,18 @@ def navigate_to_the_course_overview_page(step): course_locator = '.class-name' css_click(course_locator) + @step(u'I navigate to the courseware page of a course with multiple sections') def nav_to_the_courseware_page_of_a_course_with_multiple_sections(step): step.given('I have a course with multiple sections') step.given('I navigate to the course overview page') + @step(u'I add a section') def i_add_a_section(step): add_section(name='My New Section That I Just Added') + @step(u'I click the "([^"]*)" link$') def i_click_the_text_span(step, text): span_locator = '.toggle-button-sections span' @@ -65,16 +72,19 @@ def i_click_the_text_span(step, text): assert_equal(world.browser.find_by_css(span_locator).value, text) css_click(span_locator) + @step(u'I collapse the first section$') def i_collapse_a_section(step): collapse_locator = 'section.courseware-section a.collapse' css_click(collapse_locator) + @step(u'I expand the first section$') def i_expand_a_section(step): expand_locator = 'section.courseware-section a.expand' css_click(expand_locator) + @step(u'I see the "([^"]*)" link$') def i_see_the_span_with_text(step, text): span_locator = '.toggle-button-sections span' @@ -82,6 +92,7 @@ def i_see_the_span_with_text(step, text): assert_equal(world.browser.find_by_css(span_locator).value, text) assert_true(world.browser.find_by_css(span_locator).visible) + @step(u'I do not see the "([^"]*)" link$') def i_do_not_see_the_span_with_text(step, text): # Note that the span will exist on the page but not be visible @@ -89,6 +100,7 @@ def i_do_not_see_the_span_with_text(step, text): assert_true(world.browser.is_element_present_by_css(span_locator)) assert_false(world.browser.find_by_css(span_locator).visible) + @step(u'all sections are expanded$') def all_sections_are_expanded(step): subsection_locator = 'div.subsection-list' @@ -96,9 +108,10 @@ def all_sections_are_expanded(step): for s in subsections: assert_true(s.visible) + @step(u'all sections are collapsed$') def all_sections_are_expanded(step): subsection_locator = 'div.subsection-list' subsections = world.browser.find_by_css(subsection_locator) for s in subsections: - assert_false(s.visible) \ No newline at end of file + assert_false(s.visible) diff --git a/cms/djangoapps/contentstore/features/subsection.py b/cms/djangoapps/contentstore/features/subsection.py index ea614d3feb..e2041b8dbf 100644 --- a/cms/djangoapps/contentstore/features/subsection.py +++ b/cms/djangoapps/contentstore/features/subsection.py @@ -2,6 +2,8 @@ from lettuce import world, step from common import * ############### ACTIONS #################### + + @step('I have opened a new course section in Studio$') def i_have_opened_a_new_course_section(step): clear_courses() @@ -9,31 +11,37 @@ def i_have_opened_a_new_course_section(step): create_a_course() add_section() + @step('I click the New Subsection link') def i_click_the_new_subsection_link(step): css = 'a.new-subsection-item' css_click(css) + @step('I enter the subsection name and click save$') def i_save_subsection_name(step): name_css = 'input.new-subsection-name-input' save_css = 'input.new-subsection-name-save' - css_fill(name_css,'Subsection One') + css_fill(name_css, 'Subsection One') css_click(save_css) + @step('I have added a new subsection$') def i_have_added_a_new_subsection(step): add_subsection() ############ ASSERTIONS ################### + + @step('I see my subsection on the Courseware page$') def i_see_my_subsection_on_the_courseware_page(step): css = 'span.subsection-name' - assert world.browser.is_element_present_by_css(css) + assert world.browser.is_element_present_by_css(css) css = 'span.subsection-name-value' - assert_css_with_text(css,'Subsection One') + assert_css_with_text(css, 'Subsection One') + @step('the subsection does not exist$') def the_subsection_does_not_exist(step): css = 'span.subsection-name' - assert world.browser.is_element_not_present_by_css(css) \ No newline at end of file + assert world.browser.is_element_not_present_by_css(css) diff --git a/cms/djangoapps/contentstore/management/commands/clone.py b/cms/djangoapps/contentstore/management/commands/clone.py index 2357cd1dbd..abf04f3da3 100644 --- a/cms/djangoapps/contentstore/management/commands/clone.py +++ b/cms/djangoapps/contentstore/management/commands/clone.py @@ -14,6 +14,7 @@ from auth.authz import _copy_course_group # To run from command line: rake cms:clone SOURCE_LOC=MITx/111/Foo1 DEST_LOC=MITx/135/Foo3 # + class Command(BaseCommand): help = \ '''Clone a MongoDB backed course to another location''' diff --git a/cms/djangoapps/contentstore/management/commands/delete_course.py b/cms/djangoapps/contentstore/management/commands/delete_course.py index 0313f7faed..bb38e72d44 100644 --- a/cms/djangoapps/contentstore/management/commands/delete_course.py +++ b/cms/djangoapps/contentstore/management/commands/delete_course.py @@ -15,6 +15,7 @@ from auth.authz import _delete_course_group # To run from command line: rake cms:delete_course LOC=MITx/111/Foo1 # + class Command(BaseCommand): help = \ '''Delete a MongoDB backed course''' @@ -35,6 +36,3 @@ class Command(BaseCommand): print 'removing User permissions from course....' # in the django layer, we need to remove all the user permissions groups associated with this course _delete_course_group(loc) - - - diff --git a/cms/djangoapps/contentstore/management/commands/prompt.py b/cms/djangoapps/contentstore/management/commands/prompt.py index 9c8fd81d45..211c48406c 100644 --- a/cms/djangoapps/contentstore/management/commands/prompt.py +++ b/cms/djangoapps/contentstore/management/commands/prompt.py @@ -1,5 +1,6 @@ import sys + def query_yes_no(question, default="yes"): """Ask a yes/no question via raw_input() and return their answer. @@ -30,4 +31,4 @@ def query_yes_no(question, default="yes"): return valid[choice] else: sys.stdout.write("Please respond with 'yes' or 'no' "\ - "(or 'y' or 'n').\n") \ No newline at end of file + "(or 'y' or 'n').\n") diff --git a/cms/djangoapps/contentstore/module_info_model.py b/cms/djangoapps/contentstore/module_info_model.py index 3b783c8815..796184baa0 100644 --- a/cms/djangoapps/contentstore/module_info_model.py +++ b/cms/djangoapps/contentstore/module_info_model.py @@ -7,7 +7,8 @@ from lxml import etree import re from django.http import HttpResponseBadRequest, Http404 -def get_module_info(store, location, parent_location = None, rewrite_static_links = False): + +def get_module_info(store, location, parent_location=None, rewrite_static_links=False): try: if location.revision is None: module = store.get_item(location) @@ -36,6 +37,7 @@ def get_module_info(store, location, parent_location = None, rewrite_static_link 'metadata': module.metadata } + def set_module_info(store, location, post_data): module = None isNew = False diff --git a/cms/djangoapps/contentstore/tests/factories.py b/cms/djangoapps/contentstore/tests/factories.py index f9c505d68f..d15610f11c 100644 --- a/cms/djangoapps/contentstore/tests/factories.py +++ b/cms/djangoapps/contentstore/tests/factories.py @@ -5,6 +5,7 @@ from student.models import (User, UserProfile, Registration, CourseEnrollmentAllowed) from django.contrib.auth.models import Group + class UserProfileFactory(Factory): FACTORY_FOR = UserProfile @@ -12,12 +13,14 @@ class UserProfileFactory(Factory): name = 'Robot Studio' courseware = 'course.xml' + class RegistrationFactory(Factory): FACTORY_FOR = Registration user = None activation_key = uuid4().hex + class UserFactory(Factory): FACTORY_FOR = User @@ -32,11 +35,13 @@ class UserFactory(Factory): last_login = datetime.now() date_joined = datetime.now() + class GroupFactory(Factory): FACTORY_FOR = Group name = 'test_group' + class CourseEnrollmentAllowedFactory(Factory): FACTORY_FOR = CourseEnrollmentAllowed diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index ce7d9e757c..72ae3821cc 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -35,6 +35,7 @@ TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') + @override_settings(MODULESTORE=TEST_DATA_MODULESTORE) class ContentStoreToyCourseTest(ModuleStoreTestCase): """ @@ -77,20 +78,20 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): def test_static_tab_reordering(self): import_from_xml(modulestore(), 'common/test/data/', ['full']) - + ms = modulestore('direct') - course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None])) + course = ms.get_item(Location(['i4x', 'edX', 'full', 'course', '6.002_Spring_2012', None])) # reverse the ordering reverse_tabs = [] for tab in course.tabs: if tab['type'] == 'static_tab': reverse_tabs.insert(0, 'i4x://edX/full/static_tab/{0}'.format(tab['url_slug'])) - - resp = self.client.post(reverse('reorder_static_tabs'), json.dumps({'tabs':reverse_tabs}), "application/json") - course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None])) - + resp = self.client.post(reverse('reorder_static_tabs'), json.dumps({'tabs': reverse_tabs}), "application/json") + + course = ms.get_item(Location(['i4x', 'edX', 'full', 'course', '6.002_Spring_2012', None])) + # compare to make sure that the tabs information is in the expected order after the server call course_tabs = [] for tab in course.tabs: @@ -101,17 +102,17 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): def test_about_overrides(self): ''' - This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html + This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html while there is a base definition in /about/effort.html ''' import_from_xml(modulestore(), 'common/test/data/', ['full']) ms = modulestore('direct') - effort = ms.get_item(Location(['i4x','edX','full','about','effort', None])) - self.assertEqual(effort.definition['data'],'6 hours') + effort = ms.get_item(Location(['i4x', 'edX', 'full', 'about', 'effort', None])) + self.assertEqual(effort.definition['data'], '6 hours') # this one should be in a non-override folder - effort = ms.get_item(Location(['i4x','edX','full','about','end_date', None])) - self.assertEqual(effort.definition['data'],'TBD') + effort = ms.get_item(Location(['i4x', 'edX', 'full', 'about', 'end_date', None])) + self.assertEqual(effort.definition['data'], 'TBD') def test_remove_hide_progress_tab(self): import_from_xml(modulestore(), 'common/test/data/', ['full']) @@ -147,14 +148,14 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): clone_course(ms, cs, source_location, dest_location) - # now loop through all the units in the course and verify that the clone can render them, which + # now loop through all the units in the course and verify that the clone can render them, which # means the objects are at least present - items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) + items = ms.get_items(Location(['i4x', 'edX', 'full', 'vertical', None])) self.assertGreater(len(items), 0) - clone_items = ms.get_items(Location(['i4x', 'MITx','999','vertical', None])) + clone_items = ms.get_items(Location(['i4x', 'MITx', '999', 'vertical', None])) self.assertGreater(len(clone_items), 0) for descriptor in items: - new_loc = descriptor.location._replace(org = 'MITx', course='999') + new_loc = descriptor.location._replace(org='MITx', course='999') print "Checking {0} should now also be at {1}".format(descriptor.location.url(), new_loc.url()) resp = self.client.get(reverse('edit_unit', kwargs={'location': new_loc.url()})) self.assertEqual(resp.status_code, 200) @@ -169,7 +170,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): delete_course(ms, cs, location) - items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) + items = ms.get_items(Location(['i4x', 'edX', 'full', 'vertical', None])) self.assertEqual(len(items), 0) def verify_content_existence(self, modulestore, root_dir, location, dirname, category_name, filename_suffix=''): @@ -185,7 +186,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): def test_export_course(self): ms = modulestore('direct') - cs = contentstore() + cs = contentstore() import_from_xml(ms, 'common/test/data/', ['full']) location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') @@ -205,7 +206,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): # check for custom_tags self.verify_content_existence(ms, root_dir, location, 'custom_tags', 'custom_tag_template') - + # remove old course delete_course(ms, cs, location) @@ -213,23 +214,23 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): # reimport import_from_xml(ms, root_dir, ['test_export']) - items = ms.get_items(Location(['i4x','edX', 'full', 'vertical', None])) + items = ms.get_items(Location(['i4x', 'edX', 'full', 'vertical', None])) self.assertGreater(len(items), 0) for descriptor in items: print "Checking {0}....".format(descriptor.location.url()) resp = self.client.get(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) self.assertEqual(resp.status_code, 200) - shutil.rmtree(root_dir) + shutil.rmtree(root_dir) def test_course_handouts_rewrites(self): ms = modulestore('direct') - cs = contentstore() + cs = contentstore() # import a test course - import_from_xml(ms, 'common/test/data/', ['full']) + import_from_xml(ms, 'common/test/data/', ['full']) - handout_location= Location(['i4x', 'edX', 'full', 'course_info', 'handouts']) + handout_location = Location(['i4x', 'edX', 'full', 'course_info', 'handouts']) # get module info resp = self.client.get(reverse('module_info', kwargs={'module_location': handout_location})) @@ -239,7 +240,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): # check that /static/ has been converted to the full path # note, we know the link it should be because that's what in the 'full' course in the test data - self.assertContains(resp, '/c4x/edX/full/asset/handouts_schematic_tutorial.pdf') + self.assertContains(resp, '/c4x/edX/full/asset/handouts_schematic_tutorial.pdf') class ContentStoreTest(ModuleStoreTestCase): @@ -302,7 +303,7 @@ class ContentStoreTest(ModuleStoreTestCase): data = parse_json(resp) self.assertEqual(resp.status_code, 200) - self.assertEqual(data['ErrMsg'], + self.assertEqual(data['ErrMsg'], 'There is already a course defined with the same organization and course number.') def test_create_course_with_bad_organization(self): @@ -319,7 +320,7 @@ class ContentStoreTest(ModuleStoreTestCase): """Test viewing the index page with no courses""" # Create a course so there is something to view resp = self.client.get(reverse('index')) - self.assertContains(resp, + self.assertContains(resp, '

            My Courses

            ', status_code=200, html=True) @@ -355,7 +356,7 @@ class ContentStoreTest(ModuleStoreTestCase): } resp = self.client.get(reverse('course_index', kwargs=data)) - self.assertContains(resp, + self.assertContains(resp, 'Robot Super Course', status_code=200, html=True) @@ -365,8 +366,8 @@ class ContentStoreTest(ModuleStoreTestCase): CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') section_data = { - 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', - 'template' : 'i4x://edx/templates/chapter/Empty', + 'parent_location': 'i4x://MITx/999/course/Robot_Super_Course', + 'template': 'i4x://edx/templates/chapter/Empty', 'display_name': 'Section One', } @@ -374,7 +375,7 @@ class ContentStoreTest(ModuleStoreTestCase): self.assertEqual(resp.status_code, 200) data = parse_json(resp) - self.assertRegexpMatches(data['id'], + self.assertRegexpMatches(data['id'], '^i4x:\/\/MITx\/999\/chapter\/([0-9]|[a-f]){32}$') def test_capa_module(self): @@ -382,8 +383,8 @@ class ContentStoreTest(ModuleStoreTestCase): CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course') problem_data = { - 'parent_location' : 'i4x://MITx/999/course/Robot_Super_Course', - 'template' : 'i4x://edx/templates/problem/Empty' + 'parent_location': 'i4x://MITx/999/course/Robot_Super_Course', + 'template': 'i4x://edx/templates/problem/Empty' } resp = self.client.post(reverse('clone_item'), problem_data) diff --git a/cms/djangoapps/contentstore/tests/test_core_caching.py b/cms/djangoapps/contentstore/tests/test_core_caching.py index ed41e5cc64..676627a045 100644 --- a/cms/djangoapps/contentstore/tests/test_core_caching.py +++ b/cms/djangoapps/contentstore/tests/test_core_caching.py @@ -3,6 +3,7 @@ from xmodule.modulestore import Location from xmodule.contentstore.content import StaticContent from django.test import TestCase + class Content: def __init__(self, location, content): self.location = location @@ -11,6 +12,7 @@ class Content: def get_id(self): return StaticContent.get_id_from_location(self.location) + class CachingTestCase(TestCase): # Tests for https://edx.lighthouseapp.com/projects/102637/tickets/112-updating-asset-does-not-refresh-the-cached-copy unicodeLocation = Location(u'c4x', u'mitX', u'800', u'thumbnail', u'monsters.jpg') diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index f47733b32c..84e79b9670 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -27,21 +27,21 @@ from xmodule.modulestore.tests.factories import CourseFactory class ConvertersTestCase(TestCase): @staticmethod def struct_to_datetime(struct_time): - return datetime.datetime(struct_time.tm_year, struct_time.tm_mon, struct_time.tm_mday, struct_time.tm_hour, - struct_time.tm_min, struct_time.tm_sec, tzinfo = UTC()) - + return datetime.datetime(struct_time.tm_year, struct_time.tm_mon, struct_time.tm_mday, struct_time.tm_hour, + struct_time.tm_min, struct_time.tm_sec, tzinfo=UTC()) + def compare_dates(self, date1, date2, expected_delta): dt1 = ConvertersTestCase.struct_to_datetime(date1) dt2 = ConvertersTestCase.struct_to_datetime(date2) self.assertEqual(dt1 - dt2, expected_delta, str(date1) + "-" + str(date2) + "!=" + str(expected_delta)) - + def test_iso_to_struct(self): self.compare_dates(converters.jsdate_to_time("2013-01-01"), converters.jsdate_to_time("2012-12-31"), datetime.timedelta(days=1)) self.compare_dates(converters.jsdate_to_time("2013-01-01T00"), converters.jsdate_to_time("2012-12-31T23"), datetime.timedelta(hours=1)) self.compare_dates(converters.jsdate_to_time("2013-01-01T00:00"), converters.jsdate_to_time("2012-12-31T23:59"), datetime.timedelta(minutes=1)) self.compare_dates(converters.jsdate_to_time("2013-01-01T00:00:00"), converters.jsdate_to_time("2012-12-31T23:59:59"), datetime.timedelta(seconds=1)) - - + + class CourseTestCase(ModuleStoreTestCase): def setUp(self): """ @@ -68,13 +68,14 @@ class CourseTestCase(ModuleStoreTestCase): self.client = Client() self.client.login(username=uname, password=password) - t='i4x://edx/templates/course/Empty' - o='MITx' - n='999' - dn='Robot Super Course' + t = 'i4x://edx/templates/course/Empty' + o = 'MITx' + n = '999' + dn = 'Robot Super Course' self.course_location = Location('i4x', o, n, 'course', 'Robot_Super_Course') CourseFactory.create(template=t, org=o, number=n, display_name=dn) + class CourseDetailsTestCase(CourseTestCase): def test_virgin_fetch(self): details = CourseDetails.fetch(self.course_location) @@ -86,7 +87,7 @@ class CourseDetailsTestCase(CourseTestCase): self.assertEqual(details.overview, "", "overview somehow initialized" + details.overview) self.assertIsNone(details.intro_video, "intro_video somehow initialized" + str(details.intro_video)) self.assertIsNone(details.effort, "effort somehow initialized" + str(details.effort)) - + def test_encoder(self): details = CourseDetails.fetch(self.course_location) jsondetails = json.dumps(details, cls=CourseSettingsEncoder) @@ -100,7 +101,7 @@ class CourseDetailsTestCase(CourseTestCase): self.assertEqual(jsondetails['overview'], "", "overview somehow initialized") self.assertIsNone(jsondetails['intro_video'], "intro_video somehow initialized") self.assertIsNone(jsondetails['effort'], "effort somehow initialized") - + def test_update_and_fetch(self): ## NOTE: I couldn't figure out how to validly test time setting w/ all the conversions jsondetails = CourseDetails.fetch(self.course_location) @@ -118,6 +119,7 @@ class CourseDetailsTestCase(CourseTestCase): self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).effort, jsondetails.effort, "After set effort") + class CourseDetailsViewTest(CourseTestCase): def alter_field(self, url, details, field, val): setattr(details, field, val) @@ -128,36 +130,36 @@ class CourseDetailsViewTest(CourseTestCase): payload['end_date'] = CourseDetailsViewTest.convert_datetime_to_iso(details.end_date) payload['enrollment_start'] = CourseDetailsViewTest.convert_datetime_to_iso(details.enrollment_start) payload['enrollment_end'] = CourseDetailsViewTest.convert_datetime_to_iso(details.enrollment_end) - resp = self.client.post(url, json.dumps(payload), "application/json") + resp = self.client.post(url, json.dumps(payload), "application/json") self.compare_details_with_encoding(json.loads(resp.content), details.__dict__, field + str(val)) - + @staticmethod def convert_datetime_to_iso(datetime): if datetime is not None: return datetime.isoformat("T") else: return None - + def test_update_and_fetch(self): details = CourseDetails.fetch(self.course_location) - - resp = self.client.get(reverse('course_settings', kwargs={'org' : self.course_location.org, 'course' : self.course_location.course, - 'name' : self.course_location.name })) + + resp = self.client.get(reverse('course_settings', kwargs={'org': self.course_location.org, 'course': self.course_location.course, + 'name': self.course_location.name})) self.assertContains(resp, '
          1. Course Details
          2. ', status_code=200, html=True) - # resp s/b json from here on - url = reverse('course_settings', kwargs={'org' : self.course_location.org, 'course' : self.course_location.course, - 'name' : self.course_location.name, 'section' : 'details' }) + # resp s/b json from here on + url = reverse('course_settings', kwargs={'org': self.course_location.org, 'course': self.course_location.course, + 'name': self.course_location.name, 'section': 'details'}) resp = self.client.get(url) self.compare_details_with_encoding(json.loads(resp.content), details.__dict__, "virgin get") utc = UTC() - self.alter_field(url, details, 'start_date', datetime.datetime(2012,11,12,1,30, tzinfo=utc)) - self.alter_field(url, details, 'start_date', datetime.datetime(2012,11,1,13,30, tzinfo=utc)) - self.alter_field(url, details, 'end_date', datetime.datetime(2013,2,12,1,30, tzinfo=utc)) - self.alter_field(url, details, 'enrollment_start', datetime.datetime(2012,10,12,1,30, tzinfo=utc)) + self.alter_field(url, details, 'start_date', datetime.datetime(2012, 11, 12, 1, 30, tzinfo=utc)) + self.alter_field(url, details, 'start_date', datetime.datetime(2012, 11, 1, 13, 30, tzinfo=utc)) + self.alter_field(url, details, 'end_date', datetime.datetime(2013, 2, 12, 1, 30, tzinfo=utc)) + self.alter_field(url, details, 'enrollment_start', datetime.datetime(2012, 10, 12, 1, 30, tzinfo=utc)) - self.alter_field(url, details, 'enrollment_end', datetime.datetime(2012,11,15,1,30, tzinfo=utc)) + self.alter_field(url, details, 'enrollment_end', datetime.datetime(2012, 11, 15, 1, 30, tzinfo=utc)) self.alter_field(url, details, 'overview', "Overview") self.alter_field(url, details, 'intro_video', "intro_video") self.alter_field(url, details, 'effort', "effort") @@ -170,7 +172,7 @@ class CourseDetailsViewTest(CourseTestCase): self.assertEqual(details['overview'], encoded['overview'], context + " overviews not ==") self.assertEqual(details['intro_video'], encoded.get('intro_video', None), context + " intro_video not ==") self.assertEqual(details['effort'], encoded['effort'], context + " efforts not ==") - + def compare_date_fields(self, details, encoded, context, field): if details[field] is not None: if field in encoded and encoded[field] is not None: @@ -182,14 +184,15 @@ class CourseDetailsViewTest(CourseTestCase): else: details_encoded = jsdate_to_time(details[field]) dt2 = ConvertersTestCase.struct_to_datetime(details_encoded) - + expected_delta = datetime.timedelta(0) self.assertEqual(dt1 - dt2, expected_delta, str(dt1) + "!=" + str(dt2) + " at " + context) else: self.fail(field + " missing from encoded but in details at " + context) elif field in encoded and encoded[field] is not None: self.fail(field + " included in encoding but missing from details at " + context) - + + class CourseGradingTest(CourseTestCase): def test_initial_grader(self): descriptor = get_modulestore(self.course_location).get_item(self.course_location) @@ -209,56 +212,56 @@ class CourseGradingTest(CourseTestCase): self.assertEqual(self.course_location, test_grader.course_location, "Course locations") self.assertIsNotNone(test_grader.graders, "No graders") self.assertIsNotNone(test_grader.grade_cutoffs, "No cutoffs") - + for i, grader in enumerate(test_grader.graders): subgrader = CourseGradingModel.fetch_grader(self.course_location, i) self.assertDictEqual(grader, subgrader, str(i) + "th graders not equal") - + subgrader = CourseGradingModel.fetch_grader(self.course_location.list(), 0) self.assertDictEqual(test_grader.graders[0], subgrader, "failed with location as list") - + def test_fetch_cutoffs(self): test_grader = CourseGradingModel.fetch_cutoffs(self.course_location) # ??? should this check that it's at least a dict? (expected is { "pass" : 0.5 } I think) self.assertIsNotNone(test_grader, "No cutoffs via fetch") - + test_grader = CourseGradingModel.fetch_cutoffs(self.course_location.url()) self.assertIsNotNone(test_grader, "No cutoffs via fetch with url") - + def test_fetch_grace(self): test_grader = CourseGradingModel.fetch_grace_period(self.course_location) # almost a worthless test self.assertIn('grace_period', test_grader, "No grace via fetch") - + test_grader = CourseGradingModel.fetch_grace_period(self.course_location.url()) self.assertIn('grace_period', test_grader, "No cutoffs via fetch with url") - + def test_update_from_json(self): test_grader = CourseGradingModel.fetch(self.course_location) altered_grader = CourseGradingModel.update_from_json(test_grader.__dict__) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "Noop update") - + test_grader.graders[0]['weight'] = test_grader.graders[0].get('weight') * 2 altered_grader = CourseGradingModel.update_from_json(test_grader.__dict__) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "Weight[0] * 2") - + test_grader.grade_cutoffs['D'] = 0.3 altered_grader = CourseGradingModel.update_from_json(test_grader.__dict__) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "cutoff add D") - + test_grader.grace_period = {'hours' : '4'} altered_grader = CourseGradingModel.update_from_json(test_grader.__dict__) self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "4 hour grace period") - + def test_update_grader_from_json(self): test_grader = CourseGradingModel.fetch(self.course_location) altered_grader = CourseGradingModel.update_grader_from_json(test_grader.course_location, test_grader.graders[1]) self.assertDictEqual(test_grader.graders[1], altered_grader, "Noop update") - + test_grader.graders[1]['min_count'] = test_grader.graders[1].get('min_count') + 2 altered_grader = CourseGradingModel.update_grader_from_json(test_grader.course_location, test_grader.graders[1]) self.assertDictEqual(test_grader.graders[1], altered_grader, "min_count[1] + 2") - + test_grader.graders[1]['drop_count'] = test_grader.graders[1].get('drop_count') + 1 altered_grader = CourseGradingModel.update_grader_from_json(test_grader.course_location, test_grader.graders[1]) self.assertDictEqual(test_grader.graders[1], altered_grader, "drop_count[1] + 2") diff --git a/cms/djangoapps/contentstore/tests/test_course_updates.py b/cms/djangoapps/contentstore/tests/test_course_updates.py index 96e4468b31..c57f1322f5 100644 --- a/cms/djangoapps/contentstore/tests/test_course_updates.py +++ b/cms/djangoapps/contentstore/tests/test_course_updates.py @@ -2,29 +2,30 @@ from cms.djangoapps.contentstore.tests.test_course_settings import CourseTestCas from django.core.urlresolvers import reverse import json + class CourseUpdateTest(CourseTestCase): def test_course_update(self): # first get the update to force the creation - url = reverse('course_info', kwargs={'org' : self.course_location.org, 'course' : self.course_location.course, - 'name' : self.course_location.name }) + url = reverse('course_info', kwargs={'org': self.course_location.org, 'course': self.course_location.course, + 'name': self.course_location.name}) self.client.get(url) content = '' - payload = { 'content' : content, - 'date' : 'January 8, 2013'} - url = reverse('course_info', kwargs={'org' : self.course_location.org, 'course' : self.course_location.course, - 'provided_id' : ''}) - + payload = {'content': content, + 'date': 'January 8, 2013'} + url = reverse('course_info', kwargs={'org': self.course_location.org, 'course': self.course_location.course, + 'provided_id': ''}) + resp = self.client.post(url, json.dumps(payload), "application/json") - - payload= json.loads(resp.content) - + + payload = json.loads(resp.content) + self.assertHTMLEqual(content, payload['content'], "single iframe") - - url = reverse('course_info', kwargs={'org' : self.course_location.org, 'course' : self.course_location.course, - 'provided_id' : payload['id']}) + + url = reverse('course_info', kwargs={'org': self.course_location.org, 'course': self.course_location.course, + 'provided_id': payload['id']}) content += '
            div

            p

            ' payload['content'] = content resp = self.client.post(url, json.dumps(payload), "application/json") - + self.assertHTMLEqual(content, json.loads(resp.content)['content'], "iframe w/ div") diff --git a/cms/djangoapps/contentstore/tests/test_utils.py b/cms/djangoapps/contentstore/tests/test_utils.py index 6811d64c12..09e3b045f9 100644 --- a/cms/djangoapps/contentstore/tests/test_utils.py +++ b/cms/djangoapps/contentstore/tests/test_utils.py @@ -2,15 +2,16 @@ from cms.djangoapps.contentstore import utils import mock from django.test import TestCase + class LMSLinksTestCase(TestCase): def about_page_test(self): - location = 'i4x','mitX','101','course', 'test' + location = 'i4x', 'mitX', '101', 'course', 'test' utils.get_course_id = mock.Mock(return_value="mitX/101/test") link = utils.get_lms_link_for_about_page(location) self.assertEquals(link, "//localhost:8000/courses/mitX/101/test/about") def ls_link_test(self): - location = 'i4x','mitX','101','vertical', 'contacting_us' + location = 'i4x', 'mitX', '101', 'vertical', 'contacting_us' utils.get_course_id = mock.Mock(return_value="mitX/101/test") link = utils.get_lms_link_for_item(location, False) self.assertEquals(link, "//localhost:8000/courses/mitX/101/test/jump_to/i4x://mitX/101/vertical/contacting_us") diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index df2e4dcc79..9af5b09276 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -28,6 +28,7 @@ from xmodule.seq_module import SequenceDescriptor from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from utils import ModuleStoreTestCase, parse_json, user, registration + class ContentStoreTestCase(ModuleStoreTestCase): def _login(self, email, pw): """Login. View should always return 200. The success/fail is in the diff --git a/cms/djangoapps/contentstore/tests/utils.py b/cms/djangoapps/contentstore/tests/utils.py index 7fa5b76685..4e3510463f 100644 --- a/cms/djangoapps/contentstore/tests/utils.py +++ b/cms/djangoapps/contentstore/tests/utils.py @@ -11,8 +11,9 @@ from django.contrib.auth.models import User import xmodule.modulestore.django from xmodule.templates import update_templates + class ModuleStoreTestCase(TestCase): - """ Subclass for any test case that uses the mongodb + """ Subclass for any test case that uses the mongodb module store. This populates a uniquely named modulestore collection with templates before running the TestCase and drops it they are finished. """ @@ -22,7 +23,7 @@ class ModuleStoreTestCase(TestCase): # Use the current seconds since epoch to differentiate # the mongo collections on jenkins. - sec_since_epoch = '%s' % int(time()*100) + sec_since_epoch = '%s' % int(time() * 100) self.orig_MODULESTORE = copy.deepcopy(settings.MODULESTORE) self.test_MODULESTORE = self.orig_MODULESTORE self.test_MODULESTORE['default']['OPTIONS']['collection'] = 'modulestore_%s' % sec_since_epoch @@ -50,14 +51,17 @@ class ModuleStoreTestCase(TestCase): super(ModuleStoreTestCase, self)._post_teardown() + def parse_json(response): """Parse response, which is assumed to be json""" return json.loads(response.content) + def user(email): """look up a user by email""" return User.objects.get(email=email) + def registration(email): """look up registration object by email""" return Registration.objects.get(user__email=email) diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index da2993e463..b14dd8b353 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -5,18 +5,20 @@ from xmodule.modulestore.exceptions import ItemNotFoundError DIRECT_ONLY_CATEGORIES = ['course', 'chapter', 'sequential', 'about', 'static_tab', 'course_info'] + def get_modulestore(location): """ Returns the correct modulestore to use for modifying the specified location """ if not isinstance(location, Location): location = Location(location) - + if location.category in DIRECT_ONLY_CATEGORIES: return modulestore('direct') else: return modulestore() + def get_course_location_for_item(location): ''' cdodge: for a given Xmodule, return the course that it belongs to @@ -46,6 +48,7 @@ def get_course_location_for_item(location): return location + def get_course_for_item(location): ''' cdodge: for a given Xmodule, return the course that it belongs to @@ -85,6 +88,7 @@ def get_lms_link_for_item(location, preview=False): return lms_link + def get_lms_link_for_about_page(location): """ Returns the url to the course about page from the location tuple. @@ -99,6 +103,7 @@ def get_lms_link_for_about_page(location): return lms_link + def get_course_id(location): """ Returns the course_id from a given the location tuple. @@ -106,6 +111,7 @@ def get_course_id(location): # TODO: These will need to be changed to point to the particular instance of this problem in the particular course return modulestore().get_containing_courses(Location(location))[0].id + class UnitState(object): draft = 'draft' private = 'private' @@ -135,6 +141,7 @@ def compute_unit_state(unit): def get_date_display(date): return date.strftime("%d %B, %Y at %I:%M %p") + def update_item(location, value): """ If value is None, delete the db entry. Otherwise, update it using the correct modulestore. @@ -142,4 +149,4 @@ def update_item(location, value): if value is None: get_modulestore(location).delete_item(location) else: - get_modulestore(location).update_item(location, value) \ No newline at end of file + get_modulestore(location).update_item(location, value) diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index fb63cb34ed..137e71b24a 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -81,6 +81,7 @@ def signup(request): csrf_token = csrf(request)['csrf_token'] return render_to_response('signup.html', {'csrf': csrf_token}) + @ssl_login_shortcut @ensure_csrf_cookie def login_page(request): @@ -114,7 +115,7 @@ def index(request): courses = filter(course_filter, courses) return render_to_response('index.html', { - 'new_course_template' : Location('i4x', 'edx', 'templates', 'course', 'Empty'), + 'new_course_template': Location('i4x', 'edx', 'templates', 'course', 'Empty'), 'courses': [(course.metadata.get('display_name'), reverse('course_index', args=[ course.location.org, @@ -159,10 +160,10 @@ def course_index(request, org, course, name): if not has_access(request.user, location): raise PermissionDenied() - upload_asset_callback_url = reverse('upload_asset', kwargs = { - 'org' : org, - 'course' : course, - 'coursename' : name + upload_asset_callback_url = reverse('upload_asset', kwargs={ + 'org': org, + 'course': course, + 'coursename': name }) course = modulestore().get_item(location) @@ -213,7 +214,7 @@ def edit_subsection(request, location): # remove all metadata from the generic dictionary that is presented in a more normalized UI - policy_metadata = dict((key,value) for key, value in item.metadata.iteritems() + policy_metadata = dict((key, value) for key, value in item.metadata.iteritems() if key not in ['display_name', 'start', 'due', 'format'] and key not in item.system_metadata_fields) can_view_live = False @@ -233,9 +234,9 @@ def edit_subsection(request, location): 'course_graders': json.dumps(CourseGradingModel.fetch(course.location).graders), 'parent_location': course.location, 'parent_item': parent, - 'policy_metadata' : policy_metadata, - 'subsection_units' : subsection_units, - 'can_view_live' : can_view_live + 'policy_metadata': policy_metadata, + 'subsection_units': subsection_units, + 'can_view_live': can_view_live }) @@ -294,7 +295,7 @@ def edit_unit(request, location): # so let's generate the link url here # need to figure out where this item is in the list of children as the preview will need this - index =1 + index = 1 for child in containing_subsection.get_children(): if child.location == item.location: break @@ -348,6 +349,7 @@ def preview_component(request, location): 'editor': wrap_xmodule(component.get_html, component, 'xmodule_edit.html')(), }) + @expect_json @login_required @ensure_csrf_cookie @@ -362,7 +364,7 @@ def assignment_type_update(request, org, course, category, name): if request.method == 'GET': return HttpResponse(json.dumps(CourseGradingModel.get_section_grader_type(location)), mimetype="application/json") - elif request.method == 'POST': # post or put, doesn't matter. + elif request.method == 'POST': # post or put, doesn't matter. return HttpResponse(json.dumps(CourseGradingModel.update_section_grader_type(location, request.POST)), mimetype="application/json") @@ -527,7 +529,7 @@ def load_preview_module(request, preview_id, descriptor, instance_state, shared_ module.get_html = replace_static_urls( module.get_html, module.metadata.get('data_dir', module.location.course), - course_namespace = Location([module.location.tag, module.location.org, module.location.course, None, None]) + course_namespace=Location([module.location.tag, module.location.org, module.location.course, None, None]) ) save_preview_state(request, preview_id, descriptor.location.url(), module.get_instance_state(), module.get_shared_state()) @@ -588,7 +590,7 @@ def delete_item(request): # semantics of delete_item whereby the store is draft aware. Right now calling # delete_item on a vertical tries to delete the draft version leaving the # requested delete to never occur - if item.location.revision is None and item.location.category=='vertical' and delete_all_versions: + if item.location.revision is None and item.location.category == 'vertical' and delete_all_versions: modulestore('direct').delete_item(item.location) return HttpResponse() @@ -664,6 +666,7 @@ def create_draft(request): return HttpResponse() + @login_required @expect_json def publish_draft(request): @@ -693,6 +696,7 @@ def unpublish_unit(request): return HttpResponse() + @login_required @expect_json def clone_item(request): @@ -725,6 +729,8 @@ def clone_item(request): #@login_required #@ensure_csrf_cookie + + def upload_asset(request, org, course, coursename): ''' cdodge: this method allows for POST uploading of files into the course asset library, which will @@ -775,11 +781,11 @@ def upload_asset(request, org, course, coursename): # readback the saved content - we need the database timestamp readback = contentstore().find(content.location) - response_payload = {'displayname' : content.name, - 'uploadDate' : get_date_display(readback.last_modified_at), - 'url' : StaticContent.get_url_path_from_location(content.location), - 'thumb_url' : StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_content is not None else None, - 'msg' : 'Upload completed' + response_payload = {'displayname': content.name, + 'uploadDate': get_date_display(readback.last_modified_at), + 'url': StaticContent.get_url_path_from_location(content.location), + 'thumb_url': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_content is not None else None, + 'msg': 'Upload completed' } response = HttpResponse(json.dumps(response_payload)) @@ -789,6 +795,8 @@ def upload_asset(request, org, course, coursename): ''' This view will return all CMS users who are editors for the specified course ''' + + @login_required @ensure_csrf_cookie def manage_users(request, location): @@ -803,16 +811,16 @@ def manage_users(request, location): 'active_tab': 'users', 'context_course': course_module, 'staff': get_users_in_course_group_by_role(location, STAFF_ROLE_NAME), - 'add_user_postback_url' : reverse('add_user', args=[location]).rstrip('/'), - 'remove_user_postback_url' : reverse('remove_user', args=[location]).rstrip('/'), - 'allow_actions' : has_access(request.user, location, role=INSTRUCTOR_ROLE_NAME), - 'request_user_id' : request.user.id + 'add_user_postback_url': reverse('add_user', args=[location]).rstrip('/'), + 'remove_user_postback_url': reverse('remove_user', args=[location]).rstrip('/'), + 'allow_actions': has_access(request.user, location, role=INSTRUCTOR_ROLE_NAME), + 'request_user_id': request.user.id }) -def create_json_response(errmsg = None): +def create_json_response(errmsg=None): if errmsg is not None: - resp = HttpResponse(json.dumps({'Status': 'Failed', 'ErrMsg' : errmsg})) + resp = HttpResponse(json.dumps({'Status': 'Failed', 'ErrMsg': errmsg})) else: resp = HttpResponse(json.dumps({'Status': 'OK'})) @@ -822,13 +830,15 @@ def create_json_response(errmsg = None): This POST-back view will add a user - specified by email - to the list of editors for the specified course ''' + + @expect_json @login_required @ensure_csrf_cookie def add_user(request, location): email = request.POST["email"] - if email=='': + if email == '': return create_json_response('Please specify an email address.') # check that logged in user has admin permissions to this course @@ -854,6 +864,8 @@ def add_user(request, location): This POST-back view will remove a user - specified by email - from the list of editors for the specified course ''' + + @expect_json @login_required @ensure_csrf_cookie @@ -881,6 +893,7 @@ def remove_user(request, location): def landing(request, org, course, coursename): return render_to_response('temp-course-landing.html', {}) + @login_required @ensure_csrf_cookie def static_pages(request, org, course, coursename): @@ -921,7 +934,7 @@ def reorder_static_tabs(request): return HttpResponseBadRequest() # load all reference tabs, return BadRequest if we can't find any of them - tab_items =[] + tab_items = [] for tab in tabs: item = modulestore('direct').get_item(Location(tab)) if item is None: @@ -935,8 +948,8 @@ def reorder_static_tabs(request): for tab in course.tabs: if tab['type'] == 'static_tab': reordered_tabs.append({'type': 'static_tab', - 'name' : tab_items[static_tab_idx].metadata.get('display_name'), - 'url_slug' : tab_items[static_tab_idx].location.name}) + 'name': tab_items[static_tab_idx].metadata.get('display_name'), + 'url_slug': tab_items[static_tab_idx].location.name}) static_tab_idx += 1 else: reordered_tabs.append(tab) @@ -980,10 +993,11 @@ def edit_tabs(request, org, course, coursename): return render_to_response('edit-tabs.html', { 'active_tab': 'pages', - 'context_course':course_item, + 'context_course': course_item, 'components': components }) + def not_found(request): return render_to_response('error.html', {'error': '404'}) @@ -1014,11 +1028,12 @@ def course_info(request, org, course, name, provided_id=None): return render_to_response('course_info.html', { 'active_tab': 'courseinfo-tab', 'context_course': course_module, - 'url_base' : "/" + org + "/" + course + "/", - 'course_updates' : json.dumps(get_course_updates(location)), + 'url_base': "/" + org + "/" + course + "/", + 'course_updates': json.dumps(get_course_updates(location)), 'handouts_location': Location(['i4x', org, course, 'course_info', 'handouts']).url() }) + @expect_json @login_required @ensure_csrf_cookie @@ -1075,8 +1090,8 @@ def module_info(request, module_location): else: real_method = request.method - rewrite_static_links = request.GET.get('rewrite_url_links','True') in ['True', 'true'] - logging.debug('rewrite_static_links = {0} {1}'.format(request.GET.get('rewrite_url_links','False'), rewrite_static_links)) + rewrite_static_links = request.GET.get('rewrite_url_links', 'True') in ['True', 'true'] + logging.debug('rewrite_static_links = {0} {1}'.format(request.GET.get('rewrite_url_links', 'False'), rewrite_static_links)) # check that logged in user has permissions to this item if not has_access(request.user, location): @@ -1089,6 +1104,7 @@ def module_info(request, module_location): else: return HttpResponseBadRequest() + @login_required @ensure_csrf_cookie def get_course_settings(request, org, course, name): @@ -1109,9 +1125,10 @@ def get_course_settings(request, org, course, name): return render_to_response('settings.html', { 'active_tab': 'settings', 'context_course': course_module, - 'course_details' : json.dumps(course_details, cls=CourseSettingsEncoder) + 'course_details': json.dumps(course_details, cls=CourseSettingsEncoder) }) + @expect_json @login_required @ensure_csrf_cookie @@ -1137,12 +1154,13 @@ def course_settings_updates(request, org, course, name, section): if request.method == 'GET': # Cannot just do a get w/o knowing the course name :-( - return HttpResponse(json.dumps(manager.fetch(Location(['i4x', org, course, 'course',name])), cls=CourseSettingsEncoder), + return HttpResponse(json.dumps(manager.fetch(Location(['i4x', org, course, 'course', name])), cls=CourseSettingsEncoder), mimetype="application/json") - elif request.method == 'POST': # post or put, doesn't matter. + elif request.method == 'POST': # post or put, doesn't matter. return HttpResponse(json.dumps(manager.update_from_json(request.POST), cls=CourseSettingsEncoder), mimetype="application/json") + @expect_json @login_required @ensure_csrf_cookie @@ -1167,14 +1185,14 @@ def course_grader_updates(request, org, course, name, grader_index=None): if real_method == 'GET': # Cannot just do a get w/o knowing the course name :-( - return HttpResponse(json.dumps(CourseGradingModel.fetch_grader(Location(['i4x', org, course, 'course',name]), grader_index)), + return HttpResponse(json.dumps(CourseGradingModel.fetch_grader(Location(['i4x', org, course, 'course', name]), grader_index)), mimetype="application/json") elif real_method == "DELETE": # ??? Shoudl this return anything? Perhaps success fail? - CourseGradingModel.delete_grader(Location(['i4x', org, course, 'course',name]), grader_index) + CourseGradingModel.delete_grader(Location(['i4x', org, course, 'course', name]), grader_index) return HttpResponse() - elif request.method == 'POST': # post or put, doesn't matter. - return HttpResponse(json.dumps(CourseGradingModel.update_grader_from_json(Location(['i4x', org, course, 'course',name]), request.POST)), + elif request.method == 'POST': # post or put, doesn't matter. + return HttpResponse(json.dumps(CourseGradingModel.update_grader_from_json(Location(['i4x', org, course, 'course', name]), request.POST)), mimetype="application/json") @@ -1193,10 +1211,10 @@ def asset_index(request, org, course, name): raise PermissionDenied() - upload_asset_callback_url = reverse('upload_asset', kwargs = { - 'org' : org, - 'course' : course, - 'coursename' : name + upload_asset_callback_url = reverse('upload_asset', kwargs={ + 'org': org, + 'course': course, + 'coursename': name }) course_module = modulestore().get_item(location) @@ -1237,13 +1255,14 @@ def asset_index(request, org, course, name): def edge(request): return render_to_response('university_profiles/edge.html', {}) + @login_required @expect_json def create_new_course(request): # This logic is repeated in xmodule/modulestore/tests/factories.py # so if you change anything here, you need to also change it there. # TODO: write a test that creates two courses, one with the factory and - # the other with this method, then compare them to make sure they are + # the other with this method, then compare them to make sure they are # equivalent. template = Location(request.POST['template']) org = request.POST.get('org') @@ -1288,6 +1307,7 @@ def create_new_course(request): return HttpResponse(json.dumps({'id': new_course.location.url()})) + def initialize_course_tabs(course): # set up the default tabs # I've added this because when we add static tabs, the LMS either expects a None for the tabs list or @@ -1297,7 +1317,7 @@ def initialize_course_tabs(course): # This logic is repeated in xmodule/modulestore/tests/factories.py # so if you change anything here, you need to also change it there. - course.tabs = [{"type": "courseware"}, + course.tabs = [{"type": "courseware"}, {"type": "course_info", "name": "Course Info"}, {"type": "discussion", "name": "Discussion"}, {"type": "wiki", "name": "Wiki"}, @@ -1305,6 +1325,7 @@ def initialize_course_tabs(course): modulestore('direct').update_metadata(course.location.url(), course.own_metadata) + @ensure_csrf_cookie @login_required def import_course(request, org, course, name): @@ -1343,7 +1364,7 @@ def import_course(request, org, course, name): # find the 'course.xml' file - for r,d,f in os.walk(course_dir): + for r, d, f in os.walk(course_dir): for files in f: if files == 'course.xml': break @@ -1357,10 +1378,10 @@ def import_course(request, org, course, name): if r != course_dir: for fname in os.listdir(r): - shutil.move(r/fname, course_dir) + shutil.move(r / fname, course_dir) module_store, course_items = import_from_xml(modulestore('direct'), settings.GITHUB_REPO_ROOT, - [course_subdir], load_error_modules=False, static_content_store=contentstore(), target_location_namespace = Location(location)) + [course_subdir], load_error_modules=False, static_content_store=contentstore(), target_location_namespace=Location(location)) # we can blow this away when we're done importing. shutil.rmtree(course_dir) @@ -1376,12 +1397,13 @@ def import_course(request, org, course, name): return render_to_response('import.html', { 'context_course': course_module, 'active_tab': 'import', - 'successful_import_redirect_url' : reverse('course_index', args=[ + 'successful_import_redirect_url': reverse('course_index', args=[ course_module.location.org, course_module.location.course, course_module.location.name]) }) + @ensure_csrf_cookie @login_required def generate_export_course(request, org, course, name): @@ -1391,7 +1413,7 @@ def generate_export_course(request, org, course, name): raise PermissionDenied() loc = Location(location) - export_file = NamedTemporaryFile(prefix=name+'.', suffix=".tar.gz") + export_file = NamedTemporaryFile(prefix=name + '.', suffix=".tar.gz") root_dir = path(mkdtemp()) @@ -1404,11 +1426,11 @@ def generate_export_course(request, org, course, name): logging.debug('tar file being generated at {0}'.format(export_file.name)) tf = tarfile.open(name=export_file.name, mode='w:gz') - tf.add(root_dir/name, arcname=name) + tf.add(root_dir / name, arcname=name) tf.close() # remove temp dir - shutil.rmtree(root_dir/name) + shutil.rmtree(root_dir / name) wrapper = FileWrapper(export_file) response = HttpResponse(wrapper, content_type='application/x-tgz') @@ -1430,9 +1452,10 @@ def export_course(request, org, course, name): return render_to_response('export.html', { 'context_course': course_module, 'active_tab': 'export', - 'successful_import_redirect_url' : '' + 'successful_import_redirect_url': '' }) + def event(request): ''' A noop to swallow the analytics call so that cms methods don't spook and poor developers looking at diff --git a/cms/djangoapps/models/settings/course_details.py b/cms/djangoapps/models/settings/course_details.py index d01e784d74..b27f4e3804 100644 --- a/cms/djangoapps/models/settings/course_details.py +++ b/cms/djangoapps/models/settings/course_details.py @@ -31,16 +31,16 @@ class CourseDetails(object): """ if not isinstance(course_location, Location): course_location = Location(course_location) - + course = cls(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) - + course.start_date = descriptor.start course.end_date = descriptor.end course.enrollment_start = descriptor.enrollment_start course.enrollment_end = descriptor.enrollment_end - + temploc = course_location._replace(category='about', name='syllabus') try: course.syllabus = get_modulestore(temploc).get_item(temploc).definition['data'] @@ -52,32 +52,32 @@ class CourseDetails(object): course.overview = get_modulestore(temploc).get_item(temploc).definition['data'] except ItemNotFoundError: pass - + temploc = temploc._replace(name='effort') try: course.effort = get_modulestore(temploc).get_item(temploc).definition['data'] except ItemNotFoundError: pass - + temploc = temploc._replace(name='video') try: raw_video = get_modulestore(temploc).get_item(temploc).definition['data'] - course.intro_video = CourseDetails.parse_video_tag(raw_video) + course.intro_video = CourseDetails.parse_video_tag(raw_video) except ItemNotFoundError: pass - + return course - + @classmethod def update_from_json(cls, jsondict): """ Decode the json into CourseDetails and save any changed attrs to the db """ - ## TODO make it an error for this to be undefined & for it to not be retrievable from modulestore + ## TODO make it an error for this to be undefined & for it to not be retrievable from modulestore course_location = jsondict['course_location'] ## Will probably want to cache the inflight courses because every blur generates an update descriptor = get_modulestore(course_location).get_item(course_location) - + dirty = False if 'start_date' in jsondict: @@ -87,7 +87,7 @@ class CourseDetails(object): if converted != descriptor.start: dirty = True descriptor.start = converted - + if 'end_date' in jsondict: converted = jsdate_to_time(jsondict['end_date']) else: @@ -96,7 +96,7 @@ class CourseDetails(object): if converted != descriptor.end: dirty = True descriptor.end = converted - + if 'enrollment_start' in jsondict: converted = jsdate_to_time(jsondict['enrollment_start']) else: @@ -105,7 +105,7 @@ class CourseDetails(object): if converted != descriptor.enrollment_start: dirty = True descriptor.enrollment_start = converted - + if 'enrollment_end' in jsondict: converted = jsdate_to_time(jsondict['enrollment_end']) else: @@ -114,10 +114,10 @@ class CourseDetails(object): if converted != descriptor.enrollment_end: dirty = True descriptor.enrollment_end = converted - + if dirty: get_modulestore(course_location).update_metadata(course_location, descriptor.metadata) - + # NOTE: below auto writes to the db w/o verifying that any of the fields actually changed # to make faster, could compare against db or could have client send over a list of which fields changed. temploc = Location(course_location)._replace(category='about', name='syllabus') @@ -125,19 +125,19 @@ class CourseDetails(object): temploc = temploc._replace(name='overview') update_item(temploc, jsondict['overview']) - + temploc = temploc._replace(name='effort') update_item(temploc, jsondict['effort']) - + temploc = temploc._replace(name='video') recomposed_video_tag = CourseDetails.recompose_video_tag(jsondict['intro_video']) update_item(temploc, recomposed_video_tag) - - + + # Could just generate and return a course obj w/o doing any db reads, but I put the reads in as a means to confirm # it persisted correctly return CourseDetails.fetch(course_location) - + @staticmethod def parse_video_tag(raw_video): """ @@ -147,17 +147,17 @@ class CourseDetails(object): """ if not raw_video: return None - + keystring_matcher = re.search('(?<=embed/)[a-zA-Z0-9_-]+', raw_video) if keystring_matcher is None: keystring_matcher = re.search('' return result - + # TODO move to a more general util? Is there a better way to do the isinstance model check? class CourseSettingsEncoder(json.JSONEncoder): diff --git a/cms/djangoapps/models/settings/course_grading.py b/cms/djangoapps/models/settings/course_grading.py index 9cfa18c8c9..f4c6fd3d7c 100644 --- a/cms/djangoapps/models/settings/course_grading.py +++ b/cms/djangoapps/models/settings/course_grading.py @@ -6,55 +6,55 @@ from util import converters class CourseGradingModel(object): """ - Basically a DAO and Model combo for CRUD operations pertaining to grading policy. + Basically a DAO and Model combo for CRUD operations pertaining to grading policy. """ def __init__(self, course_descriptor): self.course_location = course_descriptor.location - self.graders = [CourseGradingModel.jsonize_grader(i, grader) for i, grader in enumerate(course_descriptor.raw_grader)] # weights transformed to ints [0..100] + self.graders = [CourseGradingModel.jsonize_grader(i, grader) for i, grader in enumerate(course_descriptor.raw_grader)] # weights transformed to ints [0..100] self.grade_cutoffs = course_descriptor.grade_cutoffs self.grace_period = CourseGradingModel.convert_set_grace_period(course_descriptor) - - @classmethod + + @classmethod def fetch(cls, course_location): """ Fetch the course details for the given course from persistence and return a CourseDetails model. """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) model = cls(descriptor) return model - + @staticmethod def fetch_grader(course_location, index): """ - Fetch the course's nth grader + Fetch the course's nth grader Returns an empty dict if there's no such grader. """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) # # ??? it would be good if these had the course_location in them so that they stand alone sufficiently # # but that would require not using CourseDescriptor's field directly. Opinions? - index = int(index) - if len(descriptor.raw_grader) > index: + index = int(index) + if len(descriptor.raw_grader) > index: return CourseGradingModel.jsonize_grader(index, descriptor.raw_grader[index]) - + # return empty model else: return { - "id" : index, - "type" : "", - "min_count" : 0, - "drop_count" : 0, - "short_label" : None, - "weight" : 0 + "id": index, + "type": "", + "min_count": 0, + "drop_count": 0, + "short_label": None, + "weight": 0 } - + @staticmethod def fetch_cutoffs(course_location): """ @@ -62,7 +62,7 @@ class CourseGradingModel(object): """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) return descriptor.grade_cutoffs @@ -73,10 +73,10 @@ class CourseGradingModel(object): """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) - return {'grace_period' : CourseGradingModel.convert_set_grace_period(descriptor) } - + return {'grace_period': CourseGradingModel.convert_set_grace_period(descriptor)} + @staticmethod def update_from_json(jsondict): """ @@ -85,32 +85,32 @@ class CourseGradingModel(object): """ course_location = jsondict['course_location'] descriptor = get_modulestore(course_location).get_item(course_location) - + graders_parsed = [CourseGradingModel.parse_grader(jsonele) for jsonele in jsondict['graders']] - + descriptor.raw_grader = graders_parsed descriptor.grade_cutoffs = jsondict['grade_cutoffs'] - + get_modulestore(course_location).update_item(course_location, descriptor.definition['data']) CourseGradingModel.update_grace_period_from_json(course_location, jsondict['grace_period']) - + return CourseGradingModel.fetch(course_location) - - + + @staticmethod def update_grader_from_json(course_location, grader): """ - Create or update the grader of the given type (string key) for the given course. Returns the modified + Create or update the grader of the given type (string key) for the given course. Returns the modified grader which is a full model on the client but not on the server (just a dict) """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) # # ??? it would be good if these had the course_location in them so that they stand alone sufficiently # # but that would require not using CourseDescriptor's field directly. Opinions? - # parse removes the id; so, grab it before parse + # parse removes the id; so, grab it before parse index = int(grader.get('id', len(descriptor.raw_grader))) grader = CourseGradingModel.parse_grader(grader) @@ -118,11 +118,11 @@ class CourseGradingModel(object): descriptor.raw_grader[index] = grader else: descriptor.raw_grader.append(grader) - + get_modulestore(course_location).update_item(course_location, descriptor.definition['data']) - + return CourseGradingModel.jsonize_grader(index, descriptor.raw_grader[index]) - + @staticmethod def update_cutoffs_from_json(course_location, cutoffs): """ @@ -131,18 +131,18 @@ class CourseGradingModel(object): """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) descriptor.grade_cutoffs = cutoffs get_modulestore(course_location).update_item(course_location, descriptor.definition['data']) - + return cutoffs - - + + @staticmethod def update_grace_period_from_json(course_location, graceperiodjson): """ - Update the course's default grace period. Incoming dict is {hours: h, minutes: m} possibly as a + Update the course's default grace period. Incoming dict is {hours: h, minutes: m} possibly as a grace_period entry in an enclosing dict. It is also safe to call this method with a value of None for graceperiodjson. """ @@ -160,7 +160,7 @@ class CourseGradingModel(object): descriptor = get_modulestore(course_location).get_item(course_location) descriptor.metadata['graceperiod'] = grace_rep get_modulestore(course_location).update_metadata(course_location, descriptor.metadata) - + @staticmethod def delete_grader(course_location, index): """ @@ -168,16 +168,16 @@ class CourseGradingModel(object): """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) - index = int(index) + index = int(index) if index < len(descriptor.raw_grader): del descriptor.raw_grader[index] # force propagation to definition descriptor.raw_grader = descriptor.raw_grader get_modulestore(course_location).update_item(course_location, descriptor.definition['data']) - - # NOTE cannot delete cutoffs. May be useful to reset + + # NOTE cannot delete cutoffs. May be useful to reset @staticmethod def delete_cutoffs(course_location, cutoffs): """ @@ -185,13 +185,13 @@ class CourseGradingModel(object): """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) descriptor.grade_cutoffs = descriptor.defaut_grading_policy['GRADE_CUTOFFS'] get_modulestore(course_location).update_item(course_location, descriptor.definition['data']) - + return descriptor.grade_cutoffs - + @staticmethod def delete_grace_period(course_location): """ @@ -199,28 +199,28 @@ class CourseGradingModel(object): """ if not isinstance(course_location, Location): course_location = Location(course_location) - + descriptor = get_modulestore(course_location).get_item(course_location) if 'graceperiod' in descriptor.metadata: del descriptor.metadata['graceperiod'] get_modulestore(course_location).update_metadata(course_location, descriptor.metadata) - + @staticmethod def get_section_grader_type(location): if not isinstance(location, Location): location = Location(location) - + descriptor = get_modulestore(location).get_item(location) return { - "graderType" : descriptor.metadata.get('format', u"Not Graded"), - "location" : location, - "id" : 99 # just an arbitrary value to + "graderType": descriptor.metadata.get('format', u"Not Graded"), + "location": location, + "id": 99 # just an arbitrary value to } - + @staticmethod def update_section_grader_type(location, jsondict): if not isinstance(location, Location): location = Location(location) - + descriptor = get_modulestore(location).get_item(location) if 'graderType' in jsondict and jsondict['graderType'] != u"Not Graded": descriptor.metadata['format'] = jsondict.get('graderType') @@ -228,10 +228,10 @@ class CourseGradingModel(object): else: if 'format' in descriptor.metadata: del descriptor.metadata['format'] if 'graded' in descriptor.metadata: del descriptor.metadata['graded'] - - get_modulestore(location).update_metadata(location, descriptor.metadata) - - + + get_modulestore(location).update_metadata(location, descriptor.metadata) + + @staticmethod def convert_set_grace_period(descriptor): # 5 hours 59 minutes 59 seconds => converted to iso format @@ -245,13 +245,13 @@ class CourseGradingModel(object): def parse_grader(json_grader): # manual to clear out kruft result = { - "type" : json_grader["type"], - "min_count" : int(json_grader.get('min_count', 0)), - "drop_count" : int(json_grader.get('drop_count', 0)), - "short_label" : json_grader.get('short_label', None), - "weight" : float(json_grader.get('weight', 0)) / 100.0 + "type": json_grader["type"], + "min_count": int(json_grader.get('min_count', 0)), + "drop_count": int(json_grader.get('drop_count', 0)), + "short_label": json_grader.get('short_label', None), + "weight": float(json_grader.get('weight', 0)) / 100.0 } - + return result @staticmethod @@ -260,6 +260,6 @@ class CourseGradingModel(object): if grader['weight']: grader['weight'] *= 100 if not 'short_label' in grader: - grader['short_label'] = "" - + grader['short_label'] = "" + return grader diff --git a/cms/envs/acceptance.py b/cms/envs/acceptance.py index 5bc9b53fc4..26a8adc92c 100644 --- a/cms/envs/acceptance.py +++ b/cms/envs/acceptance.py @@ -1,5 +1,5 @@ """ -This config file extends the test environment configuration +This config file extends the test environment configuration so that we can run the lettuce acceptance tests. """ from .test import * @@ -21,14 +21,14 @@ DATA_DIR = COURSES_ROOT # } # } -# Set this up so that rake lms[acceptance] and running the +# Set this up so that rake lms[acceptance] and running the # harvest command both use the same (test) database # which they can flush without messing up your dev db DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ENV_ROOT / "db" / "test_mitx.db", - 'TEST_NAME': ENV_ROOT / "db" / "test_mitx.db", + 'TEST_NAME': ENV_ROOT / "db" / "test_mitx.db", } } diff --git a/cms/envs/common.py b/cms/envs/common.py index 3ea532d70d..ef7a4f43fa 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -33,8 +33,8 @@ MITX_FEATURES = { 'USE_DJANGO_PIPELINE': True, 'GITHUB_PUSH': False, 'ENABLE_DISCUSSION_SERVICE': False, - 'AUTH_USE_MIT_CERTIFICATES' : False, - 'STUB_VIDEO_FOR_TESTING': False, # do not display video when running automated acceptance tests + 'AUTH_USE_MIT_CERTIFICATES': False, + 'STUB_VIDEO_FOR_TESTING': False, # do not display video when running automated acceptance tests } ENABLE_JASMINE = False @@ -229,7 +229,7 @@ PIPELINE_JS = { 'source_filenames': sorted( rooted_glob(COMMON_ROOT / 'static/', 'coffee/src/**/*.coffee') + rooted_glob(PROJECT_ROOT / 'static/', 'coffee/src/**/*.coffee') - ) + [ 'js/hesitate.js', 'js/base.js'], + ) + ['js/hesitate.js', 'js/base.js'], 'output_filename': 'js/cms-application.js', }, 'module-js': { diff --git a/cms/envs/dev.py b/cms/envs/dev.py index e29ee62e20..3dee93a398 100644 --- a/cms/envs/dev.py +++ b/cms/envs/dev.py @@ -12,7 +12,7 @@ TEMPLATE_DEBUG = DEBUG LOGGING = get_logger_config(ENV_ROOT / "log", logging_env="dev", tracking_filename="tracking.log", - dev_env = True, + dev_env=True, debug=True) modulestore_options = { @@ -41,7 +41,7 @@ CONTENTSTORE = { 'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore', 'OPTIONS': { 'host': 'localhost', - 'db' : 'xcontent', + 'db': 'xcontent', } } diff --git a/cms/envs/dev_ike.py b/cms/envs/dev_ike.py index 5fb120854b..1ebf219d44 100644 --- a/cms/envs/dev_ike.py +++ b/cms/envs/dev_ike.py @@ -9,8 +9,6 @@ import socket MITX_FEATURES['AUTH_USE_MIT_CERTIFICATES'] = True -MITX_FEATURES['USE_DJANGO_PIPELINE']=False # don't recompile scss - -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') # django 1.4 for nginx ssl proxy - +MITX_FEATURES['USE_DJANGO_PIPELINE'] = False # don't recompile scss +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') # django 1.4 for nginx ssl proxy diff --git a/cms/envs/test.py b/cms/envs/test.py index 74c3e349a4..7f39e6818b 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -19,7 +19,7 @@ TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' TEST_ROOT = path('test_root') # Makes the tests run much faster... -SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead +SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead # Want static files in the same dir for running on jenkins. STATIC_ROOT = TEST_ROOT / "staticfiles" @@ -62,7 +62,7 @@ CONTENTSTORE = { 'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore', 'OPTIONS': { 'host': 'localhost', - 'db' : 'xcontent', + 'db': 'xcontent', } } @@ -76,7 +76,7 @@ DATABASES = { LMS_BASE = "localhost:8000" CACHES = { - # This is the cache used for most things. Askbot will not work without a + # This is the cache used for most things. Askbot will not work without a # functioning cache -- it relies on caching to load its settings in places. # In staging/prod envs, the sessions also live here. 'default': { @@ -103,4 +103,4 @@ CACHES = { PASSWORD_HASHERS = ( 'django.contrib.auth.hashers.SHA1PasswordHasher', 'django.contrib.auth.hashers.MD5PasswordHasher', -) \ No newline at end of file +) diff --git a/cms/manage.py b/cms/manage.py index f8773c0641..723fa59da1 100644 --- a/cms/manage.py +++ b/cms/manage.py @@ -2,7 +2,7 @@ from django.core.management import execute_manager import imp try: - imp.find_module('settings') # Assumed to be in the same directory. + imp.find_module('settings') # Assumed to be in the same directory. except ImportError: import sys sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. " diff --git a/cms/urls.py b/cms/urls.py index c928e74d19..ad4dd87d74 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -48,7 +48,7 @@ urlpatterns = ('', url(r'^(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/gradeas.*$', 'contentstore.views.assignment_type_update', name='assignment_type_update'), - url(r'^pages/(?P[^/]+)/(?P[^/]+)/course/(?P[^/]+)$', 'contentstore.views.static_pages', + url(r'^pages/(?P[^/]+)/(?P[^/]+)/course/(?P[^/]+)$', 'contentstore.views.static_pages', name='static_pages'), url(r'^edit_static/(?P[^/]+)/(?P[^/]+)/course/(?P[^/]+)$', 'contentstore.views.edit_static', name='edit_static'), url(r'^edit_tabs/(?P[^/]+)/(?P[^/]+)/course/(?P[^/]+)$', 'contentstore.views.edit_tabs', name='edit_tabs'), @@ -56,7 +56,7 @@ urlpatterns = ('', # this is a generic method to return the data/metadata associated with a xmodule url(r'^module_info/(?P.*)$', 'contentstore.views.module_info', name='module_info'), - + # temporary landing page for a course url(r'^edge/(?P[^/]+)/(?P[^/]+)/course/(?P[^/]+)$', 'contentstore.views.landing', name='landing'), diff --git a/common/djangoapps/cache_toolbox/core.py b/common/djangoapps/cache_toolbox/core.py index 3bd184bc2c..a9c7002aa6 100644 --- a/common/djangoapps/cache_toolbox/core.py +++ b/common/djangoapps/cache_toolbox/core.py @@ -14,6 +14,7 @@ from django.db import DEFAULT_DB_ALIAS from . import app_settings from xmodule.contentstore.content import StaticContent + def get_instance(model, instance_or_pk, timeout=None, using=None): """ Returns the ``model`` instance with a primary key of ``instance_or_pk``. @@ -108,11 +109,14 @@ def instance_key(model, instance_or_pk): getattr(instance_or_pk, 'pk', instance_or_pk), ) + def set_cached_content(content): cache.set(str(content.location), content) + def get_cached_content(location): return cache.get(str(location)) + def del_cached_content(location): cache.delete(str(location)) diff --git a/common/djangoapps/contentserver/middleware.py b/common/djangoapps/contentserver/middleware.py index 1d139bcaa0..c5e887801e 100644 --- a/common/djangoapps/contentserver/middleware.py +++ b/common/djangoapps/contentserver/middleware.py @@ -12,7 +12,7 @@ from xmodule.exceptions import NotFoundError class StaticContentServer(object): def process_request(self, request): # look to see if the request is prefixed with 'c4x' tag - if request.path.startswith('/' + XASSET_LOCATION_TAG +'/'): + if request.path.startswith('/' + XASSET_LOCATION_TAG + '/'): loc = StaticContent.get_location_from_path(request.path) # first look in our cache so we don't have to round-trip to the DB content = get_cached_content(loc) diff --git a/common/djangoapps/course_groups/cohorts.py b/common/djangoapps/course_groups/cohorts.py index f84e18b214..155f82e0c7 100644 --- a/common/djangoapps/course_groups/cohorts.py +++ b/common/djangoapps/course_groups/cohorts.py @@ -13,6 +13,7 @@ from .models import CourseUserGroup log = logging.getLogger(__name__) + def is_course_cohorted(course_id): """ Given a course id, return a boolean for whether or not the course is @@ -115,6 +116,7 @@ def get_course_cohorts(course_id): ### Helpers for cohort management views + def get_cohort_by_name(course_id, name): """ Return the CourseUserGroup object for the given cohort. Raises DoesNotExist @@ -124,6 +126,7 @@ def get_cohort_by_name(course_id, name): group_type=CourseUserGroup.COHORT, name=name) + def get_cohort_by_id(course_id, cohort_id): """ Return the CourseUserGroup object for the given cohort. Raises DoesNotExist @@ -133,6 +136,7 @@ def get_cohort_by_id(course_id, cohort_id): group_type=CourseUserGroup.COHORT, id=cohort_id) + def add_cohort(course_id, name): """ Add a cohort to a course. Raises ValueError if a cohort of the same name already @@ -148,12 +152,14 @@ def add_cohort(course_id, name): group_type=CourseUserGroup.COHORT, name=name) + class CohortConflict(Exception): """ Raised when user to be added is already in another cohort in same course. """ pass + def add_user_to_cohort(cohort, username_or_email): """ Look up the given user, and if successful, add them to the specified cohort. @@ -211,4 +217,3 @@ def delete_empty_cohort(course_id, name): name, course_id)) cohort.delete() - diff --git a/common/djangoapps/course_groups/models.py b/common/djangoapps/course_groups/models.py index 957d230d92..8bab17493b 100644 --- a/common/djangoapps/course_groups/models.py +++ b/common/djangoapps/course_groups/models.py @@ -5,6 +5,7 @@ from django.db import models log = logging.getLogger(__name__) + class CourseUserGroup(models.Model): """ This model represents groups of users in a course. Groups may have different types, @@ -30,5 +31,3 @@ class CourseUserGroup(models.Model): COHORT = 'cohort' GROUP_TYPE_CHOICES = ((COHORT, 'Cohort'),) group_type = models.CharField(max_length=20, choices=GROUP_TYPE_CHOICES) - - diff --git a/common/djangoapps/course_groups/tests/tests.py b/common/djangoapps/course_groups/tests/tests.py index 86f0be0791..0fbf863fee 100644 --- a/common/djangoapps/course_groups/tests/tests.py +++ b/common/djangoapps/course_groups/tests/tests.py @@ -12,7 +12,8 @@ from xmodule.modulestore.django import modulestore, _MODULESTORES # NOTE: running this with the lms.envs.test config works without # manually overriding the modulestore. However, running with -# cms.envs.test doesn't. +# cms.envs.test doesn't. + def xml_store_config(data_dir): return { @@ -28,6 +29,7 @@ def xml_store_config(data_dir): TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestCohorts(django.test.TestCase): @@ -184,6 +186,3 @@ class TestCohorts(django.test.TestCase): self.assertTrue( is_commentable_cohorted(course.id, to_id("Feedback")), "Feedback was listed as cohorted. Should be.") - - - diff --git a/common/djangoapps/course_groups/views.py b/common/djangoapps/course_groups/views.py index d591c44356..6d5ac43fb0 100644 --- a/common/djangoapps/course_groups/views.py +++ b/common/djangoapps/course_groups/views.py @@ -22,6 +22,7 @@ import track.views log = logging.getLogger(__name__) + def json_http_response(data): """ Return an HttpResponse with the data json-serialized and the right content @@ -29,6 +30,7 @@ def json_http_response(data): """ return HttpResponse(json.dumps(data), content_type="application/json") + def split_by_comma_and_whitespace(s): """ Split a string both by commas and whitespice. Returns a list. @@ -177,6 +179,7 @@ def add_users_to_cohort(request, course_id, cohort_id): 'conflict': conflict, 'unknown': unknown}) + @ensure_csrf_cookie @require_POST def remove_user_from_cohort(request, course_id, cohort_id): diff --git a/common/djangoapps/external_auth/admin.py b/common/djangoapps/external_auth/admin.py index e93325bcb2..1ee18dadc1 100644 --- a/common/djangoapps/external_auth/admin.py +++ b/common/djangoapps/external_auth/admin.py @@ -5,8 +5,9 @@ django admin pages for courseware model from external_auth.models import * from django.contrib import admin + class ExternalAuthMapAdmin(admin.ModelAdmin): - search_fields = ['external_id','user__username'] + search_fields = ['external_id', 'user__username'] date_hierarchy = 'dtcreated' admin.site.register(ExternalAuthMap, ExternalAuthMapAdmin) diff --git a/common/djangoapps/external_auth/models.py b/common/djangoapps/external_auth/models.py index e43b306bbb..6c2f38d8b3 100644 --- a/common/djangoapps/external_auth/models.py +++ b/common/djangoapps/external_auth/models.py @@ -12,20 +12,20 @@ file and check it in at the same time as your model changes. To do that, from django.db import models from django.contrib.auth.models import User + class ExternalAuthMap(models.Model): class Meta: unique_together = (('external_id', 'external_domain'), ) external_id = models.CharField(max_length=255, db_index=True) external_domain = models.CharField(max_length=255, db_index=True) - external_credentials = models.TextField(blank=True) # JSON dictionary + external_credentials = models.TextField(blank=True) # JSON dictionary external_email = models.CharField(max_length=255, db_index=True) - external_name = models.CharField(blank=True,max_length=255, db_index=True) + external_name = models.CharField(blank=True, max_length=255, db_index=True) user = models.OneToOneField(User, unique=True, db_index=True, null=True) - internal_password = models.CharField(blank=True, max_length=31) # randomly generated - dtcreated = models.DateTimeField('creation date',auto_now_add=True) - dtsignup = models.DateTimeField('signup date',null=True) # set after signup - + internal_password = models.CharField(blank=True, max_length=31) # randomly generated + dtcreated = models.DateTimeField('creation date', auto_now_add=True) + dtsignup = models.DateTimeField('signup date', null=True) # set after signup + def __unicode__(self): s = "[%s] = (%s / %s)" % (self.external_id, self.external_name, self.external_email) return s - diff --git a/common/djangoapps/external_auth/tests/test_openid_provider.py b/common/djangoapps/external_auth/tests/test_openid_provider.py index 9c522f88b4..570dfbf9ee 100644 --- a/common/djangoapps/external_auth/tests/test_openid_provider.py +++ b/common/djangoapps/external_auth/tests/test_openid_provider.py @@ -13,9 +13,10 @@ from django.test import TestCase, LiveServerTestCase from django.core.urlresolvers import reverse from django.test.client import RequestFactory + class MyFetcher(HTTPFetcher): """A fetcher that uses server-internal calls for performing HTTP - requests. + requests. """ def __init__(self, client): @@ -42,7 +43,7 @@ class MyFetcher(HTTPFetcher): if headers and 'Accept' in headers: data['CONTENT_TYPE'] = headers['Accept'] response = self.client.get(url, data) - + # Translate the test client response to the fetcher's HTTP response abstraction content = response.content final_url = url @@ -60,6 +61,7 @@ class MyFetcher(HTTPFetcher): status=status, ) + class OpenIdProviderTest(TestCase): # def setUp(self): @@ -78,7 +80,7 @@ class OpenIdProviderTest(TestCase): provider_url = reverse('openid-provider-xrds') factory = RequestFactory() request = factory.request() - abs_provider_url = request.build_absolute_uri(location = provider_url) + abs_provider_url = request.build_absolute_uri(location=provider_url) # In order for this absolute URL to work (i.e. to get xrds, then authentication) # in the test environment, we either need a live server that works with the default @@ -86,10 +88,10 @@ class OpenIdProviderTest(TestCase): # Here we do the latter: fetcher = MyFetcher(self.client) openid.fetchers.setDefaultFetcher(fetcher, wrap_exceptions=False) - + # now we can begin the login process by invoking a local openid client, # with a pointer to the (also-local) openid provider: - with self.settings(OPENID_SSO_SERVER_URL = abs_provider_url): + with self.settings(OPENID_SSO_SERVER_URL=abs_provider_url): url = reverse('openid-login') resp = self.client.post(url) code = 200 @@ -107,7 +109,7 @@ class OpenIdProviderTest(TestCase): provider_url = reverse('openid-provider-login') factory = RequestFactory() request = factory.request() - abs_provider_url = request.build_absolute_uri(location = provider_url) + abs_provider_url = request.build_absolute_uri(location=provider_url) # In order for this absolute URL to work (i.e. to get xrds, then authentication) # in the test environment, we either need a live server that works with the default @@ -115,10 +117,10 @@ class OpenIdProviderTest(TestCase): # Here we do the latter: fetcher = MyFetcher(self.client) openid.fetchers.setDefaultFetcher(fetcher, wrap_exceptions=False) - + # now we can begin the login process by invoking a local openid client, # with a pointer to the (also-local) openid provider: - with self.settings(OPENID_SSO_SERVER_URL = abs_provider_url): + with self.settings(OPENID_SSO_SERVER_URL=abs_provider_url): url = reverse('openid-login') resp = self.client.post(url) code = 200 @@ -143,43 +145,43 @@ class OpenIdProviderTest(TestCase): self.assertContains(resp, '', html=True) # this should work on the server: self.assertContains(resp, '', html=True) - + # not included here are elements that will vary from run to run: # # - - + + def testOpenIdSetup(self): if not settings.MITX_FEATURES.get('AUTH_USE_OPENID_PROVIDER'): return url = reverse('openid-provider-login') post_args = { - "openid.mode" : "checkid_setup", - "openid.return_to" : "http://testserver/openid/complete/?janrain_nonce=2013-01-23T06%3A20%3A17ZaN7j6H", - "openid.assoc_handle" : "{HMAC-SHA1}{50ff8120}{rh87+Q==}", - "openid.claimed_id" : "http://specs.openid.net/auth/2.0/identifier_select", - "openid.ns" : "http://specs.openid.net/auth/2.0", - "openid.realm" : "http://testserver/", - "openid.identity" : "http://specs.openid.net/auth/2.0/identifier_select", - "openid.ns.ax" : "http://openid.net/srv/ax/1.0", - "openid.ax.mode" : "fetch_request", - "openid.ax.required" : "email,fullname,old_email,firstname,old_nickname,lastname,old_fullname,nickname", - "openid.ax.type.fullname" : "http://axschema.org/namePerson", - "openid.ax.type.lastname" : "http://axschema.org/namePerson/last", - "openid.ax.type.firstname" : "http://axschema.org/namePerson/first", - "openid.ax.type.nickname" : "http://axschema.org/namePerson/friendly", - "openid.ax.type.email" : "http://axschema.org/contact/email", - "openid.ax.type.old_email" : "http://schema.openid.net/contact/email", - "openid.ax.type.old_nickname" : "http://schema.openid.net/namePerson/friendly", - "openid.ax.type.old_fullname" : "http://schema.openid.net/namePerson", + "openid.mode": "checkid_setup", + "openid.return_to": "http://testserver/openid/complete/?janrain_nonce=2013-01-23T06%3A20%3A17ZaN7j6H", + "openid.assoc_handle": "{HMAC-SHA1}{50ff8120}{rh87+Q==}", + "openid.claimed_id": "http://specs.openid.net/auth/2.0/identifier_select", + "openid.ns": "http://specs.openid.net/auth/2.0", + "openid.realm": "http://testserver/", + "openid.identity": "http://specs.openid.net/auth/2.0/identifier_select", + "openid.ns.ax": "http://openid.net/srv/ax/1.0", + "openid.ax.mode": "fetch_request", + "openid.ax.required": "email,fullname,old_email,firstname,old_nickname,lastname,old_fullname,nickname", + "openid.ax.type.fullname": "http://axschema.org/namePerson", + "openid.ax.type.lastname": "http://axschema.org/namePerson/last", + "openid.ax.type.firstname": "http://axschema.org/namePerson/first", + "openid.ax.type.nickname": "http://axschema.org/namePerson/friendly", + "openid.ax.type.email": "http://axschema.org/contact/email", + "openid.ax.type.old_email": "http://schema.openid.net/contact/email", + "openid.ax.type.old_nickname": "http://schema.openid.net/namePerson/friendly", + "openid.ax.type.old_fullname": "http://schema.openid.net/namePerson", } resp = self.client.post(url, post_args) code = 200 self.assertEqual(resp.status_code, code, "got code {0} for url '{1}'. Expected code {2}" .format(resp.status_code, url, code)) - - + + # In order for this absolute URL to work (i.e. to get xrds, then authentication) # in the test environment, we either need a live server that works with the default # fetcher (i.e. urlopen2), or a test server that is reached through a custom fetcher. @@ -196,11 +198,11 @@ class OpenIdProviderLiveServerTest(LiveServerTestCase): provider_url = reverse('openid-provider-xrds') factory = RequestFactory() request = factory.request() - abs_provider_url = request.build_absolute_uri(location = provider_url) + abs_provider_url = request.build_absolute_uri(location=provider_url) # now we can begin the login process by invoking a local openid client, # with a pointer to the (also-local) openid provider: - with self.settings(OPENID_SSO_SERVER_URL = abs_provider_url): + with self.settings(OPENID_SSO_SERVER_URL=abs_provider_url): url = reverse('openid-login') resp = self.client.post(url) code = 200 diff --git a/common/djangoapps/external_auth/views.py b/common/djangoapps/external_auth/views.py index d557b33e9c..effae923b3 100644 --- a/common/djangoapps/external_auth/views.py +++ b/common/djangoapps/external_auth/views.py @@ -215,7 +215,7 @@ def ssl_dn_extract_info(dn): else: return None return (user, email, fullname) - + def ssl_get_cert_from_request(request): """ @@ -460,7 +460,7 @@ def provider_login(request): openid_request.answer(False), {}) # checkid_setup, so display login page - # (by falling through to the provider_login at the + # (by falling through to the provider_login at the # bottom of this method). elif openid_request.mode == 'checkid_setup': if openid_request.idSelect(): @@ -482,7 +482,7 @@ def provider_login(request): # handle login redirection: these are also sent to this view function, # but are distinguished by lacking the openid mode. We also know that - # they are posts, because they come from the popup + # they are posts, because they come from the popup elif request.method == 'POST' and 'openid_setup' in request.session: # get OpenID request from session openid_setup = request.session['openid_setup'] @@ -495,7 +495,7 @@ def provider_login(request): return default_render_failure(request, "Invalid OpenID trust root") # check if user with given email exists - # Failure is redirected to this method (by using the original URL), + # Failure is redirected to this method (by using the original URL), # which will bring up the login dialog. email = request.POST.get('email', None) try: @@ -542,17 +542,17 @@ def provider_login(request): # missing fields is up to the Consumer. The proper change # should only return the username, however this will likely # break the CS50 client. Temporarily we will be returning - # username filling in for fullname in addition to username + # username filling in for fullname in addition to username # as sreg nickname. - - # Note too that this is hardcoded, and not really responding to + + # Note too that this is hardcoded, and not really responding to # the extensions that were registered in the first place. results = { 'nickname': user.username, 'email': user.email, 'fullname': user.username } - + # the request succeeded: return provider_respond(server, openid_request, response, results) diff --git a/common/djangoapps/mitxmako/makoloader.py b/common/djangoapps/mitxmako/makoloader.py index 1379027e07..29184299b6 100644 --- a/common/djangoapps/mitxmako/makoloader.py +++ b/common/djangoapps/mitxmako/makoloader.py @@ -12,34 +12,35 @@ import mitxmako.middleware log = logging.getLogger(__name__) + class MakoLoader(object): """ This is a Django loader object which will load the template as a Mako template if the first line is "## mako". It is based off BaseLoader in django.template.loader. """ - + is_usable = False def __init__(self, base_loader): # base_loader is an instance of a BaseLoader subclass self.base_loader = base_loader - + module_directory = getattr(settings, 'MAKO_MODULE_DIR', None) - + if module_directory is None: log.warning("For more caching of mako templates, set the MAKO_MODULE_DIR in settings!") module_directory = tempfile.mkdtemp() - + self.module_directory = module_directory - - + + def __call__(self, template_name, template_dirs=None): return self.load_template(template_name, template_dirs) def load_template(self, template_name, template_dirs=None): source, file_path = self.load_template_source(template_name, template_dirs) - + if source.startswith("## mako\n"): # This is a mako template template = Template(filename=file_path, module_directory=self.module_directory, uri=template_name) @@ -56,23 +57,24 @@ class MakoLoader(object): # This allows for correct identification (later) of the actual template that does # not exist. return source, file_path - + def load_template_source(self, template_name, template_dirs=None): # Just having this makes the template load as an instance, instead of a class. return self.base_loader.load_template_source(template_name, template_dirs) def reset(self): self.base_loader.reset() - + class MakoFilesystemLoader(MakoLoader): is_usable = True - + def __init__(self): MakoLoader.__init__(self, FilesystemLoader()) - + + class MakoAppDirectoriesLoader(MakoLoader): is_usable = True - + def __init__(self): MakoLoader.__init__(self, AppDirectoriesLoader()) diff --git a/common/djangoapps/mitxmako/template.py b/common/djangoapps/mitxmako/template.py index 947dc8c1a4..6ef8058c7c 100644 --- a/common/djangoapps/mitxmako/template.py +++ b/common/djangoapps/mitxmako/template.py @@ -20,13 +20,15 @@ from mitxmako import middleware django_variables = ['lookup', 'output_encoding', 'encoding_errors'] # TODO: We should make this a Django Template subclass that simply has the MakoTemplate inside of it? (Intead of inheriting from MakoTemplate) + + class Template(MakoTemplate): """ This bridges the gap between a Mako template and a djano template. It can be rendered like it is a django template because the arguments are transformed in a way that MakoTemplate can understand. """ - + def __init__(self, *args, **kwargs): """Overrides base __init__ to provide django variable overrides""" if not kwargs.get('no_django', False): @@ -34,8 +36,8 @@ class Template(MakoTemplate): overrides['lookup'] = overrides['lookup']['main'] kwargs.update(overrides) super(Template, self).__init__(*args, **kwargs) - - + + def render(self, context_instance): """ This takes a render call with a context (from Django) and translates @@ -43,7 +45,7 @@ class Template(MakoTemplate): """ # collapse context_instance to a single dictionary for mako context_dictionary = {} - + # In various testing contexts, there might not be a current request context. if middleware.requestcontext is not None: for d in middleware.requestcontext: @@ -53,5 +55,5 @@ class Template(MakoTemplate): context_dictionary['settings'] = settings context_dictionary['MITX_ROOT_URL'] = settings.MITX_ROOT_URL context_dictionary['django_context'] = context_instance - + return super(Template, self).render_unicode(**context_dictionary) diff --git a/common/djangoapps/mitxmako/templatetag_helpers.py b/common/djangoapps/mitxmako/templatetag_helpers.py index e254625d3d..cd871a0fc5 100644 --- a/common/djangoapps/mitxmako/templatetag_helpers.py +++ b/common/djangoapps/mitxmako/templatetag_helpers.py @@ -2,14 +2,15 @@ from django.template import loader from django.template.base import Template, Context from django.template.loader import get_template, select_template + def django_template_include(file_name, mako_context): """ This can be used within a mako template to include a django template in the way that a django-style {% include %} does. Pass it context which can be the mako context ('context') or a dictionary. """ - - dictionary = dict( mako_context ) + + dictionary = dict(mako_context) return loader.render_to_string(file_name, dictionary=dictionary) @@ -18,7 +19,7 @@ def render_inclusion(func, file_name, takes_context, django_context, *args, **kw This allows a mako template to call a template tag function (written for django templates) that is an "inclusion tag". These functions are decorated with @register.inclusion_tag. - + -func: This is the function that is registered as an inclusion tag. You must import it directly using a python import statement. -file_name: This is the filename of the template, passed into the @@ -29,10 +30,10 @@ def render_inclusion(func, file_name, takes_context, django_context, *args, **kw a copy of the django context is available as 'django_context'. -*args and **kwargs are the arguments to func. """ - + if takes_context: args = [django_context] + list(args) - + _dict = func(*args, **kwargs) if isinstance(file_name, Template): t = file_name @@ -40,14 +41,12 @@ def render_inclusion(func, file_name, takes_context, django_context, *args, **kw t = select_template(file_name) else: t = get_template(file_name) - + nodelist = t.nodelist - + new_context = Context(_dict) csrf_token = django_context.get('csrf_token', None) if csrf_token is not None: new_context['csrf_token'] = csrf_token - - return nodelist.render(new_context) - + return nodelist.render(new_context) diff --git a/common/djangoapps/static_replace/__init__.py b/common/djangoapps/static_replace/__init__.py index cfef798bdf..6bd8125580 100644 --- a/common/djangoapps/static_replace/__init__.py +++ b/common/djangoapps/static_replace/__init__.py @@ -21,6 +21,7 @@ def _url_replace_regex(prefix): (?P=quote) # the first matching closing quote """.format(prefix=prefix) + def try_staticfiles_lookup(path): """ Try to lookup a path in staticfiles_storage. If it fails, return diff --git a/common/djangoapps/static_replace/test/test_static_replace.py b/common/djangoapps/static_replace/test/test_static_replace.py index e08c66c59f..50c0fbd246 100644 --- a/common/djangoapps/static_replace/test/test_static_replace.py +++ b/common/djangoapps/static_replace/test/test_static_replace.py @@ -53,6 +53,7 @@ def test_mongo_filestore(mock_modulestore, mock_static_content): mock_static_content.convert_legacy_static_url.assert_called_once_with('file.png', NAMESPACE) + @patch('static_replace.settings') @patch('static_replace.modulestore') @patch('static_replace.staticfiles_storage') diff --git a/common/djangoapps/status/__init__.py b/common/djangoapps/status/__init__.py index 8b13789179..e69de29bb2 100644 --- a/common/djangoapps/status/__init__.py +++ b/common/djangoapps/status/__init__.py @@ -1 +0,0 @@ - diff --git a/common/djangoapps/status/status.py b/common/djangoapps/status/status.py index c06a70f5a1..deacd9c631 100644 --- a/common/djangoapps/status/status.py +++ b/common/djangoapps/status/status.py @@ -10,6 +10,7 @@ import sys log = logging.getLogger(__name__) + def get_site_status_msg(course_id): """ Look for a file settings.STATUS_MESSAGE_PATH. If found, read it, diff --git a/common/djangoapps/student/management/commands/6002exportusers.py b/common/djangoapps/student/management/commands/6002exportusers.py index fcf565fb83..31d8092d3f 100644 --- a/common/djangoapps/student/management/commands/6002exportusers.py +++ b/common/djangoapps/student/management/commands/6002exportusers.py @@ -57,7 +57,7 @@ from student.userprofile. ''' d[key] = item return d - extracted = [{'up':extract_dict(up_keys, t[0]), 'u':extract_dict(user_keys, t[1])} for t in user_tuples] + extracted = [{'up': extract_dict(up_keys, t[0]), 'u':extract_dict(user_keys, t[1])} for t in user_tuples] fp = open('transfer_users.txt', 'w') json.dump(extracted, fp) fp.close() diff --git a/common/djangoapps/student/management/commands/add_to_group.py b/common/djangoapps/student/management/commands/add_to_group.py index 209d25da85..bdbb4027f7 100644 --- a/common/djangoapps/student/management/commands/add_to_group.py +++ b/common/djangoapps/student/management/commands/add_to_group.py @@ -3,6 +3,7 @@ from optparse import make_option from django.core.management.base import BaseCommand, CommandError from django.contrib.auth.models import User, Group + class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--list', diff --git a/common/djangoapps/student/management/commands/create_random_users.py b/common/djangoapps/student/management/commands/create_random_users.py index c6cf452a43..70374d02f2 100644 --- a/common/djangoapps/student/management/commands/create_random_users.py +++ b/common/djangoapps/student/management/commands/create_random_users.py @@ -8,6 +8,7 @@ from student.models import UserProfile, CourseEnrollment from student.views import _do_create_account, get_random_post_override + def create(n, course_id): """Create n users, enrolling them in course_id if it's not None""" for i in range(n): @@ -15,6 +16,7 @@ def create(n, course_id): if course_id is not None: CourseEnrollment.objects.create(user=user, course_id=course_id) + class Command(BaseCommand): help = """Create N new users, with random parameters. diff --git a/common/djangoapps/student/management/commands/pearson_dump.py b/common/djangoapps/student/management/commands/pearson_dump.py index 228508efb1..2aade8cf5f 100644 --- a/common/djangoapps/student/management/commands/pearson_dump.py +++ b/common/djangoapps/student/management/commands/pearson_dump.py @@ -36,7 +36,7 @@ class Command(BaseCommand): outputfile = datetime.utcnow().strftime("pearson-dump-%Y%m%d-%H%M%S.json") else: outputfile = args[0] - + # construct the query object to dump: registrations = TestCenterRegistration.objects.all() if 'course_id' in options and options['course_id']: @@ -44,24 +44,24 @@ class Command(BaseCommand): if 'exam_series_code' in options and options['exam_series_code']: registrations = registrations.filter(exam_series_code=options['exam_series_code']) - # collect output: + # collect output: output = [] for registration in registrations: if 'accommodation_pending' in options and options['accommodation_pending'] and not registration.accommodation_is_pending: continue - record = {'username' : registration.testcenter_user.user.username, - 'email' : registration.testcenter_user.email, - 'first_name' : registration.testcenter_user.first_name, - 'last_name' : registration.testcenter_user.last_name, - 'client_candidate_id' : registration.client_candidate_id, - 'client_authorization_id' : registration.client_authorization_id, - 'course_id' : registration.course_id, - 'exam_series_code' : registration.exam_series_code, - 'accommodation_request' : registration.accommodation_request, - 'accommodation_code' : registration.accommodation_code, - 'registration_status' : registration.registration_status(), - 'demographics_status' : registration.demographics_status(), - 'accommodation_status' : registration.accommodation_status(), + record = {'username': registration.testcenter_user.user.username, + 'email': registration.testcenter_user.email, + 'first_name': registration.testcenter_user.first_name, + 'last_name': registration.testcenter_user.last_name, + 'client_candidate_id': registration.client_candidate_id, + 'client_authorization_id': registration.client_authorization_id, + 'course_id': registration.course_id, + 'exam_series_code': registration.exam_series_code, + 'accommodation_request': registration.accommodation_request, + 'accommodation_code': registration.accommodation_code, + 'registration_status': registration.registration_status(), + 'demographics_status': registration.demographics_status(), + 'accommodation_status': registration.accommodation_status(), } if len(registration.upload_error_message) > 0: record['registration_error'] = registration.upload_error_message @@ -71,8 +71,7 @@ class Command(BaseCommand): record['needs_uploading'] = True output.append(record) - + # dump output: with open(outputfile, 'w') as outfile: dump(output, outfile, indent=2) - diff --git a/common/djangoapps/student/management/commands/pearson_export_cdd.py b/common/djangoapps/student/management/commands/pearson_export_cdd.py index 463eec6b70..bad98b9d25 100644 --- a/common/djangoapps/student/management/commands/pearson_export_cdd.py +++ b/common/djangoapps/student/management/commands/pearson_export_cdd.py @@ -39,7 +39,7 @@ class Command(BaseCommand): ("LastUpdate", "user_updated_at"), # in UTC, so same as what we store ]) - # define defaults, even thought 'store_true' shouldn't need them. + # define defaults, even thought 'store_true' shouldn't need them. # (call_command will set None as default value for all options that don't have one, # so one cannot rely on presence/absence of flags in that world.) option_list = BaseCommand.option_list + ( @@ -56,7 +56,7 @@ class Command(BaseCommand): ) def handle(self, **options): - # update time should use UTC in order to be comparable to the user_updated_at + # update time should use UTC in order to be comparable to the user_updated_at # field uploaded_at = datetime.utcnow() @@ -100,7 +100,7 @@ class Command(BaseCommand): extrasaction='ignore') writer.writeheader() for tcu in TestCenterUser.objects.order_by('id'): - if tcu.needs_uploading: # or dump_all + if tcu.needs_uploading: # or dump_all record = dict((csv_field, ensure_encoding(getattr(tcu, model_field))) for csv_field, model_field in Command.CSV_TO_MODEL_FIELDS.items()) diff --git a/common/djangoapps/student/management/commands/pearson_import_conf_zip.py b/common/djangoapps/student/management/commands/pearson_import_conf_zip.py index d94c3ba863..d0b2938df0 100644 --- a/common/djangoapps/student/management/commands/pearson_import_conf_zip.py +++ b/common/djangoapps/student/management/commands/pearson_import_conf_zip.py @@ -116,4 +116,3 @@ class Command(BaseCommand): tcuser.save() except TestCenterUser.DoesNotExist: Command.datadog_error(" Failed to find record for client_candidate_id {}".format(client_candidate_id), vcdcfile.name) - diff --git a/common/djangoapps/student/management/commands/pearson_make_tc_registration.py b/common/djangoapps/student/management/commands/pearson_make_tc_registration.py index b59241240d..b10cf143a0 100644 --- a/common/djangoapps/student/management/commands/pearson_make_tc_registration.py +++ b/common/djangoapps/student/management/commands/pearson_make_tc_registration.py @@ -9,6 +9,7 @@ from student.views import course_from_id from xmodule.course_module import CourseDescriptor from xmodule.modulestore.exceptions import ItemNotFoundError + class Command(BaseCommand): option_list = BaseCommand.option_list + ( # registration info: @@ -16,23 +17,23 @@ class Command(BaseCommand): '--accommodation_request', action='store', dest='accommodation_request', - ), + ), make_option( '--accommodation_code', action='store', dest='accommodation_code', - ), + ), make_option( '--client_authorization_id', action='store', dest='client_authorization_id', - ), - # exam info: + ), + # exam info: make_option( '--exam_series_code', action='store', dest='exam_series_code', - ), + ), make_option( '--eligibility_appointment_date_first', action='store', @@ -51,32 +52,32 @@ class Command(BaseCommand): action='store', dest='authorization_id', help='ID we receive from Pearson for a particular authorization' - ), + ), make_option( '--upload_status', action='store', dest='upload_status', help='status value assigned by Pearson' - ), + ), make_option( '--upload_error_message', action='store', dest='upload_error_message', help='error message provided by Pearson on a failure.' - ), + ), # control values: make_option( '--ignore_registration_dates', action='store_true', dest='ignore_registration_dates', help='find exam info for course based on exam_series_code, even if the exam is not active.' - ), + ), make_option( '--create_dummy_exam', action='store_true', dest='create_dummy_exam', help='create dummy exam info for course, even if course exists' - ), + ), ) args = "" help = "Create or modify a TestCenterRegistration entry for a given Student" @@ -103,7 +104,7 @@ class Command(BaseCommand): testcenter_user = TestCenterUser.objects.get(user=student) except TestCenterUser.DoesNotExist: raise CommandError("User \"{}\" does not have an existing demographics record".format(username)) - + # get an "exam" object. Check to see if a course_id was specified, and use information from that: exam = None create_dummy_exam = 'create_dummy_exam' in our_options and our_options['create_dummy_exam'] @@ -115,14 +116,14 @@ class Command(BaseCommand): exam = examlist[0] if len(examlist) > 0 else None else: exam = course.current_test_center_exam - except ItemNotFoundError: + except ItemNotFoundError: pass else: - # otherwise use explicit values (so we don't have to define a course): + # otherwise use explicit values (so we don't have to define a course): exam_name = "Dummy Placeholder Name" - exam_info = { 'Exam_Series_Code': our_options['exam_series_code'], - 'First_Eligible_Appointment_Date' : our_options['eligibility_appointment_date_first'], - 'Last_Eligible_Appointment_Date' : our_options['eligibility_appointment_date_last'], + exam_info = {'Exam_Series_Code': our_options['exam_series_code'], + 'First_Eligible_Appointment_Date': our_options['eligibility_appointment_date_first'], + 'Last_Eligible_Appointment_Date': our_options['eligibility_appointment_date_last'], } exam = CourseDescriptor.TestCenterExam(course_id, exam_name, exam_info) # update option values for date_first and date_last to use YYYY-MM-DD format @@ -134,15 +135,15 @@ class Command(BaseCommand): raise CommandError("Exam for course_id {} does not exist".format(course_id)) exam_code = exam.exam_series_code - - UPDATE_FIELDS = ( 'accommodation_request', + + UPDATE_FIELDS = ('accommodation_request', 'accommodation_code', 'client_authorization_id', 'exam_series_code', 'eligibility_appointment_date_first', 'eligibility_appointment_date_last', ) - + # create and save the registration: needs_updating = False registrations = get_testcenter_registration(student, course_id, exam_code) @@ -152,29 +153,29 @@ class Command(BaseCommand): if fieldname in our_options and registration.__getattribute__(fieldname) != our_options[fieldname]: needs_updating = True; else: - accommodation_request = our_options.get('accommodation_request','') + accommodation_request = our_options.get('accommodation_request', '') registration = TestCenterRegistration.create(testcenter_user, exam, accommodation_request) needs_updating = True - + if needs_updating: # first update the record with the new values, if any: for fieldname in UPDATE_FIELDS: - if fieldname in our_options and fieldname not in TestCenterRegistrationForm.Meta.fields: + if fieldname in our_options and fieldname not in TestCenterRegistrationForm.Meta.fields: registration.__setattr__(fieldname, our_options[fieldname]) - - # the registration form normally populates the data dict with + + # the registration form normally populates the data dict with # the accommodation request (if any). But here we want to # specify only those values that might change, so update the dict with existing # values. form_options = dict(our_options) for propname in TestCenterRegistrationForm.Meta.fields: - if propname not in form_options: + if propname not in form_options: form_options[propname] = registration.__getattribute__(propname) form = TestCenterRegistrationForm(instance=registration, data=form_options) if form.is_valid(): form.update_and_save() - print "Updated registration information for user's registration: username \"{}\" course \"{}\", examcode \"{}\"".format(student.username, course_id, exam_code) + print "Updated registration information for user's registration: username \"{}\" course \"{}\", examcode \"{}\"".format(student.username, course_id, exam_code) else: if (len(form.errors) > 0): print "Field Form errors encountered:" @@ -185,24 +186,22 @@ class Command(BaseCommand): print "Non-field Form errors encountered:" for nonfielderror in form.non_field_errors: print "Non-field Form Error: %s" % nonfielderror - + else: print "No changes necessary to make to existing user's registration." - + # override internal values: change_internal = False if 'exam_series_code' in our_options: exam_code = our_options['exam_series_code'] registration = get_testcenter_registration(student, course_id, exam_code)[0] - for internal_field in [ 'upload_error_message', 'upload_status', 'authorization_id']: + for internal_field in ['upload_error_message', 'upload_status', 'authorization_id']: if internal_field in our_options: registration.__setattr__(internal_field, our_options[internal_field]) change_internal = True - + if change_internal: print "Updated confirmation information in existing user's registration." registration.save() else: print "No changes necessary to make to confirmation information in existing user's registration." - - diff --git a/common/djangoapps/student/management/commands/pearson_make_tc_user.py b/common/djangoapps/student/management/commands/pearson_make_tc_user.py index 87e0b4dadd..10ef0bd067 100644 --- a/common/djangoapps/student/management/commands/pearson_make_tc_user.py +++ b/common/djangoapps/student/management/commands/pearson_make_tc_user.py @@ -5,60 +5,61 @@ from django.core.management.base import BaseCommand, CommandError from student.models import TestCenterUser, TestCenterUserForm + class Command(BaseCommand): option_list = BaseCommand.option_list + ( - # demographics: + # demographics: make_option( '--first_name', action='store', dest='first_name', - ), + ), make_option( '--middle_name', action='store', dest='middle_name', - ), + ), make_option( '--last_name', action='store', dest='last_name', - ), + ), make_option( '--suffix', action='store', dest='suffix', - ), + ), make_option( '--salutation', action='store', dest='salutation', - ), + ), make_option( '--address_1', action='store', dest='address_1', - ), + ), make_option( '--address_2', action='store', dest='address_2', - ), + ), make_option( '--address_3', action='store', dest='address_3', - ), + ), make_option( '--city', action='store', dest='city', - ), + ), make_option( '--state', action='store', dest='state', help='Two letter code (e.g. MA)' - ), + ), make_option( '--postal_code', action='store', @@ -75,12 +76,12 @@ class Command(BaseCommand): action='store', dest='phone', help='Pretty free-form (parens, spaces, dashes), but no country code' - ), + ), make_option( '--extension', action='store', dest='extension', - ), + ), make_option( '--phone_country_code', action='store', @@ -92,7 +93,7 @@ class Command(BaseCommand): action='store', dest='fax', help='Pretty free-form (parens, spaces, dashes), but no country code' - ), + ), make_option( '--fax_country_code', action='store', @@ -103,26 +104,26 @@ class Command(BaseCommand): '--company_name', action='store', dest='company_name', - ), + ), # internal values: make_option( '--client_candidate_id', action='store', dest='client_candidate_id', help='ID we assign a user to identify them to Pearson' - ), + ), make_option( '--upload_status', action='store', dest='upload_status', help='status value assigned by Pearson' - ), + ), make_option( '--upload_error_message', action='store', dest='upload_error_message', help='error message provided by Pearson on a failure.' - ), + ), ) args = "" help = "Create or modify a TestCenterUser entry for a given Student" @@ -142,20 +143,20 @@ class Command(BaseCommand): student = User.objects.get(username=username) try: testcenter_user = TestCenterUser.objects.get(user=student) - needs_updating = testcenter_user.needs_update(our_options) + needs_updating = testcenter_user.needs_update(our_options) except TestCenterUser.DoesNotExist: # do additional initialization here: testcenter_user = TestCenterUser.create(student) needs_updating = True - + if needs_updating: - # the registration form normally populates the data dict with + # the registration form normally populates the data dict with # all values from the testcenter_user. But here we only want to # specify those values that change, so update the dict with existing # values. form_options = dict(our_options) for propname in TestCenterUser.user_provided_fields(): - if propname not in form_options: + if propname not in form_options: form_options[propname] = testcenter_user.__getattribute__(propname) form = TestCenterUserForm(instance=testcenter_user, data=form_options) if form.is_valid(): @@ -170,21 +171,20 @@ class Command(BaseCommand): errorlist.append("Non-field Form errors encountered:") for nonfielderror in form.non_field_errors: errorlist.append("Non-field Form Error: {}".format(nonfielderror)) - raise CommandError("\n".join(errorlist)) + raise CommandError("\n".join(errorlist)) else: print "No changes necessary to make to existing user's demographics." - + # override internal values: change_internal = False testcenter_user = TestCenterUser.objects.get(user=student) - for internal_field in [ 'upload_error_message', 'upload_status', 'client_candidate_id']: + for internal_field in ['upload_error_message', 'upload_status', 'client_candidate_id']: if internal_field in our_options: testcenter_user.__setattr__(internal_field, our_options[internal_field]) change_internal = True - + if change_internal: testcenter_user.save() print "Updated confirmation information in existing user's demographics." else: print "No changes necessary to make to confirmation information in existing user's demographics." - diff --git a/common/djangoapps/student/management/commands/pearson_transfer.py b/common/djangoapps/student/management/commands/pearson_transfer.py index 6811e1833d..5eded6484a 100644 --- a/common/djangoapps/student/management/commands/pearson_transfer.py +++ b/common/djangoapps/student/management/commands/pearson_transfer.py @@ -46,10 +46,10 @@ class Command(BaseCommand): if not hasattr(settings, value): raise CommandError('No entry in the AWS settings' '(env/auth.json) for {0}'.format(value)) - + # check additional required settings for import and export: if options['mode'] in ('export', 'both'): - for value in ['LOCAL_EXPORT','SFTP_EXPORT']: + for value in ['LOCAL_EXPORT', 'SFTP_EXPORT']: if value not in settings.PEARSON: raise CommandError('No entry in the PEARSON settings' '(env/auth.json) for {0}'.format(value)) @@ -57,9 +57,9 @@ class Command(BaseCommand): source_dir = settings.PEARSON['LOCAL_EXPORT'] if not os.path.isdir(source_dir): os.makedirs(source_dir) - + if options['mode'] in ('import', 'both'): - for value in ['LOCAL_IMPORT','SFTP_IMPORT']: + for value in ['LOCAL_IMPORT', 'SFTP_IMPORT']: if value not in settings.PEARSON: raise CommandError('No entry in the PEARSON settings' '(env/auth.json) for {0}'.format(value)) @@ -76,7 +76,7 @@ class Command(BaseCommand): t.connect(username=settings.PEARSON['SFTP_USERNAME'], password=settings.PEARSON['SFTP_PASSWORD']) sftp = paramiko.SFTPClient.from_transport(t) - + if mode == 'export': try: sftp.chdir(files_to) @@ -92,7 +92,7 @@ class Command(BaseCommand): except IOError: raise CommandError('SFTP source path does not exist: {}'.format(files_from)) for filename in sftp.listdir('.'): - # skip subdirectories + # skip subdirectories if not S_ISDIR(sftp.stat(filename).st_mode): sftp.get(filename, files_to + '/' + filename) # delete files from sftp server once they are successfully pulled off: @@ -112,7 +112,7 @@ class Command(BaseCommand): try: for filename in os.listdir(files_from): source_file = os.path.join(files_from, filename) - # use mode as name of directory into which to write files + # use mode as name of directory into which to write files dest_file = os.path.join(mode, filename) upload_file_to_s3(bucket, source_file, dest_file) if deleteAfterCopy: @@ -135,17 +135,17 @@ class Command(BaseCommand): k.set_contents_from_filename(source_file) def export_pearson(): - options = { 'dest-from-settings' : True } + options = {'dest-from-settings': True} call_command('pearson_export_cdd', **options) call_command('pearson_export_ead', **options) mode = 'export' - sftp(settings.PEARSON['LOCAL_EXPORT'], settings.PEARSON['SFTP_EXPORT'], mode, deleteAfterCopy = False) + sftp(settings.PEARSON['LOCAL_EXPORT'], settings.PEARSON['SFTP_EXPORT'], mode, deleteAfterCopy=False) s3(settings.PEARSON['LOCAL_EXPORT'], settings.PEARSON['S3_BUCKET'], mode, deleteAfterCopy=True) def import_pearson(): mode = 'import' try: - sftp(settings.PEARSON['SFTP_IMPORT'], settings.PEARSON['LOCAL_IMPORT'], mode, deleteAfterCopy = True) + sftp(settings.PEARSON['SFTP_IMPORT'], settings.PEARSON['LOCAL_IMPORT'], mode, deleteAfterCopy=True) s3(settings.PEARSON['LOCAL_IMPORT'], settings.PEARSON['S3_BUCKET'], mode, deleteAfterCopy=False) except Exception as e: dog_http_api.event('Pearson Import failure', str(e)) diff --git a/common/djangoapps/student/management/commands/tests/test_pearson.py b/common/djangoapps/student/management/commands/tests/test_pearson.py index 2f4878a09d..12969405de 100644 --- a/common/djangoapps/student/management/commands/tests/test_pearson.py +++ b/common/djangoapps/student/management/commands/tests/test_pearson.py @@ -17,30 +17,31 @@ from student.models import User, TestCenterRegistration, TestCenterUser, get_tes log = logging.getLogger(__name__) + def create_tc_user(username): user = User.objects.create_user(username, '{}@edx.org'.format(username), 'fakepass') options = { - 'first_name' : 'TestFirst', - 'last_name' : 'TestLast', - 'address_1' : 'Test Address', - 'city' : 'TestCity', - 'state' : 'Alberta', - 'postal_code' : 'A0B 1C2', - 'country' : 'CAN', - 'phone' : '252-1866', - 'phone_country_code' : '1', + 'first_name': 'TestFirst', + 'last_name': 'TestLast', + 'address_1': 'Test Address', + 'city': 'TestCity', + 'state': 'Alberta', + 'postal_code': 'A0B 1C2', + 'country': 'CAN', + 'phone': '252-1866', + 'phone_country_code': '1', } call_command('pearson_make_tc_user', username, **options) return TestCenterUser.objects.get(user=user) - - -def create_tc_registration(username, course_id = 'org1/course1/term1', exam_code = 'exam1', accommodation_code = None): - - options = { 'exam_series_code' : exam_code, - 'eligibility_appointment_date_first' : '2013-01-01T00:00', - 'eligibility_appointment_date_last' : '2013-12-31T23:59', - 'accommodation_code' : accommodation_code, - 'create_dummy_exam' : True, + + +def create_tc_registration(username, course_id='org1/course1/term1', exam_code='exam1', accommodation_code=None): + + options = {'exam_series_code': exam_code, + 'eligibility_appointment_date_first': '2013-01-01T00:00', + 'eligibility_appointment_date_last': '2013-12-31T23:59', + 'accommodation_code': accommodation_code, + 'create_dummy_exam': True, } call_command('pearson_make_tc_registration', username, course_id, **options) @@ -48,21 +49,23 @@ def create_tc_registration(username, course_id = 'org1/course1/term1', exam_code registrations = get_testcenter_registration(user, course_id, exam_code) return registrations[0] + def create_multiple_registrations(prefix='test'): username1 = '{}_multiple1'.format(prefix) create_tc_user(username1) create_tc_registration(username1) - create_tc_registration(username1, course_id = 'org1/course2/term1') - create_tc_registration(username1, exam_code = 'exam2') + create_tc_registration(username1, course_id='org1/course2/term1') + create_tc_registration(username1, exam_code='exam2') username2 = '{}_multiple2'.format(prefix) create_tc_user(username2) create_tc_registration(username2) username3 = '{}_multiple3'.format(prefix) create_tc_user(username3) - create_tc_registration(username3, course_id = 'org1/course2/term1') + create_tc_registration(username3, course_id='org1/course2/term1') username4 = '{}_multiple4'.format(prefix) create_tc_user(username4) - create_tc_registration(username4, exam_code = 'exam2') + create_tc_registration(username4, exam_code='exam2') + def get_command_error_text(*args, **options): stderr_string = None @@ -75,21 +78,22 @@ def get_command_error_text(*args, **options): # But these are actually translated into nice messages, # and sys.exit(1) is then called. For testing, we # want to catch what sys.exit throws, and get the - # relevant text either from stdout or stderr. + # relevant text either from stdout or stderr. if (why1.message > 0): stderr_string = sys.stderr.getvalue() else: raise why1 except Exception, why: raise why - + finally: sys.stderr = old_stderr - + if stderr_string is None: - raise Exception("Expected call to {} to fail, but it succeeded!".format(args[0])) + raise Exception("Expected call to {} to fail, but it succeeded!".format(args[0])) return stderr_string - + + def get_error_string_for_management_call(*args, **options): stdout_string = None old_stdout = sys.stdout @@ -103,7 +107,7 @@ def get_error_string_for_management_call(*args, **options): # But these are actually translated into nice messages, # and sys.exit(1) is then called. For testing, we # want to catch what sys.exit throws, and get the - # relevant text either from stdout or stderr. + # relevant text either from stdout or stderr. if (why1.message == 1): stdout_string = sys.stdout.getvalue() stderr_string = sys.stderr.getvalue() @@ -111,15 +115,15 @@ def get_error_string_for_management_call(*args, **options): raise why1 except Exception, why: raise why - + finally: sys.stdout = old_stdout sys.stderr = old_stderr - + if stdout_string is None: - raise Exception("Expected call to {} to fail, but it succeeded!".format(args[0])) + raise Exception("Expected call to {} to fail, but it succeeded!".format(args[0])) return stdout_string, stderr_string - + def get_file_info(dirpath): filelist = os.listdir(dirpath) @@ -132,43 +136,45 @@ def get_file_info(dirpath): numlines = len(filecontents) return filepath, numlines else: - raise Exception("Expected to find a single file in {}, but found {}".format(dirpath,filelist)) - + raise Exception("Expected to find a single file in {}, but found {}".format(dirpath, filelist)) + + class PearsonTestCase(TestCase): ''' Base class for tests running Pearson-related commands ''' import_dir = mkdtemp(prefix="import") export_dir = mkdtemp(prefix="export") - + def assertErrorContains(self, error_message, expected): self.assertTrue(error_message.find(expected) >= 0, 'error message "{}" did not contain "{}"'.format(error_message, expected)) - + def tearDown(self): def delete_temp_dir(dirname): if os.path.exists(dirname): for filename in os.listdir(dirname): os.remove(os.path.join(dirname, filename)) os.rmdir(dirname) - + # clean up after any test data was dumped to temp directory delete_temp_dir(self.import_dir) delete_temp_dir(self.export_dir) - + # and clean up the database: # TestCenterUser.objects.all().delete() # TestCenterRegistration.objects.all().delete() + class PearsonCommandTestCase(PearsonTestCase): def test_missing_demographic_fields(self): - # We won't bother to test all details of form validation here. + # We won't bother to test all details of form validation here. # It is enough to show that it works here, but deal with test cases for the form # validation in the student tests, not these management tests. username = 'baduser' User.objects.create_user(username, '{}@edx.org'.format(username), 'fakepass') options = {} - error_string = get_command_error_text('pearson_make_tc_user', username, **options) + error_string = get_command_error_text('pearson_make_tc_user', username, **options) self.assertTrue(error_string.find('Field Form errors encountered:') >= 0) self.assertTrue(error_string.find('Field Form Error: city') >= 0) self.assertTrue(error_string.find('Field Form Error: first_name') >= 0) @@ -178,11 +184,11 @@ class PearsonCommandTestCase(PearsonTestCase): self.assertTrue(error_string.find('Field Form Error: phone') >= 0) self.assertTrue(error_string.find('Field Form Error: address_1') >= 0) self.assertErrorContains(error_string, 'Field Form Error: address_1') - + def test_create_good_testcenter_user(self): testcenter_user = create_tc_user("test_good_user") self.assertIsNotNone(testcenter_user) - + def test_create_good_testcenter_registration(self): username = 'test_good_registration' create_tc_user(username) @@ -192,21 +198,21 @@ class PearsonCommandTestCase(PearsonTestCase): def test_cdd_missing_option(self): error_string = get_command_error_text('pearson_export_cdd', **{}) self.assertErrorContains(error_string, 'Error: --destination or --dest-from-settings must be used') - + def test_ead_missing_option(self): error_string = get_command_error_text('pearson_export_ead', **{}) self.assertErrorContains(error_string, 'Error: --destination or --dest-from-settings must be used') def test_export_single_cdd(self): # before we generate any tc_users, we expect there to be nothing to output: - options = { 'dest-from-settings' : True } - with self.settings(PEARSON={ 'LOCAL_EXPORT' : self.export_dir }): + options = {'dest-from-settings': True} + with self.settings(PEARSON={'LOCAL_EXPORT': self.export_dir}): call_command('pearson_export_cdd', **options) (filepath, numlines) = get_file_info(self.export_dir) self.assertEquals(numlines, 1, "Expect cdd file to have no non-header lines") os.remove(filepath) - # generating a tc_user should result in a line in the output + # generating a tc_user should result in a line in the output username = 'test_single_cdd' create_tc_user(username) call_command('pearson_export_cdd', **options) @@ -221,23 +227,23 @@ class PearsonCommandTestCase(PearsonTestCase): os.remove(filepath) # if we modify the record, then it should be output again: - user_options = { 'first_name' : 'NewTestFirst', } + user_options = {'first_name': 'NewTestFirst', } call_command('pearson_make_tc_user', username, **user_options) call_command('pearson_export_cdd', **options) (filepath, numlines) = get_file_info(self.export_dir) self.assertEquals(numlines, 2, "Expect cdd file to have one non-header line") os.remove(filepath) - + def test_export_single_ead(self): # before we generate any registrations, we expect there to be nothing to output: - options = { 'dest-from-settings' : True } - with self.settings(PEARSON={ 'LOCAL_EXPORT' : self.export_dir }): + options = {'dest-from-settings': True} + with self.settings(PEARSON={'LOCAL_EXPORT': self.export_dir}): call_command('pearson_export_ead', **options) (filepath, numlines) = get_file_info(self.export_dir) self.assertEquals(numlines, 1, "Expect ead file to have no non-header lines") os.remove(filepath) - # generating a registration should result in a line in the output + # generating a registration should result in a line in the output username = 'test_single_ead' create_tc_user(username) create_tc_registration(username) @@ -251,7 +257,7 @@ class PearsonCommandTestCase(PearsonTestCase): (filepath, numlines) = get_file_info(self.export_dir) self.assertEquals(numlines, 1, "Expect ead file to have no non-header lines") os.remove(filepath) - + # if we modify the record, then it should be output again: create_tc_registration(username, accommodation_code='EQPMNT') call_command('pearson_export_ead', **options) @@ -261,8 +267,8 @@ class PearsonCommandTestCase(PearsonTestCase): def test_export_multiple(self): create_multiple_registrations("export") - with self.settings(PEARSON={ 'LOCAL_EXPORT' : self.export_dir }): - options = { 'dest-from-settings' : True } + with self.settings(PEARSON={'LOCAL_EXPORT': self.export_dir}): + options = {'dest-from-settings': True} call_command('pearson_export_cdd', **options) (filepath, numlines) = get_file_info(self.export_dir) self.assertEquals(numlines, 5, "Expect cdd file to have four non-header lines: total was {}".format(numlines)) @@ -294,6 +300,7 @@ S3_BUCKET = 'edx-pearson-archive' AWS_ACCESS_KEY_ID = 'put yours here' AWS_SECRET_ACCESS_KEY = 'put yours here' + class PearsonTransferTestCase(PearsonTestCase): ''' Class for tests running Pearson transfers @@ -302,14 +309,14 @@ class PearsonTransferTestCase(PearsonTestCase): def test_transfer_config(self): with self.settings(DATADOG_API='FAKE_KEY'): # TODO: why is this failing with the wrong error message?! - stderrmsg = get_command_error_text('pearson_transfer', **{'mode' : 'garbage'}) + stderrmsg = get_command_error_text('pearson_transfer', **{'mode': 'garbage'}) self.assertErrorContains(stderrmsg, 'Error: No PEARSON entries') with self.settings(DATADOG_API='FAKE_KEY'): stderrmsg = get_command_error_text('pearson_transfer') self.assertErrorContains(stderrmsg, 'Error: No PEARSON entries') with self.settings(DATADOG_API='FAKE_KEY', - PEARSON={'LOCAL_EXPORT' : self.export_dir, - 'LOCAL_IMPORT' : self.import_dir }): + PEARSON={'LOCAL_EXPORT': self.export_dir, + 'LOCAL_IMPORT': self.import_dir}): stderrmsg = get_command_error_text('pearson_transfer') self.assertErrorContains(stderrmsg, 'Error: No entry in the PEARSON settings') @@ -317,16 +324,16 @@ class PearsonTransferTestCase(PearsonTestCase): raise SkipTest() create_multiple_registrations('export_missing_dest') with self.settings(DATADOG_API='FAKE_KEY', - PEARSON={'LOCAL_EXPORT' : self.export_dir, - 'SFTP_EXPORT' : 'this/does/not/exist', - 'SFTP_HOSTNAME' : SFTP_HOSTNAME, - 'SFTP_USERNAME' : SFTP_USERNAME, - 'SFTP_PASSWORD' : SFTP_PASSWORD, - 'S3_BUCKET' : S3_BUCKET, + PEARSON={'LOCAL_EXPORT': self.export_dir, + 'SFTP_EXPORT': 'this/does/not/exist', + 'SFTP_HOSTNAME': SFTP_HOSTNAME, + 'SFTP_USERNAME': SFTP_USERNAME, + 'SFTP_PASSWORD': SFTP_PASSWORD, + 'S3_BUCKET': S3_BUCKET, }, - AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID, - AWS_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY): - options = { 'mode' : 'export'} + AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY=AWS_SECRET_ACCESS_KEY): + options = {'mode': 'export'} stderrmsg = get_command_error_text('pearson_transfer', **options) self.assertErrorContains(stderrmsg, 'Error: SFTP destination path does not exist') @@ -334,16 +341,16 @@ class PearsonTransferTestCase(PearsonTestCase): raise SkipTest() create_multiple_registrations("transfer_export") with self.settings(DATADOG_API='FAKE_KEY', - PEARSON={'LOCAL_EXPORT' : self.export_dir, - 'SFTP_EXPORT' : 'results/topvue', - 'SFTP_HOSTNAME' : SFTP_HOSTNAME, - 'SFTP_USERNAME' : SFTP_USERNAME, - 'SFTP_PASSWORD' : SFTP_PASSWORD, - 'S3_BUCKET' : S3_BUCKET, + PEARSON={'LOCAL_EXPORT': self.export_dir, + 'SFTP_EXPORT': 'results/topvue', + 'SFTP_HOSTNAME': SFTP_HOSTNAME, + 'SFTP_USERNAME': SFTP_USERNAME, + 'SFTP_PASSWORD': SFTP_PASSWORD, + 'S3_BUCKET': S3_BUCKET, }, - AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID, - AWS_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY): - options = { 'mode' : 'export'} + AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY=AWS_SECRET_ACCESS_KEY): + options = {'mode': 'export'} # call_command('pearson_transfer', **options) # # confirm that the export directory is still empty: # self.assertEqual(len(os.listdir(self.export_dir)), 0, "expected export directory to be empty") @@ -352,16 +359,16 @@ class PearsonTransferTestCase(PearsonTestCase): raise SkipTest() create_multiple_registrations('import_missing_src') with self.settings(DATADOG_API='FAKE_KEY', - PEARSON={'LOCAL_IMPORT' : self.import_dir, - 'SFTP_IMPORT' : 'this/does/not/exist', - 'SFTP_HOSTNAME' : SFTP_HOSTNAME, - 'SFTP_USERNAME' : SFTP_USERNAME, - 'SFTP_PASSWORD' : SFTP_PASSWORD, - 'S3_BUCKET' : S3_BUCKET, + PEARSON={'LOCAL_IMPORT': self.import_dir, + 'SFTP_IMPORT': 'this/does/not/exist', + 'SFTP_HOSTNAME': SFTP_HOSTNAME, + 'SFTP_USERNAME': SFTP_USERNAME, + 'SFTP_PASSWORD': SFTP_PASSWORD, + 'S3_BUCKET': S3_BUCKET, }, - AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID, - AWS_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY): - options = { 'mode' : 'import'} + AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY=AWS_SECRET_ACCESS_KEY): + options = {'mode': 'import'} stderrmsg = get_command_error_text('pearson_transfer', **options) self.assertErrorContains(stderrmsg, 'Error: SFTP source path does not exist') @@ -369,15 +376,15 @@ class PearsonTransferTestCase(PearsonTestCase): raise SkipTest() create_multiple_registrations('import_missing_src') with self.settings(DATADOG_API='FAKE_KEY', - PEARSON={'LOCAL_IMPORT' : self.import_dir, - 'SFTP_IMPORT' : 'results', - 'SFTP_HOSTNAME' : SFTP_HOSTNAME, - 'SFTP_USERNAME' : SFTP_USERNAME, - 'SFTP_PASSWORD' : SFTP_PASSWORD, - 'S3_BUCKET' : S3_BUCKET, + PEARSON={'LOCAL_IMPORT': self.import_dir, + 'SFTP_IMPORT': 'results', + 'SFTP_HOSTNAME': SFTP_HOSTNAME, + 'SFTP_USERNAME': SFTP_USERNAME, + 'SFTP_PASSWORD': SFTP_PASSWORD, + 'S3_BUCKET': S3_BUCKET, }, - AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID, - AWS_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY): - options = { 'mode' : 'import'} + AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY=AWS_SECRET_ACCESS_KEY): + options = {'mode': 'import'} call_command('pearson_transfer', **options) self.assertEqual(len(os.listdir(self.import_dir)), 0, "expected import directory to be empty") diff --git a/common/djangoapps/student/migrations/0020_add_test_center_user.py b/common/djangoapps/student/migrations/0020_add_test_center_user.py index e308e2d7e0..6c0bf5c4ee 100644 --- a/common/djangoapps/student/migrations/0020_add_test_center_user.py +++ b/common/djangoapps/student/migrations/0020_add_test_center_user.py @@ -185,4 +185,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['student'] \ No newline at end of file + complete_apps = ['student'] diff --git a/common/djangoapps/student/migrations/0021_remove_askbot.py b/common/djangoapps/student/migrations/0021_remove_askbot.py index 83ad6791f2..8f76e5078c 100644 --- a/common/djangoapps/student/migrations/0021_remove_askbot.py +++ b/common/djangoapps/student/migrations/0021_remove_askbot.py @@ -36,7 +36,7 @@ class Migration(SchemaMigration): for column in ASKBOT_AUTH_USER_COLUMNS: db.delete_column('auth_user', column) except Exception as ex: - print "Couldn't remove askbot because of {0} -- it was probably never here to begin with.".format(ex) + print "Couldn't remove askbot because of {0} -- it was probably never here to begin with.".format(ex) def backwards(self, orm): raise RuntimeError("Cannot reverse this migration: there's no going back to Askbot.") diff --git a/common/djangoapps/student/migrations/0022_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_.py b/common/djangoapps/student/migrations/0022_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_.py index f7e2571685..769ad6737d 100644 --- a/common/djangoapps/student/migrations/0022_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_.py +++ b/common/djangoapps/student/migrations/0022_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_.py @@ -152,4 +152,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['student'] \ No newline at end of file + complete_apps = ['student'] diff --git a/common/djangoapps/student/migrations/0023_add_test_center_registration.py b/common/djangoapps/student/migrations/0023_add_test_center_registration.py index c5af38dd37..4c7de6dcd9 100644 --- a/common/djangoapps/student/migrations/0023_add_test_center_registration.py +++ b/common/djangoapps/student/migrations/0023_add_test_center_registration.py @@ -238,4 +238,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['student'] \ No newline at end of file + complete_apps = ['student'] diff --git a/common/djangoapps/student/migrations/0024_add_allow_certificate.py b/common/djangoapps/student/migrations/0024_add_allow_certificate.py index fb3a97cd4b..56eccf8d70 100644 --- a/common/djangoapps/student/migrations/0024_add_allow_certificate.py +++ b/common/djangoapps/student/migrations/0024_add_allow_certificate.py @@ -169,4 +169,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['student'] \ No newline at end of file + complete_apps = ['student'] diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 71d2177bd4..54bdd77297 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -107,6 +107,7 @@ class UserProfile(models.Model): TEST_CENTER_STATUS_ACCEPTED = "Accepted" TEST_CENTER_STATUS_ERROR = "Error" + class TestCenterUser(models.Model): """This is our representation of the User for in-person testing, and specifically for Pearson at this point. A few things to note: @@ -190,7 +191,7 @@ class TestCenterUser(models.Model): @staticmethod def user_provided_fields(): - return [ 'first_name', 'middle_name', 'last_name', 'suffix', 'salutation', + return ['first_name', 'middle_name', 'last_name', 'suffix', 'salutation', 'address_1', 'address_2', 'address_3', 'city', 'state', 'postal_code', 'country', 'phone', 'extension', 'phone_country_code', 'fax', 'fax_country_code', 'company_name'] @@ -208,7 +209,7 @@ class TestCenterUser(models.Model): @staticmethod def _generate_edx_id(prefix): NUM_DIGITS = 12 - return u"{}{:012}".format(prefix, randint(1, 10**NUM_DIGITS-1)) + return u"{}{:012}".format(prefix, randint(1, 10 ** NUM_DIGITS - 1)) @staticmethod def _generate_candidate_id(): @@ -237,10 +238,11 @@ class TestCenterUser(models.Model): def is_pending(self): return not self.is_accepted and not self.is_rejected + class TestCenterUserForm(ModelForm): class Meta: model = TestCenterUser - fields = ( 'first_name', 'middle_name', 'last_name', 'suffix', 'salutation', + fields = ('first_name', 'middle_name', 'last_name', 'suffix', 'salutation', 'address_1', 'address_2', 'address_3', 'city', 'state', 'postal_code', 'country', 'phone', 'extension', 'phone_country_code', 'fax', 'fax_country_code', 'company_name') @@ -313,7 +315,8 @@ ACCOMMODATION_CODES = ( ('SRSGNR', 'Separate Room and Sign Language Interpreter'), ) -ACCOMMODATION_CODE_DICT = { code : name for (code, name) in ACCOMMODATION_CODES } +ACCOMMODATION_CODE_DICT = {code: name for (code, name) in ACCOMMODATION_CODES} + class TestCenterRegistration(models.Model): """ @@ -389,10 +392,10 @@ class TestCenterRegistration(models.Model): elif self.uploaded_at is None: return 'Add' elif self.registration_is_rejected: - # Assume that if the registration was rejected before, - # it is more likely this is the (first) correction + # Assume that if the registration was rejected before, + # it is more likely this is the (first) correction # than a second correction in flight before the first was - # processed. + # processed. return 'Add' else: # TODO: decide what to send when we have uploaded an initial version, @@ -417,7 +420,7 @@ class TestCenterRegistration(models.Model): @classmethod def create(cls, testcenter_user, exam, accommodation_request): - registration = cls(testcenter_user = testcenter_user) + registration = cls(testcenter_user=testcenter_user) registration.course_id = exam.course_id registration.accommodation_request = accommodation_request.strip() registration.exam_series_code = exam.exam_series_code @@ -501,7 +504,7 @@ class TestCenterRegistration(models.Model): return self.accommodation_code.split('*') def get_accommodation_names(self): - return [ ACCOMMODATION_CODE_DICT.get(code, "Unknown code " + code) for code in self.get_accommodation_codes() ] + return [ACCOMMODATION_CODE_DICT.get(code, "Unknown code " + code) for code in self.get_accommodation_codes()] @property def registration_signup_url(self): @@ -512,7 +515,7 @@ class TestCenterRegistration(models.Model): return "Accepted" elif self.demographics_is_rejected: return "Rejected" - else: + else: return "Pending" def accommodation_status(self): @@ -522,7 +525,7 @@ class TestCenterRegistration(models.Model): return "Accepted" elif self.accommodation_is_rejected: return "Rejected" - else: + else: return "Pending" def registration_status(self): @@ -532,12 +535,12 @@ class TestCenterRegistration(models.Model): return "Rejected" else: return "Pending" - + class TestCenterRegistrationForm(ModelForm): class Meta: model = TestCenterRegistration - fields = ( 'accommodation_request', 'accommodation_code' ) + fields = ('accommodation_request', 'accommodation_code') def clean_accommodation_request(self): code = self.cleaned_data['accommodation_request'] @@ -576,6 +579,7 @@ def get_testcenter_registration(user, course_id, exam_series_code): # Correct this (https://nose.readthedocs.org/en/latest/finding_tests.html) get_testcenter_registration.__test__ = False + def unique_id_for_user(user): """ Return a unique id for a user, suitable for inserting into @@ -666,6 +670,7 @@ class CourseEnrollmentAllowed(models.Model): #### Helper methods for use from python manage.py shell and other classes. + def get_user_by_username_or_email(username_or_email): """ Return a User object, looking up by email if username_or_email contains a @@ -767,4 +772,3 @@ def update_user_information(sender, instance, created, **kwargs): log = logging.getLogger("mitx.discussion") log.error(unicode(e)) log.error("update user info to discussion failed for user with id: " + str(instance.id)) - diff --git a/common/djangoapps/student/tests.py b/common/djangoapps/student/tests.py index 8ce407bcd1..6a2d75e3d8 100644 --- a/common/djangoapps/student/tests.py +++ b/common/djangoapps/student/tests.py @@ -17,6 +17,7 @@ COURSE_2 = 'edx/full/6.002_Spring_2012' log = logging.getLogger(__name__) + class CourseEndingTest(TestCase): """Test things related to course endings: certificates, surveys, etc""" @@ -40,7 +41,7 @@ class CourseEndingTest(TestCase): {'status': 'processing', 'show_disabled_download_button': False, 'show_download_url': False, - 'show_survey_button': False,}) + 'show_survey_button': False, }) cert_status = {'status': 'unavailable'} self.assertEqual(_cert_info(user, course, cert_status), diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index b583599e97..bf279e7b08 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -50,6 +50,7 @@ from statsd import statsd log = logging.getLogger("mitx.student") Article = namedtuple('Article', 'title url author image deck publication publish_date') + def csrf_token(context): ''' A csrf token that can be included in a form. ''' @@ -73,8 +74,8 @@ def index(request, extra_context={}, user=None): ''' # The course selection work is done in courseware.courses. - domain = settings.MITX_FEATURES.get('FORCE_UNIVERSITY_DOMAIN') # normally False - if domain==False: # do explicit check, because domain=None is valid + domain = settings.MITX_FEATURES.get('FORCE_UNIVERSITY_DOMAIN') # normally False + if domain == False: # do explicit check, because domain=None is valid domain = request.META.get('HTTP_HOST') courses = get_courses(None, domain=domain) @@ -97,6 +98,7 @@ import re day_pattern = re.compile('\s\d+,\s') multimonth_pattern = re.compile('\s?\-\s?\S+\s') + def get_date_for_press(publish_date): import datetime # strip off extra months, and just use the first: @@ -107,6 +109,7 @@ def get_date_for_press(publish_date): date = datetime.datetime.strptime(date, "%B, %Y") return date + def press(request): json_articles = cache.get("student_press_json_articles") if json_articles == None: @@ -148,6 +151,7 @@ def cert_info(user, course): return _cert_info(user, course, certificate_status_for_student(user, course.id)) + def _cert_info(user, course, cert_status): """ Implements the logic for cert_info -- split out for testing. @@ -175,7 +179,7 @@ def _cert_info(user, course, cert_status): d = {'status': status, 'show_download_url': status == 'ready', - 'show_disabled_download_button': status == 'generating',} + 'show_disabled_download_button': status == 'generating', } if (status in ('generating', 'ready', 'notpassing', 'restricted') and course.end_of_course_survey_url is not None): @@ -204,6 +208,7 @@ def _cert_info(user, course, cert_status): return d + @login_required @ensure_csrf_cookie def dashboard(request): @@ -237,9 +242,9 @@ def dashboard(request): show_courseware_links_for = frozenset(course.id for course in courses if has_access(request.user, course, 'load')) - cert_statuses = { course.id: cert_info(request.user, course) for course in courses} + cert_statuses = {course.id: cert_info(request.user, course) for course in courses} - exam_registrations = { course.id: exam_registration_info(request.user, course) for course in courses} + exam_registrations = {course.id: exam_registration_info(request.user, course) for course in courses} # Get the 3 most recent news top_news = _get_news(top=3) @@ -248,7 +253,7 @@ def dashboard(request): 'message': message, 'staff_access': staff_access, 'errored_courses': errored_courses, - 'show_courseware_links_for' : show_courseware_links_for, + 'show_courseware_links_for': show_courseware_links_for, 'cert_statuses': cert_statuses, 'news': top_news, 'exam_registrations': exam_registrations, @@ -312,7 +317,7 @@ def change_enrollment(request): 'error': 'enrollment in {} not allowed at this time' .format(course.display_name)} - org, course_num, run=course_id.split("/") + org, course_num, run = course_id.split("/") statsd.increment("common.student.enrollment", tags=["org:{0}".format(org), "course:{0}".format(course_num), @@ -326,7 +331,7 @@ def change_enrollment(request): enrollment = CourseEnrollment.objects.get(user=user, course_id=course_id) enrollment.delete() - org, course_num, run=course_id.split("/") + org, course_num, run = course_id.split("/") statsd.increment("common.student.unenrollment", tags=["org:{0}".format(org), "course:{0}".format(course_num), @@ -345,7 +350,7 @@ def change_enrollment(request): def accounts_login(request, error=""): - return render_to_response('accounts_login.html', { 'error': error }) + return render_to_response('accounts_login.html', {'error': error}) @@ -424,6 +429,7 @@ def change_setting(request): return HttpResponse(json.dumps({'success': True, 'location': up.location, })) + def _do_create_account(post_vars): """ Given cleaned post variables, create the User and UserProfile objects, as well as the @@ -551,7 +557,7 @@ def create_account(request, post_override=None): # Ok, looks like everything is legit. Create the account. ret = _do_create_account(post_vars) - if isinstance(ret,HttpResponse): # if there was an error then return that + if isinstance(ret, HttpResponse): # if there was an error then return that return ret (user, profile, registration) = ret @@ -591,7 +597,7 @@ def create_account(request, post_override=None): eamap.user = login_user eamap.dtsignup = datetime.datetime.now() eamap.save() - log.debug('Updated ExternalAuthMap for %s to be %s' % (post_vars['username'],eamap)) + log.debug('Updated ExternalAuthMap for %s to be %s' % (post_vars['username'], eamap)) if settings.MITX_FEATURES.get('BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'): log.debug('bypassing activation email') @@ -603,6 +609,7 @@ def create_account(request, post_override=None): js = {'success': True} return HttpResponse(json.dumps(js), mimetype="application/json") + def exam_registration_info(user, course): """ Returns a Registration object if the user is currently registered for a current exam of the course. Returns None if the user is not registered, or if there is no @@ -620,6 +627,7 @@ def exam_registration_info(user, course): registration = None return registration + @login_required @ensure_csrf_cookie def begin_exam_registration(request, course_id): @@ -663,6 +671,7 @@ def begin_exam_registration(request, course_id): return render_to_response('test_center_register.html', context) + @ensure_csrf_cookie def create_exam_registration(request, post_override=None): ''' @@ -725,7 +734,7 @@ def create_exam_registration(request, post_override=None): # this registration screen. else: - accommodation_request = post_vars.get('accommodation_request','') + accommodation_request = post_vars.get('accommodation_request', '') registration = TestCenterRegistration.create(testcenter_user, exam, accommodation_request) needs_saving = True log.info("User {0} enrolled in course {1} creating new exam registration".format(user.username, course_id)) @@ -834,16 +843,17 @@ def password_reset(request): form = PasswordResetForm(request.POST) if form.is_valid(): - form.save(use_https = request.is_secure(), - from_email = settings.DEFAULT_FROM_EMAIL, - request = request, - domain_override = request.get_host()) - return HttpResponse(json.dumps({'success':True, + form.save(use_https=request.is_secure(), + from_email=settings.DEFAULT_FROM_EMAIL, + request=request, + domain_override=request.get_host()) + return HttpResponse(json.dumps({'success': True, 'value': render_to_string('registration/password_reset_done.html', {})})) else: return HttpResponse(json.dumps({'success': False, 'error': 'Invalid e-mail'})) + @ensure_csrf_cookie def reactivation_email(request): ''' Send an e-mail to reactivate a deactivated account, or to @@ -856,6 +866,7 @@ def reactivation_email(request): 'error': 'No inactive user with this e-mail exists'})) return reactivation_email_for_user(user) + def reactivation_email_for_user(user): reg = Registration.objects.get(user=user) @@ -996,11 +1007,11 @@ def pending_name_changes(request): changes = list(PendingNameChange.objects.all()) js = {'students': [{'new_name': c.new_name, - 'rationale':c.rationale, - 'old_name':UserProfile.objects.get(user=c.user).name, - 'email':c.user.email, - 'uid':c.user.id, - 'cid':c.id} for c in changes]} + 'rationale': c.rationale, + 'old_name': UserProfile.objects.get(user=c.user).name, + 'email': c.user.email, + 'uid': c.user.id, + 'cid': c.id} for c in changes]} return render_to_response('name_changes.html', js) @@ -1057,6 +1068,8 @@ def accept_name_change(request): # TODO: This is a giant kludge to give Pearson something to test against ASAP. # Will need to get replaced by something that actually ties into TestCenterUser + + @csrf_exempt def test_center_login(request): if not settings.MITX_FEATURES.get('ENABLE_PEARSON_HACK_TEST'): diff --git a/common/djangoapps/track/migrations/0001_initial.py b/common/djangoapps/track/migrations/0001_initial.py index 0546203cf8..6ec146dd10 100644 --- a/common/djangoapps/track/migrations/0001_initial.py +++ b/common/djangoapps/track/migrations/0001_initial.py @@ -45,4 +45,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['track'] \ No newline at end of file + complete_apps = ['track'] diff --git a/common/djangoapps/track/migrations/0002_auto__add_field_trackinglog_host__chg_field_trackinglog_event_type__ch.py b/common/djangoapps/track/migrations/0002_auto__add_field_trackinglog_host__chg_field_trackinglog_event_type__ch.py index 4c73aa3bfd..0bb0cde42e 100644 --- a/common/djangoapps/track/migrations/0002_auto__add_field_trackinglog_host__chg_field_trackinglog_event_type__ch.py +++ b/common/djangoapps/track/migrations/0002_auto__add_field_trackinglog_host__chg_field_trackinglog_event_type__ch.py @@ -48,4 +48,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['track'] \ No newline at end of file + complete_apps = ['track'] diff --git a/common/djangoapps/track/models.py b/common/djangoapps/track/models.py index dfdf7a0558..b6a16706c1 100644 --- a/common/djangoapps/track/models.py +++ b/common/djangoapps/track/models.py @@ -2,21 +2,20 @@ from django.db import models from django.db import models + class TrackingLog(models.Model): - dtcreated = models.DateTimeField('creation date',auto_now_add=True) - username = models.CharField(max_length=32,blank=True) - ip = models.CharField(max_length=32,blank=True) + dtcreated = models.DateTimeField('creation date', auto_now_add=True) + username = models.CharField(max_length=32, blank=True) + ip = models.CharField(max_length=32, blank=True) event_source = models.CharField(max_length=32) - event_type = models.CharField(max_length=512,blank=True) + event_type = models.CharField(max_length=512, blank=True) event = models.TextField(blank=True) - agent = models.CharField(max_length=256,blank=True) - page = models.CharField(max_length=512,blank=True,null=True) + agent = models.CharField(max_length=256, blank=True) + page = models.CharField(max_length=512, blank=True, null=True) time = models.DateTimeField('event time') - host = models.CharField(max_length=64,blank=True) + host = models.CharField(max_length=64, blank=True) def __unicode__(self): s = "[%s] %s@%s: %s | %s | %s | %s" % (self.time, self.username, self.ip, self.event_source, self.event_type, self.page, self.event) return s - - diff --git a/common/djangoapps/track/views.py b/common/djangoapps/track/views.py index 54bd476799..ae3a1dcb3e 100644 --- a/common/djangoapps/track/views.py +++ b/common/djangoapps/track/views.py @@ -17,19 +17,21 @@ from track.models import TrackingLog log = logging.getLogger("tracking") -LOGFIELDS = ['username','ip','event_source','event_type','event','agent','page','time','host'] +LOGFIELDS = ['username', 'ip', 'event_source', 'event_type', 'event', 'agent', 'page', 'time', 'host'] + def log_event(event): event_str = json.dumps(event) log.info(event_str[:settings.TRACK_MAX_EVENT]) if settings.MITX_FEATURES.get('ENABLE_SQL_TRACKING_LOGS'): event['time'] = dateutil.parser.parse(event['time']) - tldat = TrackingLog(**dict( (x,event[x]) for x in LOGFIELDS )) + tldat = TrackingLog(**dict((x, event[x]) for x in LOGFIELDS)) try: tldat.save() except Exception as err: log.exception(err) + def user_track(request): try: # TODO: Do the same for many of the optional META parameters username = request.user.username @@ -87,13 +89,14 @@ def server_track(request, event_type, event, page=None): "host": request.META['SERVER_NAME'], } - if event_type.startswith("/event_logs") and request.user.is_staff: # don't log + if event_type.startswith("/event_logs") and request.user.is_staff: # don't log return log_event(event) + @login_required @ensure_csrf_cookie -def view_tracking_log(request,args=''): +def view_tracking_log(request, args=''): if not request.user.is_staff: return redirect('/') nlen = 100 @@ -104,16 +107,15 @@ def view_tracking_log(request,args=''): nlen = int(arg) if arg.startswith('username='): username = arg[9:] - + record_instances = TrackingLog.objects.all().order_by('-time') if username: record_instances = record_instances.filter(username=username) record_instances = record_instances[0:nlen] - + # fix dtstamp fmt = '%a %d-%b-%y %H:%M:%S' # "%Y-%m-%d %H:%M:%S %Z%z" for rinst in record_instances: rinst.dtstr = rinst.time.replace(tzinfo=pytz.utc).astimezone(pytz.timezone('US/Eastern')).strftime(fmt) - return render_to_response('tracking_log.html',{'records':record_instances}) - + return render_to_response('tracking_log.html', {'records': record_instances}) diff --git a/common/djangoapps/util/cache.py b/common/djangoapps/util/cache.py index 89b5dffd5e..8ab1b06acd 100644 --- a/common/djangoapps/util/cache.py +++ b/common/djangoapps/util/cache.py @@ -58,4 +58,3 @@ def cache_if_anonymous(view_func): return view_func(request, *args, **kwargs) return _decorated - diff --git a/common/djangoapps/util/converters.py b/common/djangoapps/util/converters.py index 7f96dc6c30..900371a0dd 100644 --- a/common/djangoapps/util/converters.py +++ b/common/djangoapps/util/converters.py @@ -1,7 +1,9 @@ -import time, datetime +import time +import datetime import re import calendar + def time_to_date(time_obj): """ Convert a time.time_struct to a true universal time (can pass to js Date constructor) @@ -9,6 +11,7 @@ def time_to_date(time_obj): # TODO change to using the isoformat() function on datetime. js date can parse those return calendar.timegm(time_obj) * 1000 + def jsdate_to_time(field): """ Convert a universal time (iso format) or msec since epoch to a time obj @@ -16,9 +19,9 @@ def jsdate_to_time(field): if field is None: return field elif isinstance(field, basestring): # iso format but ignores time zone assuming it's Z - d=datetime.datetime(*map(int, re.split('[^\d]', field)[:6])) # stop after seconds. Debatable + d = datetime.datetime(*map(int, re.split('[^\d]', field)[:6])) # stop after seconds. Debatable return d.utctimetuple() elif isinstance(field, int) or isinstance(field, float): return time.gmtime(field / 1000) elif isinstance(field, time.struct_time): - return field \ No newline at end of file + return field diff --git a/common/djangoapps/util/json_request.py b/common/djangoapps/util/json_request.py index 4beff7bdc8..840a8282f9 100644 --- a/common/djangoapps/util/json_request.py +++ b/common/djangoapps/util/json_request.py @@ -13,7 +13,7 @@ def expect_json(view_function): def expect_json_with_cloned_request(request, *args, **kwargs): # cdodge: fix postback errors in CMS. The POST 'content-type' header can include additional information # e.g. 'charset', so we can't do a direct string compare - if request.META.get('CONTENT_TYPE','').lower().startswith("application/json"): + if request.META.get('CONTENT_TYPE', '').lower().startswith("application/json"): cloned_request = copy.copy(request) cloned_request.POST = cloned_request.POST.copy() cloned_request.POST.update(json.loads(request.body)) diff --git a/common/djangoapps/util/views.py b/common/djangoapps/util/views.py index 0ccdd03301..cece37757b 100644 --- a/common/djangoapps/util/views.py +++ b/common/djangoapps/util/views.py @@ -93,6 +93,7 @@ def accepts(request, media_type): accept = parse_accept_header(request.META.get("HTTP_ACCEPT", "")) return media_type in [t for (t, p, q) in accept] + def debug_request(request): """Return a pretty printed version of the request""" diff --git a/common/djangoapps/xmodule_modifiers.py b/common/djangoapps/xmodule_modifiers.py index b171b402ee..7b19c27553 100644 --- a/common/djangoapps/xmodule_modifiers.py +++ b/common/djangoapps/xmodule_modifiers.py @@ -12,6 +12,7 @@ from xmodule.vertical_module import VerticalModule log = logging.getLogger("mitx.xmodule_modifiers") + def wrap_xmodule(get_html, module, template, context=None): """ Wraps the results of get_html in a standard
            with identifying @@ -32,7 +33,7 @@ def wrap_xmodule(get_html, module, template, context=None): def _get_html(): context.update({ 'content': get_html(), - 'display_name' : module.metadata.get('display_name') if module.metadata is not None else None, + 'display_name': module.metadata.get('display_name') if module.metadata is not None else None, 'class_': module.__class__.__name__, 'module_name': module.js_module_name }) @@ -52,6 +53,7 @@ def replace_course_urls(get_html, course_id): return static_replace.replace_course_urls(get_html(), course_id) return _get_html + def replace_static_urls(get_html, data_dir, course_namespace=None): """ Updates the supplied module with a new get_html function that wraps @@ -64,6 +66,7 @@ def replace_static_urls(get_html, data_dir, course_namespace=None): return static_replace.replace_static_urls(get_html(), data_dir, course_namespace) return _get_html + def grade_histogram(module_id): ''' Print out a histogram of grades on a given problem. Part of staff member debug info. @@ -98,7 +101,7 @@ def add_histogram(get_html, module, user): @wraps(get_html) def _get_html(): - if type(module) in [SequenceModule, VerticalModule]: # TODO: make this more general, eg use an XModule attribute instead + if type(module) in [SequenceModule, VerticalModule]: # TODO: make this more general, eg use an XModule attribute instead return get_html() module_id = module.id @@ -114,35 +117,35 @@ def add_histogram(get_html, module, user): # doesn't like symlinks) filepath = filename data_dir = osfs.root_path.rsplit('/')[-1] - giturl = module.metadata.get('giturl','https://github.com/MITx') - edit_link = "%s/%s/tree/master/%s" % (giturl,data_dir,filepath) + giturl = module.metadata.get('giturl', 'https://github.com/MITx') + edit_link = "%s/%s/tree/master/%s" % (giturl, data_dir, filepath) else: edit_link = False # Need to define all the variables that are about to be used giturl = "" data_dir = "" - source_file = module.metadata.get('source_file','') # source used to generate the problem XML, eg latex or word + source_file = module.metadata.get('source_file', '') # source used to generate the problem XML, eg latex or word # useful to indicate to staff if problem has been released or not # TODO (ichuang): use _has_access_descriptor.can_load in lms.courseware.access, instead of now>mstart comparison here now = time.gmtime() is_released = "unknown" - mstart = getattr(module.descriptor,'start') + mstart = getattr(module.descriptor, 'start') if mstart is not None: is_released = "Yes!" if (now > mstart) else "Not yet" staff_context = {'definition': module.definition.get('data'), 'metadata': json.dumps(module.metadata, indent=4), 'location': module.location, - 'xqa_key': module.metadata.get('xqa_key',''), - 'source_file' : source_file, - 'source_url': '%s/%s/tree/master/%s' % (giturl,data_dir,source_file), + 'xqa_key': module.metadata.get('xqa_key', ''), + 'source_file': source_file, + 'source_url': '%s/%s/tree/master/%s' % (giturl, data_dir, source_file), 'category': str(module.__class__.__name__), # Template uses element_id in js function names, so can't allow dashes - 'element_id': module.location.html_id().replace('-','_'), + 'element_id': module.location.html_id().replace('-', '_'), 'edit_link': edit_link, 'user': user, - 'xqa_server' : settings.MITX_FEATURES.get('USE_XQA_SERVER','http://xqa:server@content-qa.mitx.mit.edu/xqa'), + 'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://xqa:server@content-qa.mitx.mit.edu/xqa'), 'histogram': json.dumps(histogram), 'render_histogram': render_histogram, 'module_content': get_html(), @@ -151,4 +154,3 @@ def add_histogram(get_html, module, user): return render_to_string("staff_problem_info.html", staff_context) return _get_html - diff --git a/common/lib/capa/capa/calc.py b/common/lib/capa/capa/calc.py index 40ac14308e..0f062d17d5 100644 --- a/common/lib/capa/capa/calc.py +++ b/common/lib/capa/capa/calc.py @@ -121,9 +121,9 @@ def evaluator(variables, functions, string, cs=False): # confusing. They may also conflict with variables if we ever allow e.g. # 5R instead of 5*R suffixes = {'%': 0.01, 'k': 1e3, 'M': 1e6, 'G': 1e9, - 'T': 1e12,# 'P':1e15,'E':1e18,'Z':1e21,'Y':1e24, + 'T': 1e12, # 'P':1e15,'E':1e18,'Z':1e21,'Y':1e24, 'c': 1e-2, 'm': 1e-3, 'u': 1e-6, - 'n': 1e-9, 'p': 1e-12}# ,'f':1e-15,'a':1e-18,'z':1e-21,'y':1e-24} + 'n': 1e-9, 'p': 1e-12} # ,'f':1e-15,'a':1e-18,'z':1e-21,'y':1e-24} def super_float(text): ''' Like float, but with si extensions. 1k goes to 1000''' diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index 4b0faa91a1..9b8bbd7288 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -75,7 +75,7 @@ global_context = {'random': random, 'draganddrop': verifiers.draganddrop} # These should be removed from HTML output, including all subelements -html_problem_semantics = ["codeparam", "responseparam", "answer", "script", "hintgroup", "openendedparam","openendedrubric"] +html_problem_semantics = ["codeparam", "responseparam", "answer", "script", "hintgroup", "openendedparam", "openendedrubric"] log = logging.getLogger('mitx.' + __name__) @@ -453,7 +453,7 @@ class LoncapaProblem(object): exec code in context, context except Exception as err: log.exception("Error while execing script code: " + code) - msg = "Error while executing script code: %s" % str(err).replace('<','<') + msg = "Error while executing script code: %s" % str(err).replace('<', '<') raise responsetypes.LoncapaProblemError(msg) finally: sys.path = original_path @@ -502,7 +502,7 @@ class LoncapaProblem(object): 'id': problemtree.get('id'), 'feedback': {'message': msg, 'hint': hint, - 'hintmode': hintmode,}} + 'hintmode': hintmode, }} input_type_cls = inputtypes.registry.get_class_for_tag(problemtree.tag) the_input = input_type_cls(self.system, problemtree, state) diff --git a/common/lib/capa/capa/chem/__init__.py b/common/lib/capa/capa/chem/__init__.py index 8b13789179..e69de29bb2 100644 --- a/common/lib/capa/capa/chem/__init__.py +++ b/common/lib/capa/capa/chem/__init__.py @@ -1 +0,0 @@ - diff --git a/common/lib/capa/capa/chem/chemcalc.py b/common/lib/capa/capa/chem/chemcalc.py index 389e688cf4..5b80005044 100644 --- a/common/lib/capa/capa/chem/chemcalc.py +++ b/common/lib/capa/capa/chem/chemcalc.py @@ -17,17 +17,17 @@ from nltk.tree import Tree ARROWS = ('<->', '->') ## Defines a simple pyparsing tokenizer for chemical equations -elements = ['Ac','Ag','Al','Am','Ar','As','At','Au','B','Ba','Be', - 'Bh','Bi','Bk','Br','C','Ca','Cd','Ce','Cf','Cl','Cm', - 'Cn','Co','Cr','Cs','Cu','Db','Ds','Dy','Er','Es','Eu', - 'F','Fe','Fl','Fm','Fr','Ga','Gd','Ge','H','He','Hf', - 'Hg','Ho','Hs','I','In','Ir','K','Kr','La','Li','Lr', - 'Lu','Lv','Md','Mg','Mn','Mo','Mt','N','Na','Nb','Nd', - 'Ne','Ni','No','Np','O','Os','P','Pa','Pb','Pd','Pm', - 'Po','Pr','Pt','Pu','Ra','Rb','Re','Rf','Rg','Rh','Rn', - 'Ru','S','Sb','Sc','Se','Sg','Si','Sm','Sn','Sr','Ta', - 'Tb','Tc','Te','Th','Ti','Tl','Tm','U','Uuo','Uup', - 'Uus','Uut','V','W','Xe','Y','Yb','Zn','Zr'] +elements = ['Ac', 'Ag', 'Al', 'Am', 'Ar', 'As', 'At', 'Au', 'B', 'Ba', 'Be', + 'Bh', 'Bi', 'Bk', 'Br', 'C', 'Ca', 'Cd', 'Ce', 'Cf', 'Cl', 'Cm', + 'Cn', 'Co', 'Cr', 'Cs', 'Cu', 'Db', 'Ds', 'Dy', 'Er', 'Es', 'Eu', + 'F', 'Fe', 'Fl', 'Fm', 'Fr', 'Ga', 'Gd', 'Ge', 'H', 'He', 'Hf', + 'Hg', 'Ho', 'Hs', 'I', 'In', 'Ir', 'K', 'Kr', 'La', 'Li', 'Lr', + 'Lu', 'Lv', 'Md', 'Mg', 'Mn', 'Mo', 'Mt', 'N', 'Na', 'Nb', 'Nd', + 'Ne', 'Ni', 'No', 'Np', 'O', 'Os', 'P', 'Pa', 'Pb', 'Pd', 'Pm', + 'Po', 'Pr', 'Pt', 'Pu', 'Ra', 'Rb', 'Re', 'Rf', 'Rg', 'Rh', 'Rn', + 'Ru', 'S', 'Sb', 'Sc', 'Se', 'Sg', 'Si', 'Sm', 'Sn', 'Sr', 'Ta', + 'Tb', 'Tc', 'Te', 'Th', 'Ti', 'Tl', 'Tm', 'U', 'Uuo', 'Uup', + 'Uus', 'Uut', 'V', 'W', 'Xe', 'Y', 'Yb', 'Zn', 'Zr'] digits = map(str, range(10)) symbols = list("[](){}^+-/") phases = ["(s)", "(l)", "(g)", "(aq)"] @@ -252,7 +252,7 @@ def _get_final_tree(s): ''' tokenized = tokenizer.parseString(s) parsed = parser.parse(tokenized) - merged = _merge_children(parsed, {'S','group'}) + merged = _merge_children(parsed, {'S', 'group'}) final = _clean_parse_tree(merged) return final diff --git a/common/lib/capa/capa/correctmap.py b/common/lib/capa/capa/correctmap.py index c7386219b1..a78b10d07a 100644 --- a/common/lib/capa/capa/correctmap.py +++ b/common/lib/capa/capa/correctmap.py @@ -3,6 +3,7 @@ # # Used by responsetypes and capa_problem + class CorrectMap(object): """ Stores map between answer_id and response evaluation result for each question @@ -152,6 +153,3 @@ class CorrectMap(object): if not isinstance(other_cmap, CorrectMap): raise Exception('CorrectMap.update called with invalid argument %s' % other_cmap) self.cmap.update(other_cmap.get_dict()) - - - diff --git a/common/lib/capa/capa/customrender.py b/common/lib/capa/capa/customrender.py index ef1044e8b1..a925a5970d 100644 --- a/common/lib/capa/capa/customrender.py +++ b/common/lib/capa/capa/customrender.py @@ -22,6 +22,8 @@ log = logging.getLogger('mitx.' + __name__) registry = TagRegistry() #----------------------------------------------------------------------------- + + class MathRenderer(object): tags = ['math'] @@ -77,6 +79,7 @@ registry.register(MathRenderer) #----------------------------------------------------------------------------- + class SolutionRenderer(object): ''' A solution is just a ... which is given an ID, that is used for displaying an @@ -97,4 +100,3 @@ class SolutionRenderer(object): return etree.XML(html) registry.register(SolutionRenderer) - diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index 0b0e86ce66..83c79a7247 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -54,6 +54,7 @@ log = logging.getLogger('mitx.' + __name__) registry = TagRegistry() + class Attribute(object): """ Allows specifying required and optional attributes for input types. @@ -413,7 +414,7 @@ class JavascriptInput(InputTypeBase): return [Attribute('params', None), Attribute('problem_state', None), Attribute('display_class', None), - Attribute('display_file', None),] + Attribute('display_file', None), ] def setup(self): @@ -477,12 +478,13 @@ class TextLine(InputTypeBase): def _extra_context(self): return {'do_math': self.do_math, - 'preprocessor': self.preprocessor,} + 'preprocessor': self.preprocessor, } registry.register(TextLine) #----------------------------------------------------------------------------- + class FileSubmission(InputTypeBase): """ Upload some files (e.g. for programming assignments) @@ -508,7 +510,7 @@ class FileSubmission(InputTypeBase): Convert the list of allowed files to a convenient format. """ return [Attribute('allowed_files', '[]', transform=cls.parse_files), - Attribute('required_files', '[]', transform=cls.parse_files),] + Attribute('required_files', '[]', transform=cls.parse_files), ] def setup(self): """ @@ -524,7 +526,7 @@ class FileSubmission(InputTypeBase): self.msg = FileSubmission.submitted_msg def _extra_context(self): - return {'queue_len': self.queue_len,} + return {'queue_len': self.queue_len, } return context registry.register(FileSubmission) @@ -582,7 +584,7 @@ class CodeInput(InputTypeBase): def _extra_context(self): """Defined queue_len, add it """ - return {'queue_len': self.queue_len,} + return {'queue_len': self.queue_len, } registry.register(CodeInput) @@ -606,7 +608,7 @@ class Schematic(InputTypeBase): Attribute('parts', None), Attribute('analyses', None), Attribute('initial_value', None), - Attribute('submit_analyses', None),] + Attribute('submit_analyses', None), ] return context @@ -614,6 +616,7 @@ registry.register(Schematic) #----------------------------------------------------------------------------- + class ImageInput(InputTypeBase): """ Clickable image as an input field. Element should specify the image source, height, @@ -635,7 +638,7 @@ class ImageInput(InputTypeBase): """ return [Attribute('src'), Attribute('height'), - Attribute('width'),] + Attribute('width'), ] def setup(self): @@ -660,6 +663,7 @@ registry.register(ImageInput) #----------------------------------------------------------------------------- + class Crystallography(InputTypeBase): """ An input for crystallography -- user selects 3 points on the axes, and we get a plane. @@ -728,18 +732,19 @@ class ChemicalEquationInput(InputTypeBase): """ Can set size of text field. """ - return [Attribute('size', '20'),] + return [Attribute('size', '20'), ] def _extra_context(self): """ TODO (vshnayder): Get rid of this once we have a standard way of requiring js to be loaded. """ - return {'previewer': '/static/js/capa/chemical_equation_preview.js',} + return {'previewer': '/static/js/capa/chemical_equation_preview.js', } registry.register(ChemicalEquationInput) #----------------------------------------------------------------------------- + class DragAndDropInput(InputTypeBase): """ Input for drag and drop problems. Allows student to drag and drop images and diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py index 5f0e1639b2..adf5eda416 100644 --- a/common/lib/capa/capa/responsetypes.py +++ b/common/lib/capa/capa/responsetypes.py @@ -186,9 +186,9 @@ class LoncapaResponse(object): tree = etree.Element('span') # problem author can make this span display:inline - if self.xml.get('inline',''): - tree.set('class','inline') - + if self.xml.get('inline', ''): + tree.set('class', 'inline') + for item in self.xml: # call provided procedure to do the rendering item_xhtml = renderer(item) @@ -1294,7 +1294,7 @@ class CodeResponse(LoncapaResponse): # State associated with the queueing request queuestate = {'key': queuekey, - 'time': qtime,} + 'time': qtime, } cmap = CorrectMap() if error: diff --git a/common/lib/capa/capa/tests/__init__.py b/common/lib/capa/capa/tests/__init__.py index b06975f6ce..89cb5a5ee9 100644 --- a/common/lib/capa/capa/tests/__init__.py +++ b/common/lib/capa/capa/tests/__init__.py @@ -8,6 +8,7 @@ import xml.sax.saxutils as saxutils TEST_DIR = os.path.dirname(os.path.realpath(__file__)) + def tst_render_template(template, context): """ A test version of render to template. Renders to the repr of the context, completely ignoring @@ -25,7 +26,7 @@ test_system = Mock( user=Mock(), filestore=fs.osfs.OSFS(os.path.join(TEST_DIR, "test_files")), debug=True, - xqueue={'interface':None, 'callback_url':'/', 'default_queuename': 'testqueue', 'waittime': 10}, + xqueue={'interface': None, 'callback_url': '/', 'default_queuename': 'testqueue', 'waittime': 10}, node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"), - anonymous_student_id = 'student' + anonymous_student_id='student' ) diff --git a/common/lib/capa/capa/tests/test_customrender.py b/common/lib/capa/capa/tests/test_customrender.py index 7208ab2941..eece275b05 100644 --- a/common/lib/capa/capa/tests/test_customrender.py +++ b/common/lib/capa/capa/tests/test_customrender.py @@ -8,6 +8,7 @@ from capa import customrender # just a handy shortcut lookup_tag = customrender.registry.get_class_for_tag + def extract_context(xml): """ Given an xml element corresponding to the output of test_system.render_template, get back the @@ -15,9 +16,11 @@ def extract_context(xml): """ return eval(xml.text) + def quote_attr(s): return saxutils.quoteattr(s)[1:-1] # don't want the outer quotes + class HelperTest(unittest.TestCase): ''' Make sure that our helper function works! @@ -50,7 +53,7 @@ class SolutionRenderTest(unittest.TestCase): # our test_system "renders" templates to a div with the repr of the context xml = renderer.get_html() context = extract_context(xml) - self.assertEqual(context, {'id' : 'solution_12'}) + self.assertEqual(context, {'id': 'solution_12'}) class MathRenderTest(unittest.TestCase): @@ -65,12 +68,11 @@ class MathRenderTest(unittest.TestCase): renderer = lookup_tag('math')(test_system, element) self.assertEqual(renderer.mathstr, mathjax_out) - + def test_parsing(self): self.check_parse('$abc$', '[mathjaxinline]abc[/mathjaxinline]') self.check_parse('$abc', '$abc') self.check_parse(r'$\displaystyle 2+2$', '[mathjax] 2+2[/mathjax]') - + # NOTE: not testing get_html yet because I don't understand why it's doing what it's doing. - diff --git a/common/lib/capa/capa/tests/test_inputtypes.py b/common/lib/capa/capa/tests/test_inputtypes.py index 6c282baf95..4a5ea5c429 100644 --- a/common/lib/capa/capa/tests/test_inputtypes.py +++ b/common/lib/capa/capa/tests/test_inputtypes.py @@ -31,6 +31,7 @@ lookup_tag = inputtypes.registry.get_class_for_tag def quote_attr(s): return saxutils.quoteattr(s)[1:-1] # don't want the outer quotes + class OptionInputTest(unittest.TestCase): ''' Make sure option inputs work @@ -100,7 +101,7 @@ class ChoiceGroupTest(unittest.TestCase): 'input_type': expected_input_type, 'choices': [('foil1', 'This is foil One.'), ('foil2', 'This is foil Two.'), - ('foil3', 'This is foil Three.'),], + ('foil3', 'This is foil Three.'), ], 'name_array_suffix': expected_suffix, # what is this for?? } @@ -137,7 +138,7 @@ class JavascriptInputTest(unittest.TestCase): element = etree.fromstring(xml_str) - state = {'value': '3',} + state = {'value': '3', } the_input = lookup_tag('javascriptinput')(test_system, element, state) context = the_input._get_render_context() @@ -149,7 +150,7 @@ class JavascriptInputTest(unittest.TestCase): 'params': params, 'display_file': display_file, 'display_class': display_class, - 'problem_state': problem_state,} + 'problem_state': problem_state, } self.assertEqual(context, expected) @@ -165,7 +166,7 @@ class TextLineTest(unittest.TestCase): element = etree.fromstring(xml_str) - state = {'value': 'BumbleBee',} + state = {'value': 'BumbleBee', } the_input = lookup_tag('textline')(test_system, element, state) context = the_input._get_render_context() @@ -193,7 +194,7 @@ class TextLineTest(unittest.TestCase): element = etree.fromstring(xml_str) - state = {'value': 'BumbleBee',} + state = {'value': 'BumbleBee', } the_input = lookup_tag('textline')(test_system, element, state) context = the_input._get_render_context() @@ -231,7 +232,7 @@ class FileSubmissionTest(unittest.TestCase): state = {'value': 'BumbleBee.py', 'status': 'incomplete', - 'feedback' : {'message': '3'}, } + 'feedback': {'message': '3'}, } input_class = lookup_tag('filesubmission') the_input = input_class(test_system, element, state) @@ -275,7 +276,7 @@ class CodeInputTest(unittest.TestCase): state = {'value': 'print "good evening"', 'status': 'incomplete', - 'feedback' : {'message': '3'}, } + 'feedback': {'message': '3'}, } input_class = lookup_tag('codeinput') the_input = input_class(test_system, element, state) @@ -488,7 +489,7 @@ class ChemicalEquationTest(unittest.TestCase): element = etree.fromstring(xml_str) - state = {'value': 'H2OYeah',} + state = {'value': 'H2OYeah', } the_input = lookup_tag('chemicalequationinput')(test_system, element, state) context = the_input._get_render_context() diff --git a/common/lib/capa/capa/tests/test_responsetypes.py b/common/lib/capa/capa/tests/test_responsetypes.py index 9eecef3986..18da338b91 100644 --- a/common/lib/capa/capa/tests/test_responsetypes.py +++ b/common/lib/capa/capa/tests/test_responsetypes.py @@ -16,6 +16,7 @@ from capa.correctmap import CorrectMap from capa.util import convert_files_to_filenames from capa.xqueue_interface import dateformat + class MultiChoiceTest(unittest.TestCase): def test_MC_grade(self): multichoice_file = os.path.dirname(__file__) + "/test_files/multichoice.xml" @@ -295,16 +296,16 @@ class CodeResponseTest(unittest.TestCase): old_cmap = CorrectMap() for i, answer_id in enumerate(answer_ids): queuekey = 1000 + i - queuestate = CodeResponseTest.make_queuestate(1000+i, datetime.now()) + queuestate = CodeResponseTest.make_queuestate(1000 + i, datetime.now()) old_cmap.update(CorrectMap(answer_id=answer_ids[i], queuestate=queuestate)) # Message format common to external graders - grader_msg = 'MESSAGE' # Must be valid XML - correct_score_msg = json.dumps({'correct':True, 'score':1, 'msg': grader_msg}) - incorrect_score_msg = json.dumps({'correct':False, 'score':0, 'msg': grader_msg}) + grader_msg = 'MESSAGE' # Must be valid XML + correct_score_msg = json.dumps({'correct': True, 'score': 1, 'msg': grader_msg}) + incorrect_score_msg = json.dumps({'correct': False, 'score': 0, 'msg': grader_msg}) xserver_msgs = {'correct': correct_score_msg, - 'incorrect': incorrect_score_msg,} + 'incorrect': incorrect_score_msg, } # Incorrect queuekey, state should not be updated for correctness in ['correct', 'incorrect']: @@ -325,7 +326,7 @@ class CodeResponseTest(unittest.TestCase): new_cmap = CorrectMap() new_cmap.update(old_cmap) - npoints = 1 if correctness=='correct' else 0 + npoints = 1 if correctness == 'correct' else 0 new_cmap.set(answer_id=answer_id, npoints=npoints, correctness=correctness, msg=grader_msg, queuestate=None) test_lcp.update_score(xserver_msgs[correctness], queuekey=1000 + i) @@ -361,7 +362,7 @@ class CodeResponseTest(unittest.TestCase): for i, answer_id in enumerate(answer_ids): queuekey = 1000 + i latest_timestamp = datetime.now() - queuestate = CodeResponseTest.make_queuestate(1000+i, latest_timestamp) + queuestate = CodeResponseTest.make_queuestate(1000 + i, latest_timestamp) cmap.update(CorrectMap(answer_id=answer_id, queuestate=queuestate)) test_lcp.correct_map.update(cmap) @@ -412,6 +413,7 @@ class ChoiceResponseTest(unittest.TestCase): self.assertEquals(test_lcp.grade_answers(test_answers).get_correctness('1_3_1'), 'incorrect') self.assertEquals(test_lcp.grade_answers(test_answers).get_correctness('1_4_1'), 'correct') + class JavascriptResponseTest(unittest.TestCase): def test_jr_grade(self): @@ -424,4 +426,3 @@ class JavascriptResponseTest(unittest.TestCase): self.assertEquals(test_lcp.grade_answers(incorrect_answers).get_correctness('1_2_1'), 'incorrect') self.assertEquals(test_lcp.grade_answers(correct_answers).get_correctness('1_2_1'), 'correct') - diff --git a/common/lib/capa/capa/util.py b/common/lib/capa/capa/util.py index 0df58c216f..a0f25c4947 100644 --- a/common/lib/capa/capa/util.py +++ b/common/lib/capa/capa/util.py @@ -51,15 +51,17 @@ def convert_files_to_filenames(answers): new_answers = dict() for answer_id in answers.keys(): answer = answers[answer_id] - if is_list_of_files(answer): # Files are stored as a list, even if one file + if is_list_of_files(answer): # Files are stored as a list, even if one file new_answers[answer_id] = [f.name for f in answer] else: new_answers[answer_id] = answers[answer_id] return new_answers + def is_list_of_files(files): return isinstance(files, list) and all(is_file(f) for f in files) + def is_file(file_to_test): ''' Duck typing to check if 'file_to_test' is a File object @@ -79,11 +81,10 @@ def find_with_default(node, path, default): Returns: node.find(path).text if the find succeeds, default otherwise. - + """ v = node.find(path) if v is not None: return v.text else: return default - diff --git a/common/lib/capa/capa/xqueue_interface.py b/common/lib/capa/capa/xqueue_interface.py index 798867955b..8dbe2c84aa 100644 --- a/common/lib/capa/capa/xqueue_interface.py +++ b/common/lib/capa/capa/xqueue_interface.py @@ -10,6 +10,7 @@ import requests log = logging.getLogger('mitx.' + __name__) dateformat = '%Y%m%d%H%M%S' + def make_hashkey(seed): ''' Generate a string key by hashing @@ -29,9 +30,9 @@ def make_xheader(lms_callback_url, lms_key, queue_name): 'queue_name': designate a specific queue within xqueue server, e.g. 'MITx-6.00x' (string) } """ - return json.dumps({ 'lms_callback_url': lms_callback_url, + return json.dumps({'lms_callback_url': lms_callback_url, 'lms_key': lms_key, - 'queue_name': queue_name }) + 'queue_name': queue_name}) def parse_xreply(xreply): @@ -96,18 +97,18 @@ class XQueueInterface(object): def _login(self): - payload = { 'username': self.auth['username'], - 'password': self.auth['password'] } + payload = {'username': self.auth['username'], + 'password': self.auth['password']} return self._http_post(self.url + '/xqueue/login/', payload) def _send_to_queue(self, header, body, files_to_upload): payload = {'xqueue_header': header, - 'xqueue_body' : body} + 'xqueue_body': body} files = {} if files_to_upload is not None: for f in files_to_upload: - files.update({ f.name: f }) + files.update({f.name: f}) return self._http_post(self.url + '/xqueue/submit/', payload, files=files) diff --git a/common/lib/supertrace.py b/common/lib/supertrace.py index e17cd7a8ba..83dfa12031 100644 --- a/common/lib/supertrace.py +++ b/common/lib/supertrace.py @@ -3,7 +3,8 @@ A handy util to print a django-debug-screen-like stack trace with values of local variables. """ -import sys, traceback +import sys +import traceback from django.utils.encoding import smart_unicode @@ -48,5 +49,3 @@ def supertrace(max_len=160): print s except: print "" - - diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py index 817af9c10d..3bc8bc5143 100644 --- a/common/lib/xmodule/setup.py +++ b/common/lib/xmodule/setup.py @@ -30,7 +30,7 @@ setup( "peergrading = xmodule.peer_grading_module:PeerGradingDescriptor", "problem = xmodule.capa_module:CapaDescriptor", "problemset = xmodule.seq_module:SequenceDescriptor", - "randomize = xmodule.randomize_module:RandomizeDescriptor", + "randomize = xmodule.randomize_module:RandomizeDescriptor", "section = xmodule.backcompat_module:SemanticSectionDescriptor", "sequential = xmodule.seq_module:SequenceDescriptor", "slides = xmodule.backcompat_module:TranslateCustomTagDescriptor", diff --git a/common/lib/xmodule/xmodule/abtest_module.py b/common/lib/xmodule/xmodule/abtest_module.py index 12456bc7d7..537d864127 100644 --- a/common/lib/xmodule/xmodule/abtest_module.py +++ b/common/lib/xmodule/xmodule/abtest_module.py @@ -51,7 +51,7 @@ class ABTestModule(XModule): def get_shared_state(self): return json.dumps({'group': self.group}) - + def get_child_descriptors(self): active_locations = set(self.definition['data']['group_content'][self.group]) return [desc for desc in self.descriptor.get_children() if desc.location.url() in active_locations] @@ -171,7 +171,7 @@ class ABTestDescriptor(RawDescriptor, XmlDescriptor): group_elem.append(etree.fromstring(child.export_to_xml(resource_fs))) return xml_object - - + + def has_dynamic_children(self): return True diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index d3c8786f66..d806ec7913 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -29,6 +29,7 @@ TIMEDELTA_REGEX = re.compile(r'^((?P\d+?) day(?:s?))?(\s)?((?P\d+?) # Generated this many different variants of problems with rerandomize=per_student NUM_RANDOMIZATION_BINS = 20 + def randomization_bin(seed, problem_id): """ Pick a randomization bin for the problem given the user's seed and a problem id. @@ -43,6 +44,7 @@ def randomization_bin(seed, problem_id): # get the first few digits of the hash, convert to an int, then mod. return int(h.hexdigest()[:7], 16) % NUM_RANDOMIZATION_BINS + def only_one(lst, default="", process=lambda x: x): """ If lst is empty, returns default @@ -283,7 +285,7 @@ class CapaModule(XModule): # Next, generate a fresh LoncapaProblem self.lcp = LoncapaProblem(self.definition['data'], self.location.html_id(), - state=None, # Tabula rasa + state=None, # Tabula rasa seed=self.seed, system=self.system) # Prepend a scary warning to the student @@ -302,7 +304,7 @@ class CapaModule(XModule): html = warning try: html += self.lcp.get_html() - except Exception, err: # Couldn't do it. Give up + except Exception, err: # Couldn't do it. Give up log.exception(err) raise @@ -315,7 +317,7 @@ class CapaModule(XModule): # check button is context-specific. # Put a "Check" button if unlimited attempts or still some left - if self.max_attempts is None or self.attempts < self.max_attempts-1: + if self.max_attempts is None or self.attempts < self.max_attempts - 1: check_button = "Check" else: # Will be final check so let user know that @@ -561,9 +563,9 @@ class CapaModule(XModule): current_time = datetime.datetime.now() prev_submit_time = self.lcp.get_recentmost_queuetime() waittime_between_requests = self.system.xqueue['waittime'] - if (current_time-prev_submit_time).total_seconds() < waittime_between_requests: + if (current_time - prev_submit_time).total_seconds() < waittime_between_requests: msg = 'You must wait at least %d seconds between submissions' % waittime_between_requests - return {'success': msg, 'html': ''} # Prompts a modal dialog in ajax callback + return {'success': msg, 'html': ''} # Prompts a modal dialog in ajax callback try: old_state = self.lcp.get_state() @@ -596,7 +598,7 @@ class CapaModule(XModule): event_info['attempts'] = self.attempts self.system.track_function('save_problem_check', event_info) - if hasattr(self.system,'psychometrics_handler'): # update PsychometricsData using callback + if hasattr(self.system, 'psychometrics_handler'): # update PsychometricsData using callback self.system.psychometrics_handler(self.get_instance_state()) # render problem into HTML @@ -707,7 +709,7 @@ class CapaDescriptor(RawDescriptor): @property def editable_metadata_fields(self): """Remove metadata from the editable fields since it has its own editor""" - subset = super(CapaDescriptor,self).editable_metadata_fields + subset = super(CapaDescriptor, self).editable_metadata_fields if 'markdown' in subset: subset.remove('markdown') return subset diff --git a/common/lib/xmodule/xmodule/combined_open_ended_module.py b/common/lib/xmodule/xmodule/combined_open_ended_module.py index 14a59c9004..112a7a68f8 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_module.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_module.py @@ -50,14 +50,16 @@ ACCEPT_FILE_UPLOAD = False TRUE_DICT = ["True", True, "TRUE", "true"] HUMAN_TASK_TYPE = { - 'selfassessment' : "Self Assessment", - 'openended' : "External Grader", + 'selfassessment': "Self Assessment", + 'openended': "External Grader", } + class IncorrectMaxScoreError(Exception): def __init__(self, msg): self.msg = msg + class CombinedOpenEndedModule(XModule): """ This is a module that encapsulates all open ended grading (self assessment, peer assessment, etc). @@ -700,4 +702,4 @@ class CombinedOpenEndedDescriptor(XmlDescriptor, EditingDescriptor): for child in ['task']: add_child(child) - return elt \ No newline at end of file + return elt diff --git a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py index 6d4a3eebdf..9a213299cd 100644 --- a/common/lib/xmodule/xmodule/combined_open_ended_rubric.py +++ b/common/lib/xmodule/xmodule/combined_open_ended_rubric.py @@ -1,12 +1,14 @@ import logging from lxml import etree -log=logging.getLogger(__name__) +log = logging.getLogger(__name__) + class RubricParsingError(Exception): def __init__(self, msg): self.msg = msg + class CombinedOpenEndedRubric(object): def __init__ (self, system, view_only = False): @@ -27,8 +29,8 @@ class CombinedOpenEndedRubric(object): success = False try: rubric_categories = self.extract_categories(rubric_xml) - html = self.system.render_template('open_ended_rubric.html', - {'categories' : rubric_categories, + html = self.system.render_template('open_ended_rubric.html', + {'categories': rubric_categories, 'has_score': self.has_score, 'view_only': self.view_only}) success = True @@ -60,8 +62,8 @@ class CombinedOpenEndedRubric(object): options: [{text: "Option 1 Name", points: 0}, {text:"Option 2 Name", points: 5}] }, { category: "Category 2 Name", - options: [{text: "Option 1 Name", points: 0}, - {text: "Option 2 Name", points: 1}, + options: [{text: "Option 1 Name", points: 0}, + {text: "Option 2 Name", points: 1}, {text: "Option 3 Name", points: 2]}] ''' @@ -77,7 +79,7 @@ class CombinedOpenEndedRubric(object): def extract_category(self, category): - ''' + ''' construct an individual category {category: "Category 1 Name", options: [{text: "Option 1 text", points: 1}, @@ -110,7 +112,7 @@ class CombinedOpenEndedRubric(object): autonumbering = True # parse options for option in optionsxml: - if option.tag != 'option': + if option.tag != 'option': raise RubricParsingError("[extract_category]: expected option tag, got {0} instead".format(option.tag)) else: pointstr = option.get("points") @@ -127,7 +129,7 @@ class CombinedOpenEndedRubric(object): cur_points = cur_points + 1 else: raise Exception("[extract_category]: missing points attribute. Cannot continue to auto-create points values after a points value is explicitly defined.") - + selected = score == points optiontext = option.text options.append({'text': option.text, 'points': points, 'selected': selected}) diff --git a/common/lib/xmodule/xmodule/conditional_module.py b/common/lib/xmodule/xmodule/conditional_module.py index e20681e614..bcdf0f4738 100644 --- a/common/lib/xmodule/xmodule/conditional_module.py +++ b/common/lib/xmodule/xmodule/conditional_module.py @@ -9,12 +9,13 @@ from pkg_resources import resource_string log = logging.getLogger('mitx.' + __name__) + class ConditionalModule(XModule): ''' Blocks child module from showing unless certain conditions are met. Example: - + @@ -37,13 +38,13 @@ class ConditionalModule(XModule): def __init__(self, system, location, definition, descriptor, instance_state=None, shared_state=None, **kwargs): """ In addition to the normal XModule init, provide: - + self.condition = string describing condition required """ XModule.__init__(self, system, location, definition, descriptor, instance_state, shared_state, **kwargs) self.contents = None - self.condition = self.metadata.get('condition','') + self.condition = self.metadata.get('condition', '') #log.debug('conditional module required=%s' % self.required_modules_list) def _get_required_modules(self): @@ -56,7 +57,7 @@ class ConditionalModule(XModule): def is_condition_satisfied(self): self._get_required_modules() - if self.condition=='require_completed': + if self.condition == 'require_completed': # all required modules must be completed, as determined by # the modules .is_completed() method for module in self.required_modules: @@ -70,7 +71,7 @@ class ConditionalModule(XModule): else: log.debug('conditional module: %s IS completed' % module) return True - elif self.condition=='require_attempted': + elif self.condition == 'require_attempted': # all required modules must be attempted, as determined by # the modules .is_attempted() method for module in self.required_modules: @@ -111,9 +112,10 @@ class ConditionalModule(XModule): # for now, just deal with one child html = self.contents[0] - + return json.dumps({'html': html}) + class ConditionalDescriptor(SequenceDescriptor): module_class = ConditionalModule @@ -125,7 +127,7 @@ class ConditionalDescriptor(SequenceDescriptor): def __init__(self, *args, **kwargs): super(ConditionalDescriptor, self).__init__(*args, **kwargs) - required_module_list = [tuple(x.split('/',1)) for x in self.metadata.get('required','').split('&')] + required_module_list = [tuple(x.split('/', 1)) for x in self.metadata.get('required', '').split('&')] self.required_module_locations = [] for (tag, name) in required_module_list: loc = self.location.dict() @@ -133,9 +135,8 @@ class ConditionalDescriptor(SequenceDescriptor): loc['name'] = name self.required_module_locations.append(Location(loc)) log.debug('ConditionalDescriptor required_module_locations=%s' % self.required_module_locations) - + def get_required_module_descriptors(self): """Returns a list of XModuleDescritpor instances upon which this module depends, but are not children of this module""" return [self.system.load_item(loc) for loc in self.required_module_locations] - diff --git a/common/lib/xmodule/xmodule/contentstore/content.py b/common/lib/xmodule/xmodule/contentstore/content.py index 5b10acc0ef..be33401bc8 100644 --- a/common/lib/xmodule/xmodule/contentstore/content.py +++ b/common/lib/xmodule/xmodule/contentstore/content.py @@ -11,15 +11,16 @@ from xmodule.modulestore import Location from .django import contentstore from PIL import Image + class StaticContent(object): def __init__(self, loc, name, content_type, data, last_modified_at=None, thumbnail_location=None, import_path=None): self.location = loc - self.name = name #a display string which can be edited, and thus not part of the location which needs to be fixed + self.name = name # a display string which can be edited, and thus not part of the location which needs to be fixed self.content_type = content_type self.data = data self.last_modified_at = last_modified_at self.thumbnail_location = Location(thumbnail_location) if thumbnail_location is not None else None - # optional information about where this file was imported from. This is needed to support import/export + # optional information about where this file was imported from. This is needed to support import/export # cycles self.import_path = import_path @@ -29,7 +30,7 @@ class StaticContent(object): @staticmethod def generate_thumbnail_name(original_name): - return ('{0}'+XASSET_THUMBNAIL_TAIL_NAME).format(os.path.splitext(original_name)[0]) + return ('{0}' + XASSET_THUMBNAIL_TAIL_NAME).format(os.path.splitext(original_name)[0]) @staticmethod def compute_location(org, course, name, revision=None, is_thumbnail=False): @@ -41,7 +42,7 @@ class StaticContent(object): def get_url_path(self): return StaticContent.get_url_path_from_location(self.location) - + @staticmethod def get_url_path_from_location(location): if location is not None: @@ -56,15 +57,15 @@ class StaticContent(object): @staticmethod def get_id_from_location(location): - return { 'tag':location.tag, 'org' : location.org, 'course' : location.course, - 'category' : location.category, 'name' : location.name, - 'revision' : location.revision} + return {'tag': location.tag, 'org': location.org, 'course': location.course, + 'category': location.category, 'name': location.name, + 'revision': location.revision} @staticmethod def get_location_from_path(path): # remove leading / character if it is there one if path.startswith('/'): path = path[1:] - + return Location(path.split('/')) @staticmethod @@ -77,7 +78,7 @@ class StaticContent(object): return StaticContent.get_url_path_from_location(loc) - + class ContentStore(object): ''' @@ -95,14 +96,14 @@ class ContentStore(object): [ - {u'displayname': u'profile.jpg', u'chunkSize': 262144, u'length': 85374, - u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 183000), u'contentType': u'image/jpeg', - u'_id': {u'category': u'asset', u'name': u'profile.jpg', u'course': u'6.002x', u'tag': u'c4x', - u'org': u'MITx', u'revision': None}, u'md5': u'36dc53519d4b735eb6beba51cd686a0e'}, + {u'displayname': u'profile.jpg', u'chunkSize': 262144, u'length': 85374, + u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 183000), u'contentType': u'image/jpeg', + u'_id': {u'category': u'asset', u'name': u'profile.jpg', u'course': u'6.002x', u'tag': u'c4x', + u'org': u'MITx', u'revision': None}, u'md5': u'36dc53519d4b735eb6beba51cd686a0e'}, - {u'displayname': u'profile.thumbnail.jpg', u'chunkSize': 262144, u'length': 4073, - u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 196000), u'contentType': u'image/jpeg', - u'_id': {u'category': u'asset', u'name': u'profile.thumbnail.jpg', u'course': u'6.002x', u'tag': u'c4x', + {u'displayname': u'profile.thumbnail.jpg', u'chunkSize': 262144, u'length': 4073, + u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 196000), u'contentType': u'image/jpeg', + u'_id': {u'category': u'asset', u'name': u'profile.thumbnail.jpg', u'course': u'6.002x', u'tag': u'c4x', u'org': u'MITx', u'revision': None}, u'md5': u'ff1532598830e3feac91c2449eaa60d6'}, .... @@ -117,7 +118,7 @@ class ContentStore(object): thumbnail_name = StaticContent.generate_thumbnail_name(content.location.name) thumbnail_file_location = StaticContent.compute_location(content.location.org, content.location.course, - thumbnail_name, is_thumbnail = True) + thumbnail_name, is_thumbnail=True) # if we're uploading an image, then let's generate a thumbnail so that we can # serve it up when needed without having to rescale on the fly @@ -129,7 +130,7 @@ class ContentStore(object): # @todo: move the thumbnail size to a configuration setting?!? im = Image.open(StringIO.StringIO(content.data)) - # I've seen some exceptions from the PIL library when trying to save palletted + # I've seen some exceptions from the PIL library when trying to save palletted # PNG files to JPEG. Per the google-universe, they suggest converting to RGB first. im = im.convert('RGB') size = 128, 128 @@ -139,7 +140,7 @@ class ContentStore(object): thumbnail_file.seek(0) # store this thumbnail as any other piece of content - thumbnail_content = StaticContent(thumbnail_file_location, thumbnail_name, + thumbnail_content = StaticContent(thumbnail_file_location, thumbnail_name, 'image/jpeg', thumbnail_file) contentstore().save(thumbnail_content) @@ -149,7 +150,3 @@ class ContentStore(object): logging.exception("Failed to generate thumbnail for {0}. Exception: {1}".format(content.location, str(e))) return thumbnail_content, thumbnail_file_location - - - - diff --git a/common/lib/xmodule/xmodule/contentstore/django.py b/common/lib/xmodule/xmodule/contentstore/django.py index d8b3084135..ec0397a348 100644 --- a/common/lib/xmodule/xmodule/contentstore/django.py +++ b/common/lib/xmodule/xmodule/contentstore/django.py @@ -6,6 +6,7 @@ from django.conf import settings _CONTENTSTORE = None + def load_function(path): """ Load a function by name. diff --git a/common/lib/xmodule/xmodule/contentstore/mongo.py b/common/lib/xmodule/xmodule/contentstore/mongo.py index 01f189a9e4..68cc6d73d3 100644 --- a/common/lib/xmodule/xmodule/contentstore/mongo.py +++ b/common/lib/xmodule/xmodule/contentstore/mongo.py @@ -17,14 +17,14 @@ import os class MongoContentStore(ContentStore): def __init__(self, host, db, port=27017, user=None, password=None, **kwargs): - logging.debug( 'Using MongoDB for static content serving at host={0} db={1}'.format(host,db)) + logging.debug('Using MongoDB for static content serving at host={0} db={1}'.format(host, db)) _db = Connection(host=host, port=port, **kwargs)[db] if user is not None and password is not None: _db.authenticate(user, password) self.fs = gridfs.GridFS(_db) - self.fs_files = _db["fs.files"] # the underlying collection GridFS uses + self.fs_files = _db["fs.files"] # the underlying collection GridFS uses def save(self, content): @@ -33,24 +33,24 @@ class MongoContentStore(ContentStore): # Seems like with the GridFS we can't update existing ID's we have to do a delete/add pair self.delete(id) - with self.fs.new_file(_id = id, filename=content.get_url_path(), content_type=content.content_type, + with self.fs.new_file(_id=id, filename=content.get_url_path(), content_type=content.content_type, displayname=content.name, thumbnail_location=content.thumbnail_location, import_path=content.import_path) as fp: fp.write(content.data) - + return content - + def delete(self, id): - if self.fs.exists({"_id" : id}): + if self.fs.exists({"_id": id}): self.fs.delete(id) def find(self, location): id = StaticContent.get_id_from_location(location) try: with self.fs.get(id) as fp: - return StaticContent(location, fp.displayname, fp.content_type, fp.read(), - fp.uploadDate, thumbnail_location = fp.thumbnail_location if hasattr(fp, 'thumbnail_location') else None, - import_path = fp.import_path if hasattr(fp, 'import_path') else None) + return StaticContent(location, fp.displayname, fp.content_type, fp.read(), + fp.uploadDate, thumbnail_location=fp.thumbnail_location if hasattr(fp, 'thumbnail_location') else None, + import_path=fp.import_path if hasattr(fp, 'import_path') else None) except NoFile: raise NotFoundError() @@ -76,25 +76,25 @@ class MongoContentStore(ContentStore): self.export(asset_location, output_directory) def get_all_content_thumbnails_for_course(self, location): - return self._get_all_content_for_course(location, get_thumbnails = True) + return self._get_all_content_for_course(location, get_thumbnails=True) def get_all_content_for_course(self, location): - return self._get_all_content_for_course(location, get_thumbnails = False) + return self._get_all_content_for_course(location, get_thumbnails=False) - def _get_all_content_for_course(self, location, get_thumbnails = False): + def _get_all_content_for_course(self, location, get_thumbnails=False): ''' Returns a list of all static assets for a course. The return format is a list of dictionary elements. Example: [ - {u'displayname': u'profile.jpg', u'chunkSize': 262144, u'length': 85374, - u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 183000), u'contentType': u'image/jpeg', - u'_id': {u'category': u'asset', u'name': u'profile.jpg', u'course': u'6.002x', u'tag': u'c4x', - u'org': u'MITx', u'revision': None}, u'md5': u'36dc53519d4b735eb6beba51cd686a0e'}, + {u'displayname': u'profile.jpg', u'chunkSize': 262144, u'length': 85374, + u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 183000), u'contentType': u'image/jpeg', + u'_id': {u'category': u'asset', u'name': u'profile.jpg', u'course': u'6.002x', u'tag': u'c4x', + u'org': u'MITx', u'revision': None}, u'md5': u'36dc53519d4b735eb6beba51cd686a0e'}, - {u'displayname': u'profile.thumbnail.jpg', u'chunkSize': 262144, u'length': 4073, - u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 196000), u'contentType': u'image/jpeg', - u'_id': {u'category': u'asset', u'name': u'profile.thumbnail.jpg', u'course': u'6.002x', u'tag': u'c4x', + {u'displayname': u'profile.thumbnail.jpg', u'chunkSize': 262144, u'length': 4073, + u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 196000), u'contentType': u'image/jpeg', + u'_id': {u'category': u'asset', u'name': u'profile.thumbnail.jpg', u'course': u'6.002x', u'tag': u'c4x', u'org': u'MITx', u'revision': None}, u'md5': u'ff1532598830e3feac91c2449eaa60d6'}, .... @@ -102,10 +102,7 @@ class MongoContentStore(ContentStore): ] ''' course_filter = Location(XASSET_LOCATION_TAG, category="asset" if not get_thumbnails else "thumbnail", - course=location.course,org=location.org) + course=location.course, org=location.org) # 'borrow' the function 'location_to_query' from the Mongo modulestore implementation items = self.fs_files.find(location_to_query(course_filter)) return list(items) - - - diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 6e3e2cfa39..750c8615a0 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -147,37 +147,37 @@ class CourseDescriptor(SequenceDescriptor): """ Return a dict which is a copy of the default grading policy """ - default = {"GRADER" : [ + default = {"GRADER": [ { - "type" : "Homework", - "min_count" : 12, - "drop_count" : 2, - "short_label" : "HW", - "weight" : 0.15 + "type": "Homework", + "min_count": 12, + "drop_count": 2, + "short_label": "HW", + "weight": 0.15 }, { - "type" : "Lab", - "min_count" : 12, - "drop_count" : 2, - "weight" : 0.15 + "type": "Lab", + "min_count": 12, + "drop_count": 2, + "weight": 0.15 }, { - "type" : "Midterm Exam", - "short_label" : "Midterm", - "min_count" : 1, - "drop_count" : 0, - "weight" : 0.3 + "type": "Midterm Exam", + "short_label": "Midterm", + "min_count": 1, + "drop_count": 0, + "weight": 0.3 }, { - "type" : "Final Exam", - "short_label" : "Final", - "min_count" : 1, - "drop_count" : 0, - "weight" : 0.4 + "type": "Final Exam", + "short_label": "Final", + "min_count": 1, + "drop_count": 0, + "weight": 0.4 } ], - "GRADE_CUTOFFS" : { - "Pass" : 0.5 + "GRADE_CUTOFFS": { + "Pass": 0.5 }} return copy.deepcopy(default) @@ -230,8 +230,8 @@ class CourseDescriptor(SequenceDescriptor): # bleh, have to parse the XML here to just pull out the url_name attribute # I don't think it's stored anywhere in the instance. - course_file = StringIO(xml_data.encode('ascii','ignore')) - xml_obj = etree.parse(course_file,parser=edx_xml_parser).getroot() + course_file = StringIO(xml_data.encode('ascii', 'ignore')) + xml_obj = etree.parse(course_file, parser=edx_xml_parser).getroot() policy_dir = None url_name = xml_obj.get('url_name', xml_obj.get('slug')) @@ -329,7 +329,7 @@ class CourseDescriptor(SequenceDescriptor): def raw_grader(self, value): # NOTE WELL: this change will not update the processed graders. If we need that, this needs to call grader_from_conf self._grading_policy['RAW_GRADER'] = value - self.definition['data'].setdefault('grading_policy',{})['GRADER'] = value + self.definition['data'].setdefault('grading_policy', {})['GRADER'] = value @property def grade_cutoffs(self): @@ -338,7 +338,7 @@ class CourseDescriptor(SequenceDescriptor): @grade_cutoffs.setter def grade_cutoffs(self, value): self._grading_policy['GRADE_CUTOFFS'] = value - self.definition['data'].setdefault('grading_policy',{})['GRADE_CUTOFFS'] = value + self.definition['data'].setdefault('grading_policy', {})['GRADE_CUTOFFS'] = value @property @@ -377,7 +377,7 @@ class CourseDescriptor(SequenceDescriptor): Return list of topic ids defined in course policy. """ topics = self.metadata.get("discussion_topics", {}) - return [d["id"] for d in topics.values()] + return [d["id"] for d in topics.values()] @property @@ -436,10 +436,10 @@ class CourseDescriptor(SequenceDescriptor): scale = 300.0 # about a year if announcement: days = (now - announcement).days - score = -exp(-days/scale) + score = -exp(-days / scale) else: days = (now - start).days - score = exp(days/scale) + score = exp(days / scale) return score def _sorting_dates(self): @@ -501,16 +501,16 @@ class CourseDescriptor(SequenceDescriptor): xmoduledescriptors.append(s) # The xmoduledescriptors included here are only the ones that have scores. - section_description = { 'section_descriptor' : s, 'xmoduledescriptors' : filter(lambda child: child.has_score, xmoduledescriptors) } + section_description = {'section_descriptor': s, 'xmoduledescriptors': filter(lambda child: child.has_score, xmoduledescriptors)} section_format = s.metadata.get('format', "") - graded_sections[ section_format ] = graded_sections.get( section_format, [] ) + [section_description] + graded_sections[section_format] = graded_sections.get(section_format, []) + [section_description] all_descriptors.extend(xmoduledescriptors) all_descriptors.append(s) - return { 'graded_sections' : graded_sections, - 'all_descriptors' : all_descriptors,} + return {'graded_sections': graded_sections, + 'all_descriptors': all_descriptors, } @staticmethod @@ -636,7 +636,7 @@ class CourseDescriptor(SequenceDescriptor): # *end* of the same day, not the same time. It's going to be used as the # end of the exam overall, so we don't want the exam to disappear too soon. # It's also used optionally as the registration end date, so time matters there too. - self.last_eligible_appointment_date = self._try_parse_time('Last_Eligible_Appointment_Date') # or self.first_eligible_appointment_date + self.last_eligible_appointment_date = self._try_parse_time('Last_Eligible_Appointment_Date') # or self.first_eligible_appointment_date if self.last_eligible_appointment_date is None: raise ValueError("Last appointment date must be specified") self.registration_start_date = self._try_parse_time('Registration_Start_Date') or time.gmtime(0) @@ -715,4 +715,3 @@ class CourseDescriptor(SequenceDescriptor): @property def org(self): return self.location.org - diff --git a/common/lib/xmodule/xmodule/discussion_module.py b/common/lib/xmodule/xmodule/discussion_module.py index 57d7780d95..6ddfcbe6c0 100644 --- a/common/lib/xmodule/xmodule/discussion_module.py +++ b/common/lib/xmodule/xmodule/discussion_module.py @@ -6,6 +6,7 @@ from xmodule.raw_module import RawDescriptor import json + class DiscussionModule(XModule): js = {'coffee': [resource_string(__name__, 'js/src/time.coffee'), @@ -30,6 +31,7 @@ class DiscussionModule(XModule): self.title = xml_data.attrib['for'] self.discussion_category = xml_data.attrib['discussion_category'] + class DiscussionDescriptor(RawDescriptor): module_class = DiscussionModule template_dir_name = "discussion" diff --git a/common/lib/xmodule/xmodule/errortracker.py b/common/lib/xmodule/xmodule/errortracker.py index 6accc8b8a7..80e6d288f8 100644 --- a/common/lib/xmodule/xmodule/errortracker.py +++ b/common/lib/xmodule/xmodule/errortracker.py @@ -8,12 +8,14 @@ log = logging.getLogger(__name__) ErrorLog = namedtuple('ErrorLog', 'tracker errors') + def exc_info_to_str(exc_info): """Given some exception info, convert it into a string using the traceback.format_exception() function. """ return ''.join(traceback.format_exception(*exc_info)) + def in_exception_handler(): '''Is there an active exception?''' return sys.exc_info() != (None, None, None) @@ -44,6 +46,7 @@ def make_error_tracker(): return ErrorLog(error_tracker, errors) + def null_error_tracker(msg): '''A dummy error tracker that just ignores the messages''' pass diff --git a/common/lib/xmodule/xmodule/graders.py b/common/lib/xmodule/xmodule/graders.py index 3e6d61eb00..35318f4f1e 100644 --- a/common/lib/xmodule/xmodule/graders.py +++ b/common/lib/xmodule/xmodule/graders.py @@ -49,6 +49,7 @@ def invalid_args(func, argdict): if keywords: return set() # All accepted return set(argdict) - set(args) + def grader_from_conf(conf): """ This creates a CourseGrader from a configuration (such as in course_settings.py). @@ -80,7 +81,7 @@ def grader_from_conf(conf): subgrader_class = SingleSectionGrader else: raise ValueError("Configuration has no appropriate grader class.") - + bad_args = invalid_args(subgrader_class.__init__, subgraderconf) # See note above concerning 'name'. if bad_args.issuperset({name}): @@ -90,7 +91,7 @@ def grader_from_conf(conf): log.warning("Invalid arguments for a subgrader: %s", bad_args) for key in bad_args: del subgraderconf[key] - + subgrader = subgrader_class(**subgraderconf) subgraders.append((subgrader, subgrader.category, weight)) @@ -210,13 +211,13 @@ class SingleSectionGrader(CourseGrader): break if foundScore or generate_random_scores: - if generate_random_scores: # for debugging! - earned = random.randint(2,15) + if generate_random_scores: # for debugging! + earned = random.randint(2, 15) possible = random.randint(earned, 15) - else: # We found the score + else: # We found the score earned = foundScore.earned possible = foundScore.possible - + percent = earned / float(possible) detail = "{name} - {percent:.0%} ({earned:.3n}/{possible:.3n})".format(name=self.name, percent=percent, @@ -245,7 +246,7 @@ class AssignmentFormatGrader(CourseGrader): min_count defines how many assignments are expected throughout the course. Placeholder scores (of 0) will be inserted if the number of matching sections in the course is < min_count. If there number of matching sections in the course is > min_count, min_count will be ignored. - + show_only_average is to suppress the display of each assignment in this grader and instead only show the total score of this grader in the breakdown. @@ -257,7 +258,7 @@ class AssignmentFormatGrader(CourseGrader): short_label is similar to section_type, but shorter. For example, for Homework it would be "HW". - + starting_index is the first number that will appear. For example, starting_index=3 and min_count = 2 would produce the labels "Assignment 3", "Assignment 4" @@ -296,16 +297,16 @@ class AssignmentFormatGrader(CourseGrader): breakdown = [] for i in range(max(self.min_count, len(scores))): if i < len(scores) or generate_random_scores: - if generate_random_scores: # for debugging! - earned = random.randint(2,15) - possible = random.randint(earned, 15) + if generate_random_scores: # for debugging! + earned = random.randint(2, 15) + possible = random.randint(earned, 15) section_name = "Generated" - + else: earned = scores[i].earned possible = scores[i].possible section_name = scores[i].section - + percentage = earned / float(possible) summary = "{section_type} {index} - {name} - {percent:.0%} ({earned:.3n}/{possible:.3n})".format(index=i + self.starting_index, section_type=self.section_type, @@ -318,7 +319,7 @@ class AssignmentFormatGrader(CourseGrader): summary = "{section_type} {index} Unreleased - 0% (?/?)".format(index=i + self.starting_index, section_type=self.section_type) short_label = "{short_label} {index:02d}".format(index=i + self.starting_index, short_label=self.short_label) - + breakdown.append({'percent': percentage, 'label': short_label, 'detail': summary, 'category': self.category}) total_percent, dropped_indices = totalWithDrops(breakdown, self.drop_count) @@ -328,13 +329,13 @@ class AssignmentFormatGrader(CourseGrader): total_detail = "{section_type} Average = {percent:.0%}".format(percent=total_percent, section_type=self.section_type) total_label = "{short_label} Avg".format(short_label=self.short_label) - + if self.show_only_average: breakdown = [] - + if not self.hide_average: breakdown.append({'percent': total_percent, 'label': total_label, 'detail': total_detail, 'category': self.category, 'prominent': True}) - + return {'percent': total_percent, 'section_breakdown': breakdown, #No grade_breakdown here diff --git a/common/lib/xmodule/xmodule/grading_service_module.py b/common/lib/xmodule/xmodule/grading_service_module.py index 7c18731f53..a442f39f34 100644 --- a/common/lib/xmodule/xmodule/grading_service_module.py +++ b/common/lib/xmodule/xmodule/grading_service_module.py @@ -10,9 +10,11 @@ from lxml import etree log = logging.getLogger(__name__) + class GradingServiceError(Exception): pass + class GradingService(object): """ Interface to staff grading backend. @@ -35,7 +37,7 @@ class GradingService(object): """ response = self.session.post(self.login_url, {'username': self.username, - 'password': self.password,}) + 'password': self.password, }) response.raise_for_status() @@ -124,4 +126,4 @@ class GradingService(object): except ValueError: log.exception("Error parsing response: {0}".format(response)) return {'success': False, - 'error': "Error displaying submission"} \ No newline at end of file + 'error': "Error displaying submission"} diff --git a/common/lib/xmodule/xmodule/html_checker.py b/common/lib/xmodule/xmodule/html_checker.py index 5e6b417d28..b30e5163a2 100644 --- a/common/lib/xmodule/xmodule/html_checker.py +++ b/common/lib/xmodule/xmodule/html_checker.py @@ -1,5 +1,6 @@ from lxml import etree + def check_html(html): ''' Check whether the passed in html string can be parsed by lxml. diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 612e78ce35..af1ce0ad80 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -133,7 +133,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor): # TODO (ichuang): remove this after migration # for Fall 2012 LMS migration: keep filename (and unmangled filename) - definition['filename'] = [ filepath, filename ] + definition['filename'] = [filepath, filename] return definition @@ -180,6 +180,7 @@ class AboutDescriptor(HtmlDescriptor): """ template_dir_name = "about" + class StaticTabDescriptor(HtmlDescriptor): """ These pieces of course content are treated as HtmlModules but we need to overload where the templates are located @@ -187,6 +188,7 @@ class StaticTabDescriptor(HtmlDescriptor): """ template_dir_name = "statictab" + class CourseInfoDescriptor(HtmlDescriptor): """ These pieces of course content are treated as HtmlModules but we need to overload where the templates are located diff --git a/common/lib/xmodule/xmodule/mako_module.py b/common/lib/xmodule/xmodule/mako_module.py index f5f2fae23b..dab5d5e85b 100644 --- a/common/lib/xmodule/xmodule/mako_module.py +++ b/common/lib/xmodule/xmodule/mako_module.py @@ -34,7 +34,7 @@ class MakoModuleDescriptor(XModuleDescriptor): """ return {'module': self, 'metadata': self.metadata, - 'editable_metadata_fields' : self.editable_metadata_fields + 'editable_metadata_fields': self.editable_metadata_fields } def get_html(self): @@ -46,4 +46,3 @@ class MakoModuleDescriptor(XModuleDescriptor): def editable_metadata_fields(self): subset = [name for name in self.metadata.keys() if name not in self.system_metadata_fields] return subset - diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py index 38915adcb4..a9df6c3504 100644 --- a/common/lib/xmodule/xmodule/modulestore/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/__init__.py @@ -365,7 +365,7 @@ class ModuleStore(object): raise NotImplementedError def get_parent_locations(self, location, course_id): - '''Find all locations that are the parents of this location in this + '''Find all locations that are the parents of this location in this course. Needed for path_to_location(). returns an iterable of things that can be passed to Location. diff --git a/common/lib/xmodule/xmodule/modulestore/draft.py b/common/lib/xmodule/xmodule/modulestore/draft.py index ef2a848cac..81f4da2780 100644 --- a/common/lib/xmodule/xmodule/modulestore/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/draft.py @@ -67,7 +67,7 @@ class DraftModuleStore(ModuleStoreBase): TODO (vshnayder): this may want to live outside the modulestore eventually """ - # cdodge: we're forcing depth=0 here as the Draft store is not handling caching well + # cdodge: we're forcing depth=0 here as the Draft store is not handling caching well try: return wrap_draft(super(DraftModuleStore, self).get_instance(course_id, as_draft(location), depth=0)) except ItemNotFoundError: diff --git a/common/lib/xmodule/xmodule/modulestore/mongo.py b/common/lib/xmodule/xmodule/modulestore/mongo.py index 3b92876673..f4db62ac31 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo.py @@ -304,7 +304,7 @@ class MongoModuleStore(ModuleStoreBase): if location.category == 'static_tab': course = self.get_course_for_item(item.location) existing_tabs = course.tabs or [] - existing_tabs.append({'type':'static_tab', 'name' : item.metadata.get('display_name'), 'url_slug' : item.location.name}) + existing_tabs.append({'type': 'static_tab', 'name': item.metadata.get('display_name'), 'url_slug': item.location.name}) course.tabs = existing_tabs self.update_metadata(course.location, course.metadata) @@ -423,7 +423,7 @@ class MongoModuleStore(ModuleStoreBase): def get_parent_locations(self, location, course_id): - '''Find all locations that are the parents of this location in this + '''Find all locations that are the parents of this location in this course. Needed for path_to_location(). ''' location = Location.ensure_fully_specified(location) diff --git a/common/lib/xmodule/xmodule/modulestore/search.py b/common/lib/xmodule/xmodule/modulestore/search.py index e53df84bb6..b56b612592 100644 --- a/common/lib/xmodule/xmodule/modulestore/search.py +++ b/common/lib/xmodule/xmodule/modulestore/search.py @@ -104,14 +104,14 @@ def path_to_location(modulestore, course_id, location): # module nested in more than one positional module will work. if n > 3: position_list = [] - for path_index in range(2, n-1): + for path_index in range(2, n - 1): category = path[path_index].category if category == 'sequential' or category == 'videosequence': section_desc = modulestore.get_instance(course_id, path[path_index]) child_locs = [c.location for c in section_desc.get_children()] # positions are 1-indexed, and should be strings to be consistent with # url parsing. - position_list.append(str(child_locs.index(path[path_index+1]) + 1)) + position_list.append(str(child_locs.index(path[path_index + 1]) + 1)) position = "_".join(position_list) return (course_id, chapter, section, position) diff --git a/common/lib/xmodule/xmodule/modulestore/store_utilities.py b/common/lib/xmodule/xmodule/modulestore/store_utilities.py index af346dbb7e..192b012bef 100644 --- a/common/lib/xmodule/xmodule/modulestore/store_utilities.py +++ b/common/lib/xmodule/xmodule/modulestore/store_utilities.py @@ -3,6 +3,7 @@ from xmodule.contentstore.content import StaticContent from xmodule.modulestore import Location from xmodule.modulestore.mongo import MongoModuleStore + def clone_course(modulestore, contentstore, source_location, dest_location, delete_original=False): # first check to see if the modulestore is Mongo backed if not isinstance(modulestore, MongoModuleStore): @@ -13,7 +14,7 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele if not modulestore.has_item(dest_location): raise Exception("An empty course at {0} must have already been created. Aborting...".format(dest_location)) - # verify that the dest_location really is an empty course, which means only one + # verify that the dest_location really is an empty course, which means only one dest_modules = modulestore.get_items([dest_location.tag, dest_location.org, dest_location.course, None, None, None]) if len(dest_modules) != 1: @@ -31,12 +32,12 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele original_loc = Location(module.location) if original_loc.category != 'course': - module.location = module.location._replace(tag = dest_location.tag, org = dest_location.org, - course = dest_location.course) + module.location = module.location._replace(tag=dest_location.tag, org=dest_location.org, + course=dest_location.course) else: # on the course module we also have to update the module name - module.location = module.location._replace(tag = dest_location.tag, org = dest_location.org, - course = dest_location.course, name=dest_location.name) + module.location = module.location._replace(tag=dest_location.tag, org=dest_location.org, + course=dest_location.course, name=dest_location.name) print "Cloning module {0} to {1}....".format(original_loc, module.location) @@ -48,8 +49,8 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele new_children = [] for child_loc_url in module.definition['children']: child_loc = Location(child_loc_url) - child_loc = child_loc._replace(tag = dest_location.tag, org = dest_location.org, - course = dest_location.course) + child_loc = child_loc._replace(tag=dest_location.tag, org=dest_location.org, + course=dest_location.course) new_children = new_children + [child_loc.url()] modulestore.update_children(module.location, new_children) @@ -63,8 +64,8 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele for thumb in thumbs: thumb_loc = Location(thumb["_id"]) content = contentstore.find(thumb_loc) - content.location = content.location._replace(org = dest_location.org, - course = dest_location.course) + content.location = content.location._replace(org=dest_location.org, + course=dest_location.course) print "Cloning thumbnail {0} to {1}".format(thumb_loc, content.location) @@ -76,13 +77,13 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele for asset in assets: asset_loc = Location(asset["_id"]) content = contentstore.find(asset_loc) - content.location = content.location._replace(org = dest_location.org, - course = dest_location.course) + content.location = content.location._replace(org=dest_location.org, + course=dest_location.course) # be sure to update the pointer to the thumbnail if content.thumbnail_location is not None: - content.thumbnail_location = content.thumbnail_location._replace(org = dest_location.org, - course = dest_location.course) + content.thumbnail_location = content.thumbnail_location._replace(org=dest_location.org, + course=dest_location.course) print "Cloning asset {0} to {1}".format(asset_loc, content.location) @@ -90,6 +91,7 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele return True + def delete_course(modulestore, contentstore, source_location): # first check to see if the modulestore is Mongo backed if not isinstance(modulestore, MongoModuleStore): @@ -119,7 +121,7 @@ def delete_course(modulestore, contentstore, source_location): modules = modulestore.get_items([source_location.tag, source_location.org, source_location.course, None, None, None]) for module in modules: - if module.category != 'course': # save deleting the course module for last + if module.category != 'course': # save deleting the course module for last print "Deleting {0}...".format(module.location) modulestore.delete_item(module.location) @@ -127,4 +129,4 @@ def delete_course(modulestore, contentstore, source_location): print "Deleting {0}...".format(source_location) modulestore.delete_item(source_location) - return True \ No newline at end of file + return True diff --git a/common/lib/xmodule/xmodule/modulestore/tests/__init__.py b/common/lib/xmodule/xmodule/modulestore/tests/__init__.py index 126f0136e2..2759f2540c 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/__init__.py @@ -8,5 +8,3 @@ for i in range(5): TEST_DIR = TEST_DIR / 'test' DATA_DIR = TEST_DIR / 'data' - - diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py index b4264b30c9..1259da2690 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py @@ -5,12 +5,15 @@ from xmodule.modulestore import Location from xmodule.modulestore.django import modulestore from xmodule.timeparse import stringify_time -def XMODULE_COURSE_CREATION(class_to_create, **kwargs): + +def XMODULE_COURSE_CREATION(class_to_create, **kwargs): return XModuleCourseFactory._create(class_to_create, **kwargs) + def XMODULE_ITEM_CREATION(class_to_create, **kwargs): return XModuleItemFactory._create(class_to_create, **kwargs) + class XModuleCourseFactory(Factory): """ Factory for XModule courses. @@ -27,7 +30,7 @@ class XModuleCourseFactory(Factory): org = kwargs.get('org') number = kwargs.get('number') display_name = kwargs.get('display_name') - location = Location('i4x', org, number, + location = Location('i4x', org, number, 'course', Location.clean(display_name)) store = modulestore('direct') @@ -42,20 +45,22 @@ class XModuleCourseFactory(Factory): new_course.metadata['data_dir'] = uuid4().hex new_course.metadata['start'] = stringify_time(gmtime()) - new_course.tabs = [{"type": "courseware"}, + new_course.tabs = [{"type": "courseware"}, {"type": "course_info", "name": "Course Info"}, {"type": "discussion", "name": "Discussion"}, {"type": "wiki", "name": "Wiki"}, {"type": "progress", "name": "Progress"}] # Update the data in the mongo datastore - store.update_metadata(new_course.location.url(), new_course.own_metadata) + store.update_metadata(new_course.location.url(), new_course.own_metadata) return new_course + class Course: pass + class CourseFactory(XModuleCourseFactory): FACTORY_FOR = Course @@ -64,6 +69,7 @@ class CourseFactory(XModuleCourseFactory): number = '999' display_name = 'Robot Super Course' + class XModuleItemFactory(Factory): """ Factory for XModule items. @@ -80,7 +86,7 @@ class XModuleItemFactory(Factory): """ DETACHED_CATEGORIES = ['about', 'static_tab', 'course_info'] - + parent_location = Location(kwargs.get('parent_location')) template = Location(kwargs.get('template')) display_name = kwargs.get('display_name') @@ -107,9 +113,11 @@ class XModuleItemFactory(Factory): return new_item + class Item: pass + class ItemFactory(XModuleItemFactory): FACTORY_FOR = Item diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_location.py b/common/lib/xmodule/xmodule/modulestore/tests/test_location.py index afe5e47d10..0772951884 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_location.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_location.py @@ -61,6 +61,7 @@ invalid = ("foo", ["foo"], ["foo", "bar"], invalid_dict, invalid_dict2) + def test_is_valid(): for v in valid: assert_equals(Location.is_valid(v), True) @@ -68,6 +69,7 @@ def test_is_valid(): for v in invalid: assert_equals(Location.is_valid(v), False) + def test_dict(): assert_equals("tag://org/course/category/name", Location(input_dict).url()) assert_equals(dict(revision=None, **input_dict), Location(input_dict).dict()) @@ -76,6 +78,7 @@ def test_dict(): assert_equals("tag://org/course/category/name@revision", Location(input_dict).url()) assert_equals(input_dict, Location(input_dict).dict()) + def test_list(): assert_equals("tag://org/course/category/name", Location(input_list).url()) assert_equals(input_list + [None], Location(input_list).list()) @@ -115,17 +118,18 @@ def test_equality(): ) # All the cleaning functions should do the same thing with these -general_pairs = [ ('',''), +general_pairs = [('', ''), (' ', '_'), ('abc,', 'abc_'), ('ab fg!@//\\aj', 'ab_fg_aj'), (u"ab\xA9", "ab_"), # no unicode allowed for now ] + def test_clean(): pairs = general_pairs + [ ('a:b', 'a_b'), # no colons in non-name components - ('a-b', 'a-b'), # dashes ok + ('a-b', 'a-b'), # dashes ok ('a.b', 'a.b'), # dot ok ] for input, output in pairs: diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore.py index 64816581ce..94ea622907 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_modulestore.py @@ -3,6 +3,7 @@ from nose.tools import assert_equals, assert_raises, assert_not_equals, with_set from xmodule.modulestore.exceptions import ItemNotFoundError, NoPathToItem from xmodule.modulestore.search import path_to_location + def check_path_to_location(modulestore): '''Make sure that path_to_location works: should be passed a modulestore with the toy and simple courses loaded.''' @@ -22,4 +23,3 @@ def check_path_to_location(modulestore): ) for location in not_found: assert_raises(ItemNotFoundError, path_to_location, modulestore, course_id, location) - diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py index 4c593e391e..6f6f47ba85 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py @@ -102,4 +102,3 @@ class TestMongoModuleStore(object): def test_path_to_location(self): '''Make sure that path_to_location works''' check_path_to_location(self.store) - diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py b/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py index c4446bebb5..321d98967b 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_xml.py @@ -5,6 +5,7 @@ from xmodule.modulestore.xml_importer import import_from_xml from .test_modulestore import check_path_to_location from . import DATA_DIR + class TestXMLModuleStore(object): def test_path_to_location(self): """Make sure that path_to_location works properly""" @@ -12,5 +13,5 @@ class TestXMLModuleStore(object): print "Starting import" modulestore = XMLModuleStore(DATA_DIR, course_dirs=['toy', 'simple']) print "finished import" - + check_path_to_location(modulestore) diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py index 17d6f04932..8446162f26 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml.py +++ b/common/lib/xmodule/xmodule/modulestore/xml.py @@ -363,7 +363,7 @@ class XMLModuleStore(ModuleStoreBase): # been imported into the cms from xml course_file = StringIO(clean_out_mako_templating(course_file.read())) - course_data = etree.parse(course_file,parser=edx_xml_parser).getroot() + course_data = etree.parse(course_file, parser=edx_xml_parser).getroot() org = course_data.get('org') @@ -437,7 +437,7 @@ class XMLModuleStore(ModuleStoreBase): self.load_extra_content(system, course_descriptor, 'course_info', self.data_dir / course_dir / 'info', course_dir, url_name) # now import all static tabs which are expected to be stored in - # in /tabs or /tabs/ + # in /tabs or /tabs/ self.load_extra_content(system, course_descriptor, 'static_tab', self.data_dir / course_dir / 'tabs', course_dir, url_name) self.load_extra_content(system, course_descriptor, 'custom_tag_template', self.data_dir / course_dir / 'custom_tags', course_dir, url_name) @@ -454,12 +454,12 @@ class XMLModuleStore(ModuleStoreBase): # then look in a override folder based on the course run if os.path.isdir(base_dir / url_name): - self._load_extra_content(system, course_descriptor, category, base_dir / url_name, course_dir) + self._load_extra_content(system, course_descriptor, category, base_dir / url_name, course_dir) def _load_extra_content(self, system, course_descriptor, category, path, course_dir): - for filepath in glob.glob(path/ '*'): + for filepath in glob.glob(path / '*'): if not os.path.isdir(filepath): with open(filepath) as f: try: @@ -467,7 +467,7 @@ class XMLModuleStore(ModuleStoreBase): # tabs are referenced in policy.json through a 'slug' which is just the filename without the .html suffix slug = os.path.splitext(os.path.basename(filepath))[0] loc = Location('i4x', course_descriptor.location.org, course_descriptor.location.course, category, slug) - module = HtmlDescriptor(system, definition={'data' : html}, **{'location' : loc}) + module = HtmlDescriptor(system, definition={'data': html}, **{'location': loc}) # VS[compat]: # Hack because we need to pull in the 'display_name' for static tabs (because we need to edit them) # from the course policy @@ -555,7 +555,7 @@ class XMLModuleStore(ModuleStoreBase): Return a dictionary of course_dir -> [(msg, exception_str)], for each course_dir where course loading failed. """ - return dict( (k, self.errored_courses[k].errors) for k in self.errored_courses) + return dict((k, self.errored_courses[k].errors) for k in self.errored_courses) def update_item(self, location, data): """ @@ -590,7 +590,7 @@ class XMLModuleStore(ModuleStoreBase): raise NotImplementedError("XMLModuleStores are read-only") def get_parent_locations(self, location, course_id): - '''Find all locations that are the parents of this location in this + '''Find all locations that are the parents of this location in this course. Needed for path_to_location(). returns an iterable of things that can be passed to Location. This may diff --git a/common/lib/xmodule/xmodule/modulestore/xml_exporter.py b/common/lib/xmodule/xmodule/modulestore/xml_exporter.py index 3522b45718..bdbd5a6133 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_exporter.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_exporter.py @@ -3,6 +3,7 @@ from xmodule.modulestore import Location from xmodule.modulestore.django import modulestore from fs.osfs import OSFS + def export_to_xml(modulestore, contentstore, course_location, root_dir, course_dir): course = modulestore.get_item(course_location) @@ -27,7 +28,7 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d export_extra_content(export_fs, modulestore, course_location, 'course_info', 'info', '.html') -def export_extra_content(export_fs, modulestore, course_location, category_type, dirname, file_suffix = ''): +def export_extra_content(export_fs, modulestore, course_location, category_type, dirname, file_suffix=''): query_loc = Location('i4x', course_location.org, course_location.course, category_type, None) items = modulestore.get_items(query_loc) @@ -36,7 +37,3 @@ def export_extra_content(export_fs, modulestore, course_location, category_type, for item in items: with item_dir.open(item.location.name + file_suffix, 'w') as item_file: item_file.write(item.definition['data'].encode('utf8')) - - - - \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py index 7658d699d4..0b77900ae9 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py @@ -11,9 +11,10 @@ from xmodule.contentstore.content import StaticContent, XASSET_SRCREF_PREFIX log = logging.getLogger(__name__) -def import_static_content(modules, course_loc, course_data_path, static_content_store, target_location_namespace, - subpath = 'static', verbose=False): - + +def import_static_content(modules, course_loc, course_data_path, static_content_store, target_location_namespace, + subpath='static', verbose=False): + remap_dict = {} # now import all static assets @@ -36,7 +37,7 @@ def import_static_content(modules, course_loc, course_data_path, static_content_ with open(content_path, 'rb') as f: data = f.read() - content = StaticContent(content_loc, filename, mime_type, data, import_path = fullname_with_subpath) + content = StaticContent(content_loc, filename, mime_type, data, import_path=fullname_with_subpath) # first let's save a thumbnail so we can get back a thumbnail location (thumbnail_content, thumbnail_location) = static_content_store.generate_thumbnail(content) @@ -50,11 +51,12 @@ def import_static_content(modules, course_loc, course_data_path, static_content_ #store the remapping information which will be needed to subsitute in the module data remap_dict[fullname_with_subpath] = content_loc.name except: - raise + raise return remap_dict -def verify_content_links(module, base_dir, static_content_store, link, remap_dict = None): + +def verify_content_links(module, base_dir, static_content_store, link, remap_dict=None): if link.startswith('/static/'): # yes, then parse out the name path = link[len('/static/'):] @@ -70,7 +72,7 @@ def verify_content_links(module, base_dir, static_content_store, link, remap_dic with open(static_pathname, 'rb') as f: data = f.read() - content = StaticContent(content_loc, filename, mime_type, data, import_path = path) + content = StaticContent(content_loc, filename, mime_type, data, import_path=path) # first let's save a thumbnail so we can get back a thumbnail location (thumbnail_content, thumbnail_location) = static_content_store.generate_thumbnail(content) @@ -79,20 +81,21 @@ def verify_content_links(module, base_dir, static_content_store, link, remap_dic content.thumbnail_location = thumbnail_location #then commit the content - static_content_store.save(content) + static_content_store.save(content) - new_link = StaticContent.get_url_path_from_location(content_loc) + new_link = StaticContent.get_url_path_from_location(content_loc) if remap_dict is not None: remap_dict[link] = new_link - return new_link + return new_link except Exception, e: logging.exception('Skipping failed content load from {0}. Exception: {1}'.format(path, e)) return link -def import_from_xml(store, data_dir, course_dirs=None, + +def import_from_xml(store, data_dir, course_dirs=None, default_class='xmodule.raw_module.RawDescriptor', load_error_modules=True, static_content_store=None, target_location_namespace=None, verbose=False): """ @@ -108,7 +111,7 @@ def import_from_xml(store, data_dir, course_dirs=None, the policy.json. so we need to keep the original url_name during import """ - + module_store = XMLModuleStore( data_dir, default_class=default_class, @@ -137,12 +140,12 @@ def import_from_xml(store, data_dir, course_dirs=None, module = remap_namespace(module, target_location_namespace) - # cdodge: more hacks (what else). Seems like we have a problem when importing a course (like 6.002) which - # does not have any tabs defined in the policy file. The import goes fine and then displays fine in LMS, - # but if someone tries to add a new tab in the CMS, then the LMS barfs because it expects that - + # cdodge: more hacks (what else). Seems like we have a problem when importing a course (like 6.002) which + # does not have any tabs defined in the policy file. The import goes fine and then displays fine in LMS, + # but if someone tries to add a new tab in the CMS, then the LMS barfs because it expects that - # if there is *any* tabs - then there at least needs to be some predefined ones if module.tabs is None or len(module.tabs) == 0: - module.tabs = [{"type": "courseware"}, + module.tabs = [{"type": "courseware"}, {"type": "course_info", "name": "Course Info"}, {"type": "discussion", "name": "Discussion"}, {"type": "wiki", "name": "Wiki"}] # note, add 'progress' when we can support it on Edge @@ -159,13 +162,13 @@ def import_from_xml(store, data_dir, course_dirs=None, course_items.append(module) - + # then import all the static content if static_content_store is not None: _namespace_rename = target_location_namespace if target_location_namespace is not None else course_location - + # first pass to find everything in /static/ - import_static_content(module_store.modules[course_id], course_location, course_data_path, static_content_store, + import_static_content(module_store.modules[course_id], course_location, course_data_path, static_content_store, _namespace_rename, subpath='static', verbose=verbose) # finally loop through all the modules @@ -188,18 +191,18 @@ def import_from_xml(store, data_dir, course_dirs=None, # cdodge: now go through any link references to '/static/' and make sure we've imported # it as a StaticContent asset - try: + try: remap_dict = {} # use the rewrite_links as a utility means to enumerate through all links # in the module data. We use that to load that reference into our asset store # IMPORTANT: There appears to be a bug in lxml.rewrite_link which makes us not be able to # do the rewrites natively in that code. - # For example, what I'm seeing is -> + # For example, what I'm seeing is -> # Note the dropped element closing tag. This causes the LMS to fail when rendering modules - that's # no good, so we have to do this kludge if isinstance(module_data, str) or isinstance(module_data, unicode): # some module 'data' fields are non strings which blows up the link traversal code - lxml_rewrite_links(module_data, lambda link: verify_content_links(module, course_data_path, + lxml_rewrite_links(module_data, lambda link: verify_content_links(module, course_data_path, static_content_store, link, remap_dict)) for key in remap_dict.keys(): @@ -219,17 +222,18 @@ def import_from_xml(store, data_dir, course_dirs=None, return module_store, course_items + def remap_namespace(module, target_location_namespace): if target_location_namespace is None: return module - + # This looks a bit wonky as we need to also change the 'name' of the imported course to be what # the caller passed in if module.location.category != 'course': - module.location = module.location._replace(tag=target_location_namespace.tag, org=target_location_namespace.org, + module.location = module.location._replace(tag=target_location_namespace.tag, org=target_location_namespace.org, course=target_location_namespace.course) else: - module.location = module.location._replace(tag=target_location_namespace.tag, org=target_location_namespace.org, + module.location = module.location._replace(tag=target_location_namespace.tag, org=target_location_namespace.org, course=target_location_namespace.course, name=target_location_namespace.name) # then remap children pointers since they too will be re-namespaced @@ -238,15 +242,16 @@ def remap_namespace(module, target_location_namespace): new_locs = [] for child in children_locs: child_loc = Location(child) - new_child_loc = child_loc._replace(tag=target_location_namespace.tag, org=target_location_namespace.org, + new_child_loc = child_loc._replace(tag=target_location_namespace.tag, org=target_location_namespace.org, course=target_location_namespace.course) new_locs.append(new_child_loc.url()) - module.definition['children'] = new_locs + module.definition['children'] = new_locs return module + def validate_category_hierarchy(module_store, course_id, parent_category, expected_child_category): err_cnt = 0 @@ -265,7 +270,8 @@ def validate_category_hierarchy(module_store, course_id, parent_category, expect return err_cnt -def validate_data_source_path_existence(path, is_err = True, extra_msg = None): + +def validate_data_source_path_existence(path, is_err=True, extra_msg=None): _cnt = 0 if not os.path.exists(path): print ("{0}: Expected folder at {1}. {2}".format('ERROR' if is_err == True else 'WARNING', path, extra_msg if @@ -273,18 +279,19 @@ def validate_data_source_path_existence(path, is_err = True, extra_msg = None): _cnt = 1 return _cnt + def validate_data_source_paths(data_dir, course_dir): # check that there is a '/static/' directory course_path = data_dir / course_dir err_cnt = 0 warn_cnt = 0 err_cnt += validate_data_source_path_existence(course_path / 'static') - warn_cnt += validate_data_source_path_existence(course_path / 'static/subs', is_err = False, - extra_msg = 'Video captions (if they are used) will not work unless they are static/subs.') + warn_cnt += validate_data_source_path_existence(course_path / 'static/subs', is_err=False, + extra_msg='Video captions (if they are used) will not work unless they are static/subs.') return err_cnt, warn_cnt -def perform_xlint(data_dir, course_dirs, +def perform_xlint(data_dir, course_dirs, default_class='xmodule.raw_module.RawDescriptor', load_error_modules=True): err_cnt = 0 @@ -308,9 +315,9 @@ def perform_xlint(data_dir, course_dirs, for err_log_entry in err_log.errors: msg = err_log_entry[0] if msg.startswith('ERROR:'): - err_cnt+=1 + err_cnt += 1 else: - warn_cnt+=1 + warn_cnt += 1 # then count outright all courses that failed to load at all for err_log in module_store.errored_courses.itervalues(): @@ -318,9 +325,9 @@ def perform_xlint(data_dir, course_dirs, msg = err_log_entry[0] print msg if msg.startswith('ERROR:'): - err_cnt+=1 + err_cnt += 1 else: - warn_cnt+=1 + warn_cnt += 1 for course_id in module_store.modules.keys(): # constrain that courses only have 'chapter' children @@ -345,6 +352,3 @@ def perform_xlint(data_dir, course_dirs, print "This course can be imported, but some errors may occur during the run of the course. It is recommend that you fix your courseware before importing" else: print "This course can be imported successfully." - - - diff --git a/common/lib/xmodule/xmodule/open_ended_image_submission.py b/common/lib/xmodule/xmodule/open_ended_image_submission.py index 8fa4d721d3..10b1a20a7c 100644 --- a/common/lib/xmodule/xmodule/open_ended_image_submission.py +++ b/common/lib/xmodule/xmodule/open_ended_image_submission.py @@ -51,6 +51,7 @@ MAX_COLORS_TO_COUNT = 16 #Maximum number of colors allowed in an uploaded image MAX_COLORS = 400 + class ImageProperties(object): """ Class to check properties of an image and to validate if they are allowed. @@ -187,6 +188,7 @@ class URLProperties(object): return success return success + def run_url_tests(url_string): """ Creates a URLProperties object and runs all tests @@ -244,7 +246,7 @@ def upload_to_s3(file_to_upload, keyname): #k.set_metadata("Content-Type", 'images/png') k.set_acl("public-read") - public_url = k.generate_url(60 * 60 * 24 * 365) # URL timeout in seconds. + public_url = k.generate_url(60 * 60 * 24 * 365) # URL timeout in seconds. return True, public_url except: @@ -260,6 +262,3 @@ def get_from_s3(s3_public_url): r = requests.get(s3_public_url, timeout=2) data = r.text return data - - - diff --git a/common/lib/xmodule/xmodule/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_module.py index 94d45d96e3..072a7153fb 100644 --- a/common/lib/xmodule/xmodule/open_ended_module.py +++ b/common/lib/xmodule/xmodule/open_ended_module.py @@ -38,6 +38,7 @@ from combined_open_ended_rubric import CombinedOpenEndedRubric log = logging.getLogger("mitx.courseware") + class OpenEndedModule(openendedchild.OpenEndedChild): """ The open ended module supports all external open ended grader problems. @@ -300,7 +301,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): # We want to display available feedback in a particular order. # This dictionary specifies which goes first--lower first. - priorities = {# These go at the start of the feedback + priorities = { # These go at the start of the feedback 'spelling': 0, 'grammar': 1, # needs to be after all the other feedback @@ -674,5 +675,3 @@ class OpenEndedDescriptor(XmlDescriptor, EditingDescriptor): add_child(child) return elt - - diff --git a/common/lib/xmodule/xmodule/openendedchild.py b/common/lib/xmodule/xmodule/openendedchild.py index 7151ac0723..a56937270b 100644 --- a/common/lib/xmodule/xmodule/openendedchild.py +++ b/common/lib/xmodule/xmodule/openendedchild.py @@ -38,6 +38,7 @@ MAX_ATTEMPTS = 1 # Overriden by max_score specified in xml. MAX_SCORE = 1 + class OpenEndedChild(object): """ States: @@ -375,18 +376,13 @@ class OpenEndedChild(object): """ success = False links = re.findall(r'(https?://\S+)', string) - if len(links)>0: + if len(links) > 0: for link in links: success = open_ended_image_submission.run_url_tests(link) if not success: string = re.sub(link, '', string) else: - string = re.sub(link, self.generate_image_tag_from_url(link,link), string) + string = re.sub(link, self.generate_image_tag_from_url(link, link), string) success = True return success, string - - - - - diff --git a/common/lib/xmodule/xmodule/peer_grading_module.py b/common/lib/xmodule/xmodule/peer_grading_module.py index e853160f4a..20f71f3b3c 100644 --- a/common/lib/xmodule/xmodule/peer_grading_module.py +++ b/common/lib/xmodule/xmodule/peer_grading_module.py @@ -43,6 +43,7 @@ TRUE_DICT = [True, "True", "true", "TRUE"] MAX_SCORE = 1 IS_GRADED = True + class PeerGradingModule(XModule): _VERSION = 1 @@ -80,7 +81,7 @@ class PeerGradingModule(XModule): self.is_graded = (self.is_graded in TRUE_DICT) self.link_to_location = self.metadata.get('link_to_location', USE_FOR_SINGLE_LOCATION) - if self.use_for_single_location ==True: + if self.use_for_single_location == True: #This will raise an exception if the location is invalid link_to_location_object = Location(self.link_to_location) @@ -116,7 +117,7 @@ class PeerGradingModule(XModule): if not self.use_for_single_location: return self.peer_grading() else: - return self.peer_grading_problem({'location' : self.link_to_location})['html'] + return self.peer_grading_problem({'location': self.link_to_location})['html'] def handle_ajax(self, dispatch, get): """ @@ -128,8 +129,8 @@ class PeerGradingModule(XModule): 'show_calibration_essay': self.show_calibration_essay, 'is_student_calibrated': self.is_student_calibrated, 'save_grade': self.save_grade, - 'save_calibration_essay' : self.save_calibration_essay, - 'problem' : self.peer_grading_problem, + 'save_calibration_essay': self.save_calibration_essay, + 'problem': self.peer_grading_problem, } if dispatch not in handlers: @@ -175,11 +176,11 @@ class PeerGradingModule(XModule): return None count_graded = response['count_graded'] count_required = response['count_required'] - if count_required>0 and count_graded>=count_required: + if count_required > 0 and count_graded >= count_required: self.student_data_for_location = response score_dict = { - 'score': int(count_graded>=count_required), + 'score': int(count_graded >= count_required), 'total': self.max_grade, } @@ -399,7 +400,7 @@ class PeerGradingModule(XModule): log.exception("Error saving calibration grade, location: {0}, submission_id: {1}, submission_key: {2}, grader_id: {3}".format(location, submission_id, submission_key, grader_id)) return self._err_response('Could not connect to grading service') - def peer_grading(self, get = None): + def peer_grading(self, get=None): ''' Show a peer grading interface ''' @@ -434,19 +435,19 @@ class PeerGradingModule(XModule): 'error_text': error_text, # Checked above 'staff_access': False, - 'use_single_location' : self.use_for_single_location, + 'use_single_location': self.use_for_single_location, }) return html - def peer_grading_problem(self, get = None): + def peer_grading_problem(self, get=None): ''' Show individual problem interface ''' - if get == None or get.get('location')==None: + if get == None or get.get('location') == None: if not self.use_for_single_location: #This is an error case, because it must be set to use a single location to be called without get parameters - return {'html' : "", 'success' : False} + return {'html': "", 'success': False} problem_location = self.link_to_location elif get.get('location') is not None: @@ -460,10 +461,10 @@ class PeerGradingModule(XModule): 'ajax_url': ajax_url, # Checked above 'staff_access': False, - 'use_single_location' : self.use_for_single_location, + 'use_single_location': self.use_for_single_location, }) - return {'html' : html, 'success' : True} + return {'html': html, 'success': True} def get_instance_state(self): """ @@ -473,11 +474,12 @@ class PeerGradingModule(XModule): """ state = { - 'student_data_for_location' : self.student_data_for_location, + 'student_data_for_location': self.student_data_for_location, } return json.dumps(state) + class PeerGradingDescriptor(XmlDescriptor, EditingDescriptor): """ Module for adding combined open ended questions @@ -534,4 +536,4 @@ class PeerGradingDescriptor(XmlDescriptor, EditingDescriptor): for child in ['task']: add_child(child) - return elt \ No newline at end of file + return elt diff --git a/common/lib/xmodule/xmodule/peer_grading_service.py b/common/lib/xmodule/xmodule/peer_grading_service.py index 6b30f4e043..8c50b6ff0a 100644 --- a/common/lib/xmodule/xmodule/peer_grading_service.py +++ b/common/lib/xmodule/xmodule/peer_grading_service.py @@ -14,11 +14,13 @@ from combined_open_ended_rubric import CombinedOpenEndedRubric, RubricParsingErr from lxml import etree from grading_service_module import GradingService, GradingServiceError -log=logging.getLogger(__name__) +log = logging.getLogger(__name__) + class GradingServiceError(Exception): pass + class PeerGradingService(GradingService): """ Interface with the grading controller for peer grading @@ -47,23 +49,23 @@ class PeerGradingService(GradingService): return self.try_to_decode(self._render_rubric(response)) def save_grade(self, location, grader_id, submission_id, score, feedback, submission_key, rubric_scores, submission_flagged): - data = {'grader_id' : grader_id, - 'submission_id' : submission_id, - 'score' : score, - 'feedback' : feedback, + data = {'grader_id': grader_id, + 'submission_id': submission_id, + 'score': score, + 'feedback': feedback, 'submission_key': submission_key, 'location': location, 'rubric_scores': rubric_scores, 'rubric_scores_complete': True, - 'submission_flagged' : submission_flagged} + 'submission_flagged': submission_flagged} return self.try_to_decode(self.post(self.save_grade_url, data)) def is_student_calibrated(self, problem_location, grader_id): - params = {'problem_id' : problem_location, 'student_id': grader_id} + params = {'problem_id': problem_location, 'student_id': grader_id} return self.try_to_decode(self.get(self.is_student_calibrated_url, params)) def show_calibration_essay(self, problem_location, grader_id): - params = {'problem_id' : problem_location, 'student_id': grader_id} + params = {'problem_id': problem_location, 'student_id': grader_id} response = self.get(self.show_calibration_essay_url, params) return self.try_to_decode(self._render_rubric(response)) @@ -100,10 +102,12 @@ class PeerGradingService(GradingService): This is a mock peer grading service that can be used for unit tests without making actual service calls to the grading controller """ + + class MockPeerGradingService(object): def get_next_submission(self, problem_location, grader_id): return json.dumps({'success': True, - 'submission_id':1, + 'submission_id': 1, 'submission_key': "", 'student_response': 'fake student response', 'prompt': 'fake submission prompt', @@ -119,7 +123,7 @@ class MockPeerGradingService(object): def show_calibration_essay(self, problem_location, grader_id): return json.dumps({'success': True, - 'submission_id':1, + 'submission_id': 1, 'submission_key': '', 'student_response': 'fake student response', 'prompt': 'fake submission prompt', @@ -140,6 +144,8 @@ class MockPeerGradingService(object): ]}) _service = None + + def peer_grading_service(system): """ Return a peer grading service instance--if settings.MOCK_PEER_GRADING is True, diff --git a/common/lib/xmodule/xmodule/randomize_module.py b/common/lib/xmodule/xmodule/randomize_module.py index f88cdc5efb..b336789193 100644 --- a/common/lib/xmodule/xmodule/randomize_module.py +++ b/common/lib/xmodule/xmodule/randomize_module.py @@ -12,6 +12,7 @@ from pkg_resources import resource_string log = logging.getLogger('mitx.' + __name__) + class RandomizeModule(XModule): """ Chooses a random child module. Chooses the same one every time for each student. @@ -96,7 +97,7 @@ class RandomizeModule(XModule): def get_icon_class(self): return self.child.get_icon_class() if self.child else 'other' - + class RandomizeDescriptor(SequenceDescriptor): # the editing interface can be the same as for sequences -- just a container module_class = RandomizeModule @@ -118,4 +119,3 @@ class RandomizeDescriptor(SequenceDescriptor): makes it use module.get_child_descriptors(). """ return True - diff --git a/common/lib/xmodule/xmodule/raw_module.py b/common/lib/xmodule/xmodule/raw_module.py index efdd2e7ba0..4a2bfbceaf 100644 --- a/common/lib/xmodule/xmodule/raw_module.py +++ b/common/lib/xmodule/xmodule/raw_module.py @@ -6,6 +6,7 @@ import sys log = logging.getLogger(__name__) + class RawDescriptor(XmlDescriptor, XMLEditingDescriptor): """ Module that provides a raw editing view of its data and children. It @@ -13,7 +14,7 @@ class RawDescriptor(XmlDescriptor, XMLEditingDescriptor): """ @classmethod def definition_from_xml(cls, xml_object, system): - return {'data': etree.tostring(xml_object, pretty_print=True,encoding='unicode')} + return {'data': etree.tostring(xml_object, pretty_print=True, encoding='unicode')} def definition_to_xml(self, resource_fs): try: diff --git a/common/lib/xmodule/xmodule/self_assessment_module.py b/common/lib/xmodule/xmodule/self_assessment_module.py index 38a60e11f5..07cc68a83a 100644 --- a/common/lib/xmodule/xmodule/self_assessment_module.py +++ b/common/lib/xmodule/xmodule/self_assessment_module.py @@ -25,6 +25,7 @@ from combined_open_ended_rubric import CombinedOpenEndedRubric log = logging.getLogger("mitx.courseware") + class SelfAssessmentModule(openendedchild.OpenEndedChild): """ A Self Assessment module that allows students to write open-ended responses, diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py index 6dd92cc8fa..36011744f5 100644 --- a/common/lib/xmodule/xmodule/seq_module.py +++ b/common/lib/xmodule/xmodule/seq_module.py @@ -88,8 +88,8 @@ class SequenceModule(XModule): 'type': child.get_icon_class(), 'id': child.id, } - if childinfo['title']=='': - childinfo['title'] = child.metadata.get('display_name','') + if childinfo['title'] == '': + childinfo['title'] = child.metadata.get('display_name', '') contents.append(childinfo) params = {'items': contents, @@ -116,7 +116,7 @@ class SequenceDescriptor(MakoModuleDescriptor, XmlDescriptor): mako_template = 'widgets/sequence-edit.html' module_class = SequenceModule - stores_state = True # For remembering where in the sequence the student is + stores_state = True # For remembering where in the sequence the student is js = {'coffee': [resource_string(__name__, 'js/src/sequence/edit.coffee')]} js_module_name = "SequenceDescriptor" @@ -140,4 +140,3 @@ class SequenceDescriptor(MakoModuleDescriptor, XmlDescriptor): xml_object.append( etree.fromstring(child.export_to_xml(resource_fs))) return xml_object - diff --git a/common/lib/xmodule/xmodule/stringify.py b/common/lib/xmodule/xmodule/stringify.py index dab8ff0425..5a640e91b1 100644 --- a/common/lib/xmodule/xmodule/stringify.py +++ b/common/lib/xmodule/xmodule/stringify.py @@ -1,6 +1,7 @@ from itertools import chain from lxml import etree + def stringify_children(node): ''' Return all contents of an xml tree, without the outside tags. diff --git a/common/lib/xmodule/xmodule/template_module.py b/common/lib/xmodule/xmodule/template_module.py index d7e7ece897..5f376945eb 100644 --- a/common/lib/xmodule/xmodule/template_module.py +++ b/common/lib/xmodule/xmodule/template_module.py @@ -5,6 +5,7 @@ from mako.template import Template from xmodule.modulestore.django import modulestore import logging + class CustomTagModule(XModule): """ This module supports tags of the form @@ -81,4 +82,3 @@ class CustomTagDescriptor(RawDescriptor): to export them in a file with yet another layer of indirection. """ return False - diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index 1f323834a9..04e7ee19b1 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -29,9 +29,9 @@ test_system = ModuleSystem( user=Mock(is_staff=False), filestore=Mock(), debug=True, - xqueue={'interface':None, 'callback_url':'/', 'default_queuename': 'testqueue', 'waittime': 10}, + xqueue={'interface': None, 'callback_url': '/', 'default_queuename': 'testqueue', 'waittime': 10}, node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"), - anonymous_student_id = 'student' + anonymous_student_id='student' ) @@ -85,4 +85,3 @@ class ModelsTest(unittest.TestCase): except: exception_happened = True self.assertTrue(exception_happened) - diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py index e8f639e3c9..a22fcdb5f6 100644 --- a/common/lib/xmodule/xmodule/tests/test_capa_module.py +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -10,6 +10,7 @@ from lxml import etree from . import test_system + class CapaFactory(object): """ A helper class to create problem modules with various parameters for testing. @@ -58,7 +59,7 @@ class CapaFactory(object): attempts: also added to instance state. Will be converted to an int. """ - definition = {'data': CapaFactory.sample_problem_xml,} + definition = {'data': CapaFactory.sample_problem_xml, } location = Location(["i4x", "edX", "capa_test", "problem", "SampleProblem{0}".format(CapaFactory.next_num())]) metadata = {} @@ -208,8 +209,3 @@ class CapaModuleTest(unittest.TestCase): due=self.yesterday_str, graceperiod=self.two_day_delta_str) self.assertFalse(still_in_grace.answer_available()) - - - - - diff --git a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py index c89f5ee848..690eb7e39e 100644 --- a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py +++ b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py @@ -20,6 +20,7 @@ OpenEndedModule """ + class OpenEndedChildTest(unittest.TestCase): location = Location(["i4x", "edX", "sa_test", "selfassessment", "SampleQuestion"]) @@ -38,17 +39,17 @@ class OpenEndedChildTest(unittest.TestCase): 'max_attempts': 20, 'prompt': prompt, 'rubric': rubric, - 'max_score': max_score, + 'max_score': max_score, 'display_name': 'Name', - 'accept_file_upload' : False, + 'accept_file_upload': False, } definition = Mock() descriptor = Mock() def setUp(self): - self.openendedchild = OpenEndedChild(test_system, self.location, + self.openendedchild = OpenEndedChild(test_system, self.location, self.definition, self.descriptor, self.static_data, self.metadata) - + def test_latest_answer_empty(self): answer = self.openendedchild.latest_answer() @@ -115,12 +116,12 @@ class OpenEndedChildTest(unittest.TestCase): self.assertEqual(score['score'], new_score) self.assertEqual(score['total'], self.static_data['max_score']) - + def test_reset(self): self.openendedchild.reset(test_system) state = json.loads(self.openendedchild.get_instance_state()) self.assertEqual(state['state'], OpenEndedChild.INITIAL) - + def test_is_last_response_correct(self): new_answer = "New Answer" @@ -134,6 +135,7 @@ class OpenEndedChildTest(unittest.TestCase): self.assertEqual(self.openendedchild.is_last_response_correct(), 'incorrect') + class OpenEndedModuleTest(unittest.TestCase): location = Location(["i4x", "edX", "sa_test", "selfassessment", "SampleQuestion"]) @@ -152,7 +154,7 @@ class OpenEndedModuleTest(unittest.TestCase): 'max_attempts': 20, 'prompt': prompt, 'rubric': rubric, - 'max_score': max_score, + 'max_score': max_score, 'display_name': 'Name', 'accept_file_upload': False, } @@ -170,9 +172,9 @@ class OpenEndedModuleTest(unittest.TestCase): def setUp(self): test_system.location = self.location self.mock_xqueue = MagicMock() - self.mock_xqueue.send_to_queue.return_value=(None, "Message") - test_system.xqueue = {'interface':self.mock_xqueue, 'callback_url':'/', 'default_queuename': 'testqueue', 'waittime': 1} - self.openendedmodule = OpenEndedModule(test_system, self.location, + self.mock_xqueue.send_to_queue.return_value = (None, "Message") + test_system.xqueue = {'interface': self.mock_xqueue, 'callback_url': '/', 'default_queuename': 'testqueue', 'waittime': 1} + self.openendedmodule = OpenEndedModule(test_system, self.location, self.definition, self.descriptor, self.static_data, self.metadata) def test_message_post(self): @@ -194,8 +196,8 @@ class OpenEndedModuleTest(unittest.TestCase): result = self.openendedmodule.message_post(get, test_system) self.assertTrue(result['success']) # make sure it's actually sending something we want to the queue - self.mock_xqueue.send_to_queue.assert_called_with(body = json.dumps(contents), header=ANY) - + self.mock_xqueue.send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY) + state = json.loads(self.openendedmodule.get_instance_state()) self.assertIsNotNone(state['state'], OpenEndedModule.DONE) @@ -205,21 +207,21 @@ class OpenEndedModuleTest(unittest.TestCase): student_info = {'anonymous_student_id': test_system.anonymous_student_id, 'submission_time': qtime} contents = self.openendedmodule.payload.copy() - contents.update({ + contents.update({ 'student_info': json.dumps(student_info), - 'student_response': submission, + 'student_response': submission, 'max_score': self.max_score }) result = self.openendedmodule.send_to_grader(submission, test_system) self.assertTrue(result) - self.mock_xqueue.send_to_queue.assert_called_with(body = json.dumps(contents), header=ANY) + self.mock_xqueue.send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY) def update_score_single(self): self.openendedmodule.new_history_entry("New Entry") - score_msg = { + score_msg = { 'correct': True, 'score': 4, - 'msg' : 'Grader Message', + 'msg': 'Grader Message', 'feedback': "Grader Feedback" } get = {'queuekey': "abcd", @@ -232,10 +234,10 @@ class OpenEndedModuleTest(unittest.TestCase): "success": True, "feedback": "Grader Feedback" } - score_msg = { + score_msg = { 'correct': True, 'score': 4, - 'msg' : 'Grader Message', + 'msg': 'Grader Message', 'feedback': json.dumps(feedback), 'grader_type': 'IN', 'grader_id': '1', @@ -261,6 +263,7 @@ class OpenEndedModuleTest(unittest.TestCase): score = self.openendedmodule.latest_score() self.assertEqual(score, 4) + class CombinedOpenEndedModuleTest(unittest.TestCase): location = Location(["i4x", "edX", "open_ended", "combinedopenended", "SampleQuestion"]) @@ -280,7 +283,7 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): 'max_attempts': 20, 'prompt': prompt, 'rubric': rubric, - 'max_score': max_score, + 'max_score': max_score, 'display_name': 'Name' }) @@ -335,5 +338,3 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): changed = self.combinedoe.update_task_states() self.assertTrue(changed) - - diff --git a/common/lib/xmodule/xmodule/tests/test_conditional.py b/common/lib/xmodule/xmodule/tests/test_conditional.py index f889ec7111..1b463eccaf 100644 --- a/common/lib/xmodule/xmodule/tests/test_conditional.py +++ b/common/lib/xmodule/xmodule/tests/test_conditional.py @@ -17,10 +17,11 @@ from xmodule.modulestore.exceptions import ItemNotFoundError from .test_export import DATA_DIR ORG = 'test_org' -COURSE = 'conditional' # name of directory with course data +COURSE = 'conditional' # name of directory with course data from . import test_system + class DummySystem(ImportSystem): @patch('xmodule.modulestore.xml.OSFS', lambda dir: MemoryFS()) @@ -82,11 +83,11 @@ class ConditionalModuleTest(unittest.TestCase): location = descriptor descriptor = self.modulestore.get_instance(course.id, location, depth=None) location = descriptor.location - instance_state = instance_states.get(location.category,None) + instance_state = instance_states.get(location.category, None) print "inner_get_module, location.category=%s, inst_state=%s" % (location.category, instance_state) return descriptor.xmodule_constructor(test_system)(instance_state, shared_state) - location = Location(["i4x", "edX", "cond_test", "conditional","condone"]) + location = Location(["i4x", "edX", "cond_test", "conditional", "condone"]) module = inner_get_module(location) def replace_urls(text, staticfiles_prefix=None, replace_prefix='/static/', course_namespace=None): @@ -105,15 +106,13 @@ class ConditionalModuleTest(unittest.TestCase): gdi = module.get_display_items() print "gdi=", gdi - ajax = json.loads(module.handle_ajax('','')) + ajax = json.loads(module.handle_ajax('', '')) self.assertTrue('xmodule.conditional_module' in ajax['html']) print "ajax: ", ajax # now change state of the capa problem to make it completed - instance_states['problem'] = json.dumps({'attempts':1}) + instance_states['problem'] = json.dumps({'attempts': 1}) - ajax = json.loads(module.handle_ajax('','')) + ajax = json.loads(module.handle_ajax('', '')) self.assertTrue('This is a secret' in ajax['html']) print "post-attempt ajax: ", ajax - - diff --git a/common/lib/xmodule/xmodule/tests/test_content.py b/common/lib/xmodule/xmodule/tests/test_content.py index 6bd10f22f7..1bcd2f4ebe 100644 --- a/common/lib/xmodule/xmodule/tests/test_content.py +++ b/common/lib/xmodule/xmodule/tests/test_content.py @@ -3,11 +3,13 @@ from xmodule.contentstore.content import StaticContent from xmodule.contentstore.content import ContentStore from xmodule.modulestore import Location + class Content: def __init__(self, location, content_type): self.location = location self.content_type = content_type + class ContentTest(unittest.TestCase): def test_thumbnail_none(self): # We had a bug where a thumbnail location of None was getting transformed into a Location tuple, with @@ -22,4 +24,4 @@ class ContentTest(unittest.TestCase): content = Content(Location(u'c4x', u'mitX', u'800', u'asset', u'monsters.jpg'), None) (thumbnail_content, thumbnail_file_location) = contentStore.generate_thumbnail(content) self.assertIsNone(thumbnail_content) - self.assertEqual(Location(u'c4x', u'mitX', u'800', u'thumbnail', u'monsters.jpg'), thumbnail_file_location) \ No newline at end of file + self.assertEqual(Location(u'c4x', u'mitX', u'800', u'thumbnail', u'monsters.jpg'), thumbnail_file_location) diff --git a/common/lib/xmodule/xmodule/tests/test_export.py b/common/lib/xmodule/xmodule/tests/test_export.py index f92d58db03..da1b04bd94 100644 --- a/common/lib/xmodule/xmodule/tests/test_export.py +++ b/common/lib/xmodule/xmodule/tests/test_export.py @@ -27,6 +27,7 @@ def strip_metadata(descriptor, key): for d in descriptor.get_children(): strip_metadata(d, key) + def strip_filenames(descriptor): """ Recursively strips 'filename' from all children's definitions. @@ -119,12 +120,12 @@ class RoundTripTestCase(unittest.TestCase): def test_selfassessment_roundtrip(self): #Test selfassessment xmodule to see if it exports correctly - self.check_export_roundtrip(DATA_DIR,"self_assessment") + self.check_export_roundtrip(DATA_DIR, "self_assessment") def test_graphicslidertool_roundtrip(self): #Test graphicslidertool xmodule to see if it exports correctly - self.check_export_roundtrip(DATA_DIR,"graphic_slider_tool") + self.check_export_roundtrip(DATA_DIR, "graphic_slider_tool") def test_exam_registration_roundtrip(self): # Test exam_registration xmodule to see if it exports correctly - self.check_export_roundtrip(DATA_DIR,"test_exam_registration") + self.check_export_roundtrip(DATA_DIR, "test_exam_registration") diff --git a/common/lib/xmodule/xmodule/tests/test_graders.py b/common/lib/xmodule/xmodule/tests/test_graders.py index fa0e94d2d5..27416b1d5c 100644 --- a/common/lib/xmodule/xmodule/tests/test_graders.py +++ b/common/lib/xmodule/xmodule/tests/test_graders.py @@ -4,6 +4,7 @@ import unittest from xmodule import graders from xmodule.graders import Score, aggregate_scores + class GradesheetTest(unittest.TestCase): def test_weighted_grading(self): @@ -217,4 +218,3 @@ class GraderTest(unittest.TestCase): #TODO: How do we test failure cases? The parser only logs an error when #it can't parse something. Maybe it should throw exceptions? - diff --git a/common/lib/xmodule/xmodule/tests/test_import.py b/common/lib/xmodule/xmodule/tests/test_import.py index 7cd91223e3..42072ffe4d 100644 --- a/common/lib/xmodule/xmodule/tests/test_import.py +++ b/common/lib/xmodule/xmodule/tests/test_import.py @@ -61,6 +61,7 @@ class BaseCourseTestCase(unittest.TestCase): self.assertEquals(len(courses), 1) return courses[0] + class ImportTestCase(BaseCourseTestCase): def test_fallback(self): @@ -323,7 +324,7 @@ class ImportTestCase(BaseCourseTestCase): self.assertEqual(len(sections), 4) - for i in (2,3): + for i in (2, 3): video = sections[i] # Name should be 'video_{hash}' print "video {0} url_name: {1}".format(i, video.url_name) @@ -379,5 +380,3 @@ class ImportTestCase(BaseCourseTestCase): # and finally... course.metadata['cohort_config'] = {'cohorted': True} self.assertTrue(course.is_cohorted) - - diff --git a/common/lib/xmodule/xmodule/tests/test_progress.py b/common/lib/xmodule/xmodule/tests/test_progress.py index cb011cdc2b..0114ba4ad3 100644 --- a/common/lib/xmodule/xmodule/tests/test_progress.py +++ b/common/lib/xmodule/xmodule/tests/test_progress.py @@ -7,6 +7,7 @@ from xmodule import x_module from . import test_system + class ProgressTest(unittest.TestCase): ''' Test that basic Progress objects work. A Progress represents a fraction between 0 and 1. diff --git a/common/lib/xmodule/xmodule/tests/test_randomize_module.py b/common/lib/xmodule/xmodule/tests/test_randomize_module.py index 6353245f1a..456fd379a5 100644 --- a/common/lib/xmodule/xmodule/tests/test_randomize_module.py +++ b/common/lib/xmodule/xmodule/tests/test_randomize_module.py @@ -52,4 +52,3 @@ class RandomizeModuleTestCase(unittest.TestCase): # TODO: add tests that create a module and check. Passing state is a good way to # check that child access works... - diff --git a/common/lib/xmodule/xmodule/tests/test_self_assessment.py b/common/lib/xmodule/xmodule/tests/test_self_assessment.py index c5fb82e412..78dbb082ac 100644 --- a/common/lib/xmodule/xmodule/tests/test_self_assessment.py +++ b/common/lib/xmodule/xmodule/tests/test_self_assessment.py @@ -8,6 +8,7 @@ from lxml import etree from . import test_system + class SelfAssessmentTest(unittest.TestCase): rubric = ''' @@ -44,7 +45,7 @@ class SelfAssessmentTest(unittest.TestCase): 'prompt': self.prompt, 'max_score': 1, 'display_name': "Name", - 'accept_file_upload' : False, + 'accept_file_upload': False, } self.module = SelfAssessmentModule(test_system, self.location, @@ -74,4 +75,3 @@ class SelfAssessmentTest(unittest.TestCase): self.module.save_answer({'student_answer': 'answer 4'}, test_system) self.module.save_assessment({'assessment': '1'}, test_system) self.assertEqual(self.module.state, self.module.DONE) - diff --git a/common/lib/xmodule/xmodule/tests/test_stringify.py b/common/lib/xmodule/xmodule/tests/test_stringify.py index 29e99bef56..e44b93b0b8 100644 --- a/common/lib/xmodule/xmodule/tests/test_stringify.py +++ b/common/lib/xmodule/xmodule/tests/test_stringify.py @@ -2,6 +2,7 @@ from nose.tools import assert_equals, assert_true, assert_false from lxml import etree from xmodule.stringify import stringify_children + def test_stringify(): text = 'Hi
            there Bruce!
            ' html = '''{0}'''.format(text) @@ -9,6 +10,7 @@ def test_stringify(): out = stringify_children(xml) assert_equals(out, text) + def test_stringify_again(): html = """A voltage source is non-linear!
            diff --git a/common/lib/xmodule/xmodule/timeparse.py b/common/lib/xmodule/xmodule/timeparse.py index 36c0f725e5..1c3a780ad8 100644 --- a/common/lib/xmodule/xmodule/timeparse.py +++ b/common/lib/xmodule/xmodule/timeparse.py @@ -5,6 +5,7 @@ import time TIME_FORMAT = "%Y-%m-%dT%H:%M" + def parse_time(time_str): """ Takes a time string in TIME_FORMAT @@ -15,6 +16,7 @@ def parse_time(time_str): """ return time.strptime(time_str, TIME_FORMAT) + def stringify_time(time_struct): """ Convert a time struct to a string diff --git a/common/lib/xmodule/xmodule/util/decorators.py b/common/lib/xmodule/xmodule/util/decorators.py index 81ab747a3e..0b9b301244 100644 --- a/common/lib/xmodule/xmodule/util/decorators.py +++ b/common/lib/xmodule/xmodule/util/decorators.py @@ -4,8 +4,8 @@ def lazyproperty(fn): """ Use this decorator for lazy generation of properties that are expensive to compute. From http://stackoverflow.com/a/3013910/86828 - - + + Example: class Test(object): @@ -13,7 +13,7 @@ def lazyproperty(fn): def a(self): print 'generating "a"' return range(5) - + Interactive Session: >>> t = Test() >>> t.__dict__ @@ -26,11 +26,11 @@ def lazyproperty(fn): >>> t.a [0, 1, 2, 3, 4] """ - + attr_name = '_lazy_' + fn.__name__ @property def _lazyprop(self): if not hasattr(self, attr_name): setattr(self, attr_name, fn(self)) return getattr(self, attr_name) - return _lazyprop \ No newline at end of file + return _lazyprop diff --git a/common/lib/xmodule/xmodule/vertical_module.py b/common/lib/xmodule/xmodule/vertical_module.py index 14105b41d0..5827ea96a9 100644 --- a/common/lib/xmodule/xmodule/vertical_module.py +++ b/common/lib/xmodule/xmodule/vertical_module.py @@ -47,6 +47,6 @@ class VerticalDescriptor(SequenceDescriptor): js = {'coffee': [resource_string(__name__, 'js/src/vertical/edit.coffee')]} js_module_name = "VerticalDescriptor" - + # TODO (victor): Does this need its own definition_to_xml method? Otherwise it looks # like verticals will get exported as sequentials... diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py index f21cd37a37..6d9715cfd6 100644 --- a/common/lib/xmodule/xmodule/video_module.py +++ b/common/lib/xmodule/xmodule/video_module.py @@ -121,7 +121,7 @@ class VideoModule(XModule): return self.youtube def get_html(self): - if isinstance(modulestore(), XMLModuleStore) : + if isinstance(modulestore(), XMLModuleStore): # VS[compat] # cdodge: filesystem static content support. caption_asset_path = "/static/{0}/subs/".format(self.metadata['data_dir']) diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 0e4e8e0f00..87c085b19a 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -109,16 +109,16 @@ class HTMLSnippet(object): All of these will be loaded onto the page in the CMS """ # cdodge: We've moved the xmodule.coffee script from an outside directory into the xmodule area of common - # this means we need to make sure that all xmodules include this dependency which had been previously implicitly + # this means we need to make sure that all xmodules include this dependency which had been previously implicitly # fulfilled in a different area of code js = cls.js - + if js is None: js = {} if 'coffee' not in js: js['coffee'] = [] - + js['coffee'].append(resource_string(__name__, 'js/src/xmodule.coffee')) return js @@ -538,7 +538,7 @@ class XModuleDescriptor(Plugin, HTMLSnippet, ResourceTemplates): def start(self, value): if isinstance(value, time.struct_time): self.metadata['start'] = stringify_time(value) - + @property def days_early_for_beta(self): """ diff --git a/common/lib/xmodule/xmodule/xml_module.py b/common/lib/xmodule/xmodule/xml_module.py index ed2f6ce921..64c3aabbcc 100644 --- a/common/lib/xmodule/xmodule/xml_module.py +++ b/common/lib/xmodule/xmodule/xml_module.py @@ -16,6 +16,7 @@ edx_xml_parser = etree.XMLParser(dtd_validation=False, load_dtd=False, remove_comments=True, remove_blank_text=True, encoding='utf-8') + def name_to_pathname(name): """ Convert a location name for use in a path: replace ':' with '/'. @@ -23,6 +24,7 @@ def name_to_pathname(name): """ return name.replace(':', '/') + def is_pointer_tag(xml_obj): """ Check if xml_obj is a pointer tag: . @@ -46,6 +48,7 @@ def is_pointer_tag(xml_obj): return len(xml_obj) == 0 and actual_attr == expected_attr and not has_text + def get_metadata_from_xml(xml_object, remove=True): meta = xml_object.find('meta') if meta is None: @@ -58,6 +61,7 @@ def get_metadata_from_xml(xml_object, remove=True): _AttrMapBase = namedtuple('_AttrMap', 'from_xml to_xml') + class AttrMap(_AttrMapBase): """ A class that specifies two functions: @@ -93,16 +97,16 @@ class XmlDescriptor(XModuleDescriptor): metadata_attributes = ('format', 'graceperiod', 'showanswer', 'rerandomize', 'start', 'due', 'graded', 'display_name', 'url_name', 'hide_from_toc', 'ispublic', # if True, then course is listed for all users; see - 'xqa_key', # for xqaa server access - # information about testcenter exams is a dict (of dicts), not a string, - # so it cannot be easily exportable as a course element's attribute. + 'xqa_key', # for xqaa server access + # information about testcenter exams is a dict (of dicts), not a string, + # so it cannot be easily exportable as a course element's attribute. 'testcenter_info', # VS[compat] Remove once unused. 'name', 'slug') - metadata_to_strip = ('data_dir', + metadata_to_strip = ('data_dir', # cdodge: @TODO: We need to figure out a way to export out 'tabs' and 'grading_policy' which is on the course - 'tabs', 'grading_policy', 'is_draft', 'published_by', 'published_date', + 'tabs', 'grading_policy', 'is_draft', 'published_by', 'published_date', 'discussion_blackouts', 'testcenter_info', # VS[compat] -- remove the below attrs once everything is in the CMS 'course', 'org', 'url_name', 'filename') @@ -117,7 +121,7 @@ class XmlDescriptor(XModuleDescriptor): bool_map = AttrMap(to_bool, from_bool) to_int = lambda val: int(val) - from_int = lambda val: str(val) + from_int = lambda val: str(val) int_map = AttrMap(to_int, from_int) xml_attribute_map = { # type conversion: want True/False in python, "true"/"false" in xml @@ -125,7 +129,7 @@ class XmlDescriptor(XModuleDescriptor): 'hide_progress_tab': bool_map, 'allow_anonymous': bool_map, 'allow_anonymous_to_peers': bool_map, - 'weight':int_map + 'weight': int_map } @@ -133,8 +137,8 @@ class XmlDescriptor(XModuleDescriptor): # importing 2012 courses. # A set of metadata key conversions that we want to make metadata_translations = { - 'slug' : 'url_name', - 'name' : 'display_name', + 'slug': 'url_name', + 'name': 'display_name', } @classmethod @@ -230,7 +234,7 @@ class XmlDescriptor(XModuleDescriptor): # TODO (ichuang): remove this after migration # for Fall 2012 LMS migration: keep filename (and unmangled filename) - definition['filename'] = [ filepath, filename ] + definition['filename'] = [filepath, filename] return definition @@ -291,9 +295,9 @@ class XmlDescriptor(XModuleDescriptor): filepath = cls._format_filepath(xml_object.tag, name_to_pathname(url_name)) definition_xml = cls.load_file(filepath, system.resources_fs, location) else: - definition_xml = xml_object # this is just a pointer, not the real definition content + definition_xml = xml_object # this is just a pointer, not the real definition content - definition = cls.load_definition(definition_xml, system, location) # note this removes metadata + definition = cls.load_definition(definition_xml, system, location) # note this removes metadata # VS[compat] -- make Ike's github preview links work in both old and # new file layouts if is_pointer_tag(xml_object): @@ -303,13 +307,13 @@ class XmlDescriptor(XModuleDescriptor): metadata = cls.load_metadata(definition_xml) # move definition metadata into dict - dmdata = definition.get('definition_metadata','') + dmdata = definition.get('definition_metadata', '') if dmdata: metadata['definition_metadata_raw'] = dmdata try: metadata.update(json.loads(dmdata)) except Exception as err: - log.debug('Error %s in loading metadata %s' % (err,dmdata)) + log.debug('Error %s in loading metadata %s' % (err, dmdata)) metadata['definition_metadata_err'] = str(err) # Set/override any metadata specified by policy diff --git a/common/static/js/vendor/mathjax-MathJax-c9db6ac/docs/source/conf.py b/common/static/js/vendor/mathjax-MathJax-c9db6ac/docs/source/conf.py index f0a8013eed..819bff31aa 100644 --- a/common/static/js/vendor/mathjax-MathJax-c9db6ac/docs/source/conf.py +++ b/common/static/js/vendor/mathjax-MathJax-c9db6ac/docs/source/conf.py @@ -11,7 +11,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sys +import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/common/xml_cleanup.py b/common/xml_cleanup.py index 15890fb99e..5f2b527063 100755 --- a/common/xml_cleanup.py +++ b/common/xml_cleanup.py @@ -8,12 +8,16 @@ In particular, the remove-meta option is only intended to be used after pulling using the metadata_to_json management command. """ -import os, fnmatch, re, sys +import os +import fnmatch +import re +import sys from lxml import etree from collections import defaultdict INVALID_CHARS = re.compile(r"[^\w.-]") + def clean(value): """ Return value, made into a form legal for locations @@ -24,6 +28,7 @@ def clean(value): # category -> set of url_names for that category that we've already seen used_names = defaultdict(set) + def clean_unique(category, name): cleaned = clean(name) if cleaned not in used_names[category]: @@ -38,6 +43,7 @@ def clean_unique(category, name): used_names[category].add(cleaned) return cleaned + def cleanup(filepath, remove_meta): # Keys that are exported to the policy file, and so # can be removed from the xml afterward @@ -70,7 +76,7 @@ def cleanup(filepath, remove_meta): print "WARNING: {0} has both slug and url_name".format(node) if ('url_name' in attrs and 'filename' in attrs and - len(attrs)==2 and attrs['url_name'] == attrs['filename']): + len(attrs) == 2 and attrs['url_name'] == attrs['filename']): # This is a pointer tag in disguise. Get rid of the filename. print 'turning {0}.{1} into a pointer tag'.format(node.tag, attrs['url_name']) del attrs['filename'] @@ -108,5 +114,3 @@ def main(args): if __name__ == '__main__': main(sys.argv[1:]) - - diff --git a/lms/djangoapps/certificates/migrations/0008_auto__del_revokedcertificate__del_field_generatedcertificate_name__add.py b/lms/djangoapps/certificates/migrations/0008_auto__del_revokedcertificate__del_field_generatedcertificate_name__add.py index cbec7214c0..872804d286 100644 --- a/lms/djangoapps/certificates/migrations/0008_auto__del_revokedcertificate__del_field_generatedcertificate_name__add.py +++ b/lms/djangoapps/certificates/migrations/0008_auto__del_revokedcertificate__del_field_generatedcertificate_name__add.py @@ -160,4 +160,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['certificates'] \ No newline at end of file + complete_apps = ['certificates'] diff --git a/lms/djangoapps/certificates/migrations/0009_auto__del_field_generatedcertificate_graded_download_url__del_field_ge.py b/lms/djangoapps/certificates/migrations/0009_auto__del_field_generatedcertificate_graded_download_url__del_field_ge.py index 40637452cc..2ff1434314 100644 --- a/lms/djangoapps/certificates/migrations/0009_auto__del_field_generatedcertificate_graded_download_url__del_field_ge.py +++ b/lms/djangoapps/certificates/migrations/0009_auto__del_field_generatedcertificate_graded_download_url__del_field_ge.py @@ -92,4 +92,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['certificates'] \ No newline at end of file + complete_apps = ['certificates'] diff --git a/lms/djangoapps/certificates/migrations/0010_auto__del_field_generatedcertificate_enabled__add_field_generatedcerti.py b/lms/djangoapps/certificates/migrations/0010_auto__del_field_generatedcertificate_enabled__add_field_generatedcerti.py index 5970c96f6b..a41e58cc3b 100644 --- a/lms/djangoapps/certificates/migrations/0010_auto__del_field_generatedcertificate_enabled__add_field_generatedcerti.py +++ b/lms/djangoapps/certificates/migrations/0010_auto__del_field_generatedcertificate_enabled__add_field_generatedcerti.py @@ -78,4 +78,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['certificates'] \ No newline at end of file + complete_apps = ['certificates'] diff --git a/lms/djangoapps/certificates/migrations/0011_auto__del_field_generatedcertificate_certificate_id__add_field_generat.py b/lms/djangoapps/certificates/migrations/0011_auto__del_field_generatedcertificate_certificate_id__add_field_generat.py index 36d6e5d4f3..155839a82f 100644 --- a/lms/djangoapps/certificates/migrations/0011_auto__del_field_generatedcertificate_certificate_id__add_field_generat.py +++ b/lms/djangoapps/certificates/migrations/0011_auto__del_field_generatedcertificate_certificate_id__add_field_generat.py @@ -87,4 +87,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['certificates'] \ No newline at end of file + complete_apps = ['certificates'] diff --git a/lms/djangoapps/certificates/migrations/0012_auto__add_field_generatedcertificate_name__add_field_generatedcertific.py b/lms/djangoapps/certificates/migrations/0012_auto__add_field_generatedcertificate_name__add_field_generatedcertific.py index 4195860ca5..9261654ec8 100644 --- a/lms/djangoapps/certificates/migrations/0012_auto__add_field_generatedcertificate_name__add_field_generatedcertific.py +++ b/lms/djangoapps/certificates/migrations/0012_auto__add_field_generatedcertificate_name__add_field_generatedcertific.py @@ -90,4 +90,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['certificates'] \ No newline at end of file + complete_apps = ['certificates'] diff --git a/lms/djangoapps/certificates/migrations/0013_auto__add_field_generatedcertificate_error_reason.py b/lms/djangoapps/certificates/migrations/0013_auto__add_field_generatedcertificate_error_reason.py index 7f31e6ebd9..6031c8055b 100644 --- a/lms/djangoapps/certificates/migrations/0013_auto__add_field_generatedcertificate_error_reason.py +++ b/lms/djangoapps/certificates/migrations/0013_auto__add_field_generatedcertificate_error_reason.py @@ -75,4 +75,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['certificates'] \ No newline at end of file + complete_apps = ['certificates'] diff --git a/lms/djangoapps/certificates/migrations/0014_adding_whitelist.py b/lms/djangoapps/certificates/migrations/0014_adding_whitelist.py index 1bd4d994cf..0aafea4067 100644 --- a/lms/djangoapps/certificates/migrations/0014_adding_whitelist.py +++ b/lms/djangoapps/certificates/migrations/0014_adding_whitelist.py @@ -86,4 +86,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['certificates'] \ No newline at end of file + complete_apps = ['certificates'] diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 0e68e3cfe7..dc438b805a 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -62,6 +62,7 @@ class CertificateStatuses(object): restricted = 'restricted' error = 'error' + class CertificateWhitelist(models.Model): """ Tracks students who are whitelisted, all users @@ -74,6 +75,7 @@ class CertificateWhitelist(models.Model): course_id = models.CharField(max_length=255, blank=True, default='') whitelist = models.BooleanField(default=0) + class GeneratedCertificate(models.Model): user = models.ForeignKey(User) course_id = models.CharField(max_length=255, blank=True, default='') diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index d926035efd..a7eb4e3c81 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -142,7 +142,7 @@ class XQueueCertInterface(object): """ - VALID_STATUSES = [ status.generating, + VALID_STATUSES = [status.generating, status.unavailable, status.deleted, status.error, status.notpassing] diff --git a/lms/djangoapps/course_wiki/course_nav.py b/lms/djangoapps/course_wiki/course_nav.py index 122f9ebb54..434860a0f7 100644 --- a/lms/djangoapps/course_wiki/course_nav.py +++ b/lms/djangoapps/course_wiki/course_nav.py @@ -11,6 +11,7 @@ from courseware.courses import get_course_with_access IN_COURSE_WIKI_REGEX = r'/courses/(?P[^/]+/[^/]+/[^/]+)/wiki/(?P.*|)$' + class Middleware(object): """ This middleware is to keep the course nav bar above the wiki while @@ -18,68 +19,68 @@ class Middleware(object): If it intercepts a request for /wiki/.. that has a referrer in the form /courses/course_id/... it will redirect the user to the page /courses/course_id/wiki/... - + It is also possible that someone followed a link leading to a course that they don't have access to. In this case, we redirect them to the same page on the regular wiki. - + If we return a redirect, this middleware makes sure that the redirect keeps the student in the course. - + Finally, if the student is in the course viewing a wiki, we change the reverse() function to resolve wiki urls as a course wiki url by setting the _transform_url attribute on wiki.models.reverse. - + Forgive me Father, for I have hacked. """ - + def __init__(self): self.redirected = False - + def process_request(self, request): self.redirected = False wiki_reverse._transform_url = lambda url: url - + referer = request.META.get('HTTP_REFERER') destination = request.path - - + + if request.method == 'GET': new_destination = self.get_redirected_url(request.user, referer, destination) - + if new_destination != destination: # We mark that we generated this redirection, so we don't modify it again self.redirected = True return redirect(new_destination) - + course_match = re.match(IN_COURSE_WIKI_REGEX, destination) if course_match: course_id = course_match.group('course_id') prepend_string = '/courses/' + course_match.group('course_id') wiki_reverse._transform_url = lambda url: prepend_string + url - + return None - - + + def process_response(self, request, response): """ If this is a redirect response going to /wiki/*, then we might need to change it to be a redirect going to /courses/*/wiki*. """ - if not self.redirected and response.status_code == 302: #This is a redirect + if not self.redirected and response.status_code == 302: # This is a redirect referer = request.META.get('HTTP_REFERER') destination_url = response['LOCATION'] destination = urlparse(destination_url).path - + new_destination = self.get_redirected_url(request.user, referer, destination) - + if new_destination != destination: new_url = destination_url.replace(destination, new_destination) response['LOCATION'] = new_url - + return response - - + + def get_redirected_url(self, user, referer, destination): """ Returns None if the destination shouldn't be changed. @@ -87,14 +88,14 @@ class Middleware(object): if not referer: return destination referer_path = urlparse(referer).path - + path_match = re.match(r'^/wiki/(?P.*|)$', destination) if path_match: # We are going to the wiki. Check if we came from a course course_match = re.match(r'/courses/(?P[^/]+/[^/]+/[^/]+)/.*', referer_path) if course_match: course_id = course_match.group('course_id') - + # See if we are able to view the course. If we are, redirect to it try: course = get_course_with_access(user, course_id, 'load') @@ -102,9 +103,9 @@ class Middleware(object): except Http404: # Even though we came from the course, we can't see it. So don't worry about it. pass - + else: - # It is also possible we are going to a course wiki view, but we + # It is also possible we are going to a course wiki view, but we # don't have permission to see the course! course_match = re.match(IN_COURSE_WIKI_REGEX, destination) if course_match: @@ -117,9 +118,9 @@ class Middleware(object): except Http404: # We can't see the course, so redirect to the regular wiki return "/wiki/" + course_match.group('wiki_path') - + return destination - + def context_processor(request): """ @@ -129,21 +130,20 @@ def context_processor(request): then we add 'course' to the context. This allows the course nav bar to be shown. """ - + match = re.match(IN_COURSE_WIKI_REGEX, request.path) if match: course_id = match.group('course_id') - + try: course = get_course_with_access(request.user, course_id, 'load') staff_access = has_access(request.user, course, 'staff') - return {'course' : course, + return {'course': course, 'staff_access': staff_access} except Http404: # We couldn't access the course for whatever reason. It is too late to change # the URL here, so we just leave the course context. The middleware shouldn't # let this happen pass - + return {} - \ No newline at end of file diff --git a/lms/djangoapps/course_wiki/editors.py b/lms/djangoapps/course_wiki/editors.py index c1f5b733ad..2ca8260bfe 100644 --- a/lms/djangoapps/course_wiki/editors.py +++ b/lms/djangoapps/course_wiki/editors.py @@ -14,11 +14,11 @@ class CodeMirrorWidget(forms.Widget): def __init__(self, attrs=None): # The 'rows' and 'cols' attributes are required for HTML correctness. default_attrs = {'class': 'markItUp', - 'rows': '10', 'cols': '40',} + 'rows': '10', 'cols': '40', } if attrs: default_attrs.update(attrs) super(CodeMirrorWidget, self).__init__(default_attrs) - + def render(self, name, value, attrs=None): if value is None: value = '' @@ -34,10 +34,10 @@ class CodeMirrorWidget(forms.Widget): class CodeMirror(BaseEditor): editor_id = 'codemirror' - + def get_admin_widget(self, instance=None): return MarkItUpAdminWidget() - + def get_widget(self, instance=None): return CodeMirrorWidget() @@ -61,4 +61,3 @@ class CodeMirror(BaseEditor): "js/wiki/CodeMirror.init.js", "js/wiki/cheatsheet.js", ) - diff --git a/lms/djangoapps/course_wiki/plugins/markdownedx/__init__.py b/lms/djangoapps/course_wiki/plugins/markdownedx/__init__.py index 8845471eda..53fd3d4d3b 100644 --- a/lms/djangoapps/course_wiki/plugins/markdownedx/__init__.py +++ b/lms/djangoapps/course_wiki/plugins/markdownedx/__init__.py @@ -1,2 +1,2 @@ # Make sure wiki_plugin.py gets run. -from course_wiki.plugins.markdownedx.wiki_plugin import ExtendMarkdownPlugin \ No newline at end of file +from course_wiki.plugins.markdownedx.wiki_plugin import ExtendMarkdownPlugin diff --git a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py index a9148511e3..b14803744b 100644 --- a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py +++ b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py @@ -28,4 +28,3 @@ class MathJaxExtension(markdown.Extension): def makeExtension(configs=None): return MathJaxExtension(configs) - diff --git a/lms/djangoapps/course_wiki/plugins/markdownedx/wiki_plugin.py b/lms/djangoapps/course_wiki/plugins/markdownedx/wiki_plugin.py index ffbe7b0a52..765ee57422 100644 --- a/lms/djangoapps/course_wiki/plugins/markdownedx/wiki_plugin.py +++ b/lms/djangoapps/course_wiki/plugins/markdownedx/wiki_plugin.py @@ -7,15 +7,15 @@ from wiki.core.plugins import registry as plugin_registry from course_wiki.plugins.markdownedx import mdx_circuit, mdx_mathjax, mdx_video + class ExtendMarkdownPlugin(BasePlugin): """ This plugin simply loads all of the markdown extensions we use in edX. """ - + markdown_extensions = [mdx_circuit.CircuitExtension(configs={}), #mdx_image.ImageExtension() , #This one doesn't work. Tries to import simplewiki.settings - mdx_mathjax.MathJaxExtension(configs={}) , + mdx_mathjax.MathJaxExtension(configs={}), mdx_video.VideoExtension(configs={})] plugin_registry.register(ExtendMarkdownPlugin) - diff --git a/lms/djangoapps/course_wiki/tests/__init__.py b/lms/djangoapps/course_wiki/tests/__init__.py index 8b13789179..e69de29bb2 100644 --- a/lms/djangoapps/course_wiki/tests/__init__.py +++ b/lms/djangoapps/course_wiki/tests/__init__.py @@ -1 +0,0 @@ - diff --git a/lms/djangoapps/course_wiki/tests/tests.py b/lms/djangoapps/course_wiki/tests/tests.py index f1c4fa4810..99f138f0bc 100644 --- a/lms/djangoapps/course_wiki/tests/tests.py +++ b/lms/djangoapps/course_wiki/tests/tests.py @@ -13,10 +13,10 @@ class WikiRedirectTestCase(PageLoader): def setUp(self): xmodule.modulestore.django._MODULESTORES = {} courses = modulestore().get_courses() - + def find_course(name): """Assumes the course is present""" - return [c for c in courses if c.location.course==name][0] + return [c for c in courses if c.location.course == name][0] self.full = find_course("full") self.toy = find_course("toy") @@ -29,91 +29,89 @@ class WikiRedirectTestCase(PageLoader): self.create_account('u2', self.instructor, self.password) self.activate_user(self.student) self.activate_user(self.instructor) - - - + + + def test_wiki_redirect(self): """ Test that requesting wiki URLs redirect properly to or out of classes. - - An enrolled in student going from /courses/edX/toy/2012_Fall/progress - to /wiki/some/fake/wiki/page/ will redirect to + + An enrolled in student going from /courses/edX/toy/2012_Fall/progress + to /wiki/some/fake/wiki/page/ will redirect to /courses/edX/toy/2012_Fall/wiki/some/fake/wiki/page/ - + An unenrolled student going to /courses/edX/toy/2012_Fall/wiki/some/fake/wiki/page/ will be redirected to /wiki/some/fake/wiki/page/ - + """ self.login(self.student, self.password) - + self.enroll(self.toy) - - referer = reverse("progress", kwargs={ 'course_id' : self.toy.id }) + + referer = reverse("progress", kwargs={'course_id': self.toy.id}) destination = reverse("wiki:get", kwargs={'path': 'some/fake/wiki/page/'}) - + redirected_to = referer.replace("progress", "wiki/some/fake/wiki/page/") - - resp = self.client.get( destination, HTTP_REFERER=referer) - self.assertEqual(resp.status_code, 302 ) - - self.assertEqual(resp['Location'], 'http://testserver' + redirected_to ) - - + + resp = self.client.get(destination, HTTP_REFERER=referer) + self.assertEqual(resp.status_code, 302) + + self.assertEqual(resp['Location'], 'http://testserver' + redirected_to) + + # Now we test that the student will be redirected away from that page if the course doesn't exist # We do this in the same test because we want to make sure the redirected_to is constructed correctly - + # This is a location like /courses/*/wiki/* , but with an invalid course ID - bad_course_wiki_page = redirected_to.replace( self.toy.location.course, "bad_course" ) - - resp = self.client.get( bad_course_wiki_page, HTTP_REFERER=referer) + bad_course_wiki_page = redirected_to.replace(self.toy.location.course, "bad_course") + + resp = self.client.get(bad_course_wiki_page, HTTP_REFERER=referer) self.assertEqual(resp.status_code, 302) - self.assertEqual(resp['Location'], 'http://testserver' + destination ) - - + self.assertEqual(resp['Location'], 'http://testserver' + destination) + + def create_course_page(self, course): """ Test that loading the course wiki page creates the wiki page. The user must be enrolled in the course to see the page. """ - - course_wiki_home = reverse('course_wiki', kwargs={'course_id' : course.id}) - referer = reverse("progress", kwargs={ 'course_id' : self.toy.id }) - + + course_wiki_home = reverse('course_wiki', kwargs={'course_id': course.id}) + referer = reverse("progress", kwargs={'course_id': self.toy.id}) + resp = self.client.get(course_wiki_home, follow=True, HTTP_REFERER=referer) - + course_wiki_page = referer.replace('progress', 'wiki/' + self.toy.wiki_slug + "/") - + ending_location = resp.redirect_chain[-1][0] ending_status = resp.redirect_chain[-1][1] - - self.assertEquals(ending_location, 'http://testserver' + course_wiki_page ) + + self.assertEquals(ending_location, 'http://testserver' + course_wiki_page) self.assertEquals(resp.status_code, 200) - + self.has_course_navigator(resp) - + def has_course_navigator(self, resp): """ Ensure that the response has the course navigator. """ - self.assertTrue( "course info" in resp.content.lower() ) - self.assertTrue( "courseware" in resp.content.lower() ) - - + self.assertTrue("course info" in resp.content.lower()) + self.assertTrue("courseware" in resp.content.lower()) + + def test_course_navigator(self): """" Test that going from a course page to a wiki page contains the course navigator. """ - + self.login(self.student, self.password) self.enroll(self.toy) self.create_course_page(self.toy) - - - course_wiki_page = reverse('wiki:get', kwargs={'path' : self.toy.wiki_slug + '/'}) - referer = reverse("courseware", kwargs={ 'course_id' : self.toy.id }) - + + + course_wiki_page = reverse('wiki:get', kwargs={'path': self.toy.wiki_slug + '/'}) + referer = reverse("courseware", kwargs={'course_id': self.toy.id}) + resp = self.client.get(course_wiki_page, follow=True, HTTP_REFERER=referer) - + self.has_course_navigator(resp) - - diff --git a/lms/djangoapps/course_wiki/views.py b/lms/djangoapps/course_wiki/views.py index 47112fc1d3..a088f8fc14 100644 --- a/lms/djangoapps/course_wiki/views.py +++ b/lms/djangoapps/course_wiki/views.py @@ -12,6 +12,7 @@ from courseware.courses import get_course_by_id log = logging.getLogger(__name__) + def root_create(request): """ In the edX wiki, we don't show the root_create view. Instead, we @@ -28,7 +29,7 @@ def course_wiki_redirect(request, course_id): example, "/6.002x") to keep things simple. """ course = get_course_by_id(course_id) - + course_slug = course.wiki_slug @@ -43,7 +44,7 @@ def course_wiki_redirect(request, course_id): except: pass - + valid_slug = True if not course_slug: log.exception("This course is improperly configured. The slug cannot be empty.") @@ -54,8 +55,8 @@ def course_wiki_redirect(request, course_id): if not valid_slug: return redirect("wiki:get", path="") - - + + # The wiki needs a Site object created. We make sure it exists here try: site = Site.objects.get_current() @@ -66,30 +67,30 @@ def course_wiki_redirect(request, course_id): new_site.save() if str(new_site.id) != str(settings.SITE_ID): raise ImproperlyConfigured("No site object was created and the SITE_ID doesn't match the newly created one. " + str(new_site.id) + "!=" + str(settings.SITE_ID)) - + try: urlpath = URLPath.get_by_path(course_slug, select_related=True) - - results = list( Article.objects.filter( id = urlpath.article.id ) ) + + results = list(Article.objects.filter(id=urlpath.article.id)) if results: article = results[0] else: article = None - + except (NoRootURL, URLPath.DoesNotExist): # We will create it in the next block urlpath = None article = None - + if not article: # create it root = get_or_create_root() - + if urlpath: # Somehow we got a urlpath without an article. Just delete it and # recerate it. urlpath.delete() - + urlpath = URLPath.create_article( root, course_slug, @@ -105,9 +106,9 @@ def course_wiki_redirect(request, course_id): 'other_read': True, 'other_write': True, }) - + return redirect("wiki:get", path=urlpath.path) - + def get_or_create_root(): """ @@ -121,12 +122,12 @@ def get_or_create_root(): return root except NoRootURL: pass - + starting_content = "\n".join(( "Welcome to the edX Wiki", "===", "Visit a course wiki to add an article.")) - + root = URLPath.create_root(title="Wiki", content=starting_content) article = root.article @@ -136,6 +137,5 @@ def get_or_create_root(): article.other_read = True article.other_write = False article.save() - + return root - diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py index 475a708254..b41d231011 100644 --- a/lms/djangoapps/courseware/access.py +++ b/lms/djangoapps/courseware/access.py @@ -186,9 +186,9 @@ def _get_access_group_name_course_desc(course, action): ''' Return name of group which gives staff access to course. Only understands action = 'staff' and 'instructor' ''' - if action=='staff': + if action == 'staff': return _course_staff_group_name(course.location) - elif action=='instructor': + elif action == 'instructor': return _course_instructor_group_name(course.location) return [] @@ -367,6 +367,7 @@ def _course_staff_group_name(location, course_context=None): return 'staff_%s' % course_id + def course_beta_test_group_name(location): """ Get the name of the beta tester group for a location. Right now, that's @@ -462,6 +463,7 @@ def _adjust_start_date_for_beta_testers(user, descriptor): return descriptor.start + def _has_instructor_access_to_location(user, location, course_context=None): return _has_access_to_location(user, location, 'instructor', course_context) diff --git a/lms/djangoapps/courseware/admin.py b/lms/djangoapps/courseware/admin.py index f7e54d1800..9ef4c1de20 100644 --- a/lms/djangoapps/courseware/admin.py +++ b/lms/djangoapps/courseware/admin.py @@ -11,4 +11,3 @@ admin.site.register(StudentModule) admin.site.register(OfflineComputedGrade) admin.site.register(OfflineComputedGradeLog) - diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index ce29d69784..52346d7583 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -27,6 +27,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError log = logging.getLogger(__name__) + def get_request_for_thread(): """Walk up the stack, return the nearest first argument named "request".""" frame = None @@ -152,7 +153,7 @@ def get_course_about_section(course, section_key): request = get_request_for_thread() loc = course.location._replace(category='about', name=section_key) - course_module = get_module(request.user, request, loc, None, course.id, not_found_ok = True, wrap_xmodule_display = False) + course_module = get_module(request.user, request, loc, None, course.id, not_found_ok=True, wrap_xmodule_display=False) html = '' @@ -190,7 +191,7 @@ def get_course_info_section(request, cache, course, section_key): loc = Location(course.location.tag, course.location.org, course.location.course, 'course_info', section_key) - course_module = get_module(request.user, request, loc, cache, course.id, wrap_xmodule_display = False) + course_module = get_module(request.user, request, loc, cache, course.id, wrap_xmodule_display=False) html = '' if course_module is not None: @@ -259,7 +260,7 @@ def get_courses(user, domain=None): courses = branding.get_visible_courses(domain) courses = [c for c in courses if has_access(user, c, 'see_exists')] - courses = sorted(courses, key=lambda course:course.number) + courses = sorted(courses, key=lambda course: course.number) return courses diff --git a/lms/djangoapps/courseware/features/courses.py b/lms/djangoapps/courseware/features/courses.py index aecaa139ff..9b1316b00d 100644 --- a/lms/djangoapps/courseware/features/courses.py +++ b/lms/djangoapps/courseware/features/courses.py @@ -8,6 +8,8 @@ from logging import getLogger logger = getLogger(__name__) ## support functions + + def get_courses(): ''' Returns dict of lists of courses available, keyed by course.org (ie university). @@ -41,6 +43,7 @@ def get_courses(): # courseware = [ {'chapter_name':c.display_name, 'sections':[s.display_name for s in c.get_children()]} for c in chapters] # return courseware + def get_courseware_with_tabs(course_id): """ Given a course_id (string), return a courseware array of dictionaries for the @@ -101,18 +104,19 @@ def get_courseware_with_tabs(course_id): """ course = get_course_by_id(course_id) - chapters = [ chapter for chapter in course.get_children() if chapter.metadata.get('hide_from_toc','false').lower() != 'true' ] - courseware = [{'chapter_name':c.display_name, - 'sections':[{'section_name':s.display_name, - 'clickable_tab_count':len(s.get_children()) if (type(s)==seq_module.SequenceDescriptor) else 0, - 'tabs':[{'children_count':len(t.get_children()) if (type(t)==vertical_module.VerticalDescriptor) else 0, - 'class':t.__class__.__name__ } - for t in s.get_children() ]} + chapters = [chapter for chapter in course.get_children() if chapter.metadata.get('hide_from_toc', 'false').lower() != 'true'] + courseware = [{'chapter_name': c.display_name, + 'sections': [{'section_name': s.display_name, + 'clickable_tab_count': len(s.get_children()) if (type(s) == seq_module.SequenceDescriptor) else 0, + 'tabs': [{'children_count': len(t.get_children()) if (type(t) == vertical_module.VerticalDescriptor) else 0, + 'class': t.__class__.__name__} + for t in s.get_children()]} for s in c.get_children() if s.metadata.get('hide_from_toc', 'false').lower() != 'true']} - for c in chapters ] + for c in chapters] return courseware + def process_section(element, num_tabs=0): ''' Process section reads through whatever is in 'course-content' and classifies it according to sequence module type. diff --git a/lms/djangoapps/courseware/features/courseware.py b/lms/djangoapps/courseware/features/courseware.py index 05ecd63f4b..7e99cc9f55 100644 --- a/lms/djangoapps/courseware/features/courseware.py +++ b/lms/djangoapps/courseware/features/courseware.py @@ -1,7 +1,8 @@ from lettuce import world, step from lettuce.django import django_url + @step('I visit the courseware URL$') def i_visit_the_course_info_url(step): url = django_url('/courses/MITx/6.002x/2012_Fall/courseware') - world.browser.visit(url) \ No newline at end of file + world.browser.visit(url) diff --git a/lms/djangoapps/courseware/features/courseware_common.py b/lms/djangoapps/courseware/features/courseware_common.py index 8850c88fef..5ee21da906 100644 --- a/lms/djangoapps/courseware/features/courseware_common.py +++ b/lms/djangoapps/courseware/features/courseware_common.py @@ -1,36 +1,43 @@ from lettuce import world, step from lettuce.django import django_url + @step('I click on View Courseware') def i_click_on_view_courseware(step): css = 'p.enter-course' world.browser.find_by_css(css).first.click() + @step('I click on the "([^"]*)" tab$') def i_click_on_the_tab(step, tab): world.browser.find_link_by_text(tab).first.click() world.save_the_html() + @step('I visit the courseware URL$') def i_visit_the_course_info_url(step): url = django_url('/courses/MITx/6.002x/2012_Fall/courseware') world.browser.visit(url) + @step(u'I do not see "([^"]*)" anywhere on the page') def i_do_not_see_text_anywhere_on_the_page(step, text): - assert world.browser.is_text_not_present(text) + assert world.browser.is_text_not_present(text) + @step(u'I am on the dashboard page$') def i_am_on_the_dashboard_page(step): assert world.browser.is_element_present_by_css('section.courses') assert world.browser.url == django_url('/dashboard') + @step('the "([^"]*)" tab is active$') def the_tab_is_active(step, tab): css = '.course-tabs a.active' active_tab = world.browser.find_by_css(css) assert (active_tab.text == tab) + @step('the login dialog is visible$') def login_dialog_visible(step): css = 'form#login_form.login_form' diff --git a/lms/djangoapps/courseware/features/openended.py b/lms/djangoapps/courseware/features/openended.py index d37f9a0fae..0725a051ff 100644 --- a/lms/djangoapps/courseware/features/openended.py +++ b/lms/djangoapps/courseware/features/openended.py @@ -4,29 +4,33 @@ from nose.tools import assert_equals, assert_in from logging import getLogger logger = getLogger(__name__) + @step('I navigate to an openended question$') def navigate_to_an_openended_question(step): world.register_by_course_id('MITx/3.091x/2012_Fall') - world.log_in('robot@edx.org','test') + world.log_in('robot@edx.org', 'test') problem = '/courses/MITx/3.091x/2012_Fall/courseware/Week_10/Polymer_Synthesis/' world.browser.visit(django_url(problem)) tab_css = 'ol#sequence-list > li > a[data-element="5"]' world.browser.find_by_css(tab_css).click() + @step('I navigate to an openended question as staff$') def navigate_to_an_openended_question_as_staff(step): world.register_by_course_id('MITx/3.091x/2012_Fall', True) - world.log_in('robot@edx.org','test') + world.log_in('robot@edx.org', 'test') problem = '/courses/MITx/3.091x/2012_Fall/courseware/Week_10/Polymer_Synthesis/' world.browser.visit(django_url(problem)) tab_css = 'ol#sequence-list > li > a[data-element="5"]' world.browser.find_by_css(tab_css).click() + @step(u'I enter the answer "([^"]*)"$') def enter_the_answer_text(step, text): textarea_css = 'textarea' world.browser.find_by_css(textarea_css).first.fill(text) + @step(u'I submit the answer "([^"]*)"$') def i_submit_the_answer_text(step, text): textarea_css = 'textarea' @@ -34,53 +38,62 @@ def i_submit_the_answer_text(step, text): check_css = 'input.check' world.browser.find_by_css(check_css).click() + @step('I click the link for full output$') def click_full_output_link(step): link_css = 'a.full' world.browser.find_by_css(link_css).first.click() + @step(u'I visit the staff grading page$') def i_visit_the_staff_grading_page(step): # course_u = '/courses/MITx/3.091x/2012_Fall' # sg_url = '%s/staff_grading' % course_u world.browser.click_link_by_text('Instructor') - world.browser.click_link_by_text('Staff grading') + world.browser.click_link_by_text('Staff grading') # world.browser.visit(django_url(sg_url)) + @step(u'I see the grader message "([^"]*)"$') def see_grader_message(step, msg): message_css = 'div.external-grader-message' grader_msg = world.browser.find_by_css(message_css).text assert_in(msg, grader_msg) + @step(u'I see the grader status "([^"]*)"$') def see_the_grader_status(step, status): status_css = 'div.grader-status' grader_status = world.browser.find_by_css(status_css).text assert_equals(status, grader_status) + @step('I see the red X$') def see_the_red_x(step): x_css = 'div.grader-status > span.incorrect' assert world.browser.find_by_css(x_css) + @step(u'I see the grader score "([^"]*)"$') def see_the_grader_score(step, score): score_css = 'div.result-output > p' score_text = world.browser.find_by_css(score_css).text assert_equals(score_text, 'Score: %s' % score) + @step('I see the link for full output$') def see_full_output_link(step): link_css = 'a.full' assert world.browser.find_by_css(link_css) + @step('I see the spelling grading message "([^"]*)"$') def see_spelling_msg(step, msg): spelling_css = 'div.spelling' - spelling_msg = world.browser.find_by_css(spelling_css).text + spelling_msg = world.browser.find_by_css(spelling_css).text assert_equals('Spelling: %s' % msg, spelling_msg) + @step(u'my answer is queued for instructor grading$') def answer_is_queued_for_instructor_grading(step): list_css = 'ul.problem-list > li > a' diff --git a/lms/djangoapps/courseware/features/smart-accordion.py b/lms/djangoapps/courseware/features/smart-accordion.py index 95d3396f57..7c4770d632 100644 --- a/lms/djangoapps/courseware/features/smart-accordion.py +++ b/lms/djangoapps/courseware/features/smart-accordion.py @@ -7,6 +7,7 @@ from courses import * from logging import getLogger logger = getLogger(__name__) + def check_for_errors(): e = world.browser.find_by_css('.outside-app') if len(e) > 0: @@ -14,6 +15,7 @@ def check_for_errors(): else: assert True + @step(u'I verify all the content of each course') def i_verify_all_the_content_of_each_course(step): all_possible_courses = get_courses() @@ -34,11 +36,11 @@ def i_verify_all_the_content_of_each_course(step): check_for_errors() # Get the course. E.g. 'MITx/6.002x/2012_Fall' - current_course = sub('/info','', sub('.*/courses/', '', world.browser.url)) - validate_course(current_course,ids) + current_course = sub('/info', '', sub('.*/courses/', '', world.browser.url)) + validate_course(current_course, ids) world.browser.find_link_by_text('Courseware').click() - assert world.browser.is_element_present_by_id('accordion',wait_time=2) + assert world.browser.is_element_present_by_id('accordion', wait_time=2) check_for_errors() browse_course(current_course) @@ -46,6 +48,7 @@ def i_verify_all_the_content_of_each_course(step): world.browser.find_by_css('.user-link').click() check_for_errors() + def browse_course(course_id): ## count chapters from xml and page and compare @@ -91,7 +94,7 @@ def browse_course(course_id): world.browser.find_by_css('#accordion > nav > div')[chapter_it].find_by_tag('li')[section_it].find_by_tag('a').click() ## sometimes the course-content takes a long time to load - assert world.browser.is_element_present_by_css('.course-content',wait_time=5) + assert world.browser.is_element_present_by_css('.course-content', wait_time=5) ## look for server error div check_for_errors() @@ -108,7 +111,7 @@ def browse_course(course_id): rendered_tabs = 0 num_rendered_tabs = 0 - msg = ('%d tabs expected, %d tabs found, %s - %d - %s' % + msg = ('%d tabs expected, %d tabs found, %s - %d - %s' % (num_tabs, num_rendered_tabs, course_id, section_it, sections[section_it]['section_name'])) #logger.debug(msg) @@ -132,7 +135,7 @@ def browse_course(course_id): tab_class = tabs[tab_it]['class'] if tab_children != 0: rendered_items = world.browser.find_by_css('div#seq_content > section > ol > li > section') - num_rendered_items = len(rendered_items) + num_rendered_items = len(rendered_items) msg = ('%d items expected, %d items found, %s - %d - %s - tab %d' % (tab_children, num_rendered_items, course_id, section_it, sections[section_it]['section_name'], tab_it)) #logger.debug(msg) diff --git a/lms/djangoapps/courseware/grades.py b/lms/djangoapps/courseware/grades.py index f532e6c530..62dd656fe1 100644 --- a/lms/djangoapps/courseware/grades.py +++ b/lms/djangoapps/courseware/grades.py @@ -18,15 +18,17 @@ from models import StudentModule log = logging.getLogger("mitx.courseware") + def yield_module_descendents(module): stack = module.get_display_items() stack.reverse() while len(stack) > 0: next_module = stack.pop() - stack.extend( next_module.get_display_items() ) + stack.extend(next_module.get_display_items()) yield next_module + def yield_dynamic_descriptor_descendents(descriptor, module_creator): """ This returns all of the descendants of a descriptor. If the descriptor @@ -39,15 +41,15 @@ def yield_dynamic_descriptor_descendents(descriptor, module_creator): return module.get_child_descriptors() else: return descriptor.get_children() - - + + stack = [descriptor] while len(stack) > 0: next_descriptor = stack.pop() - stack.extend( get_dynamic_descriptor_children(next_descriptor) ) + stack.extend(get_dynamic_descriptor_children(next_descriptor)) yield next_descriptor - + def yield_problems(request, course, student): """ @@ -88,6 +90,7 @@ def yield_problems(request, course, student): if isinstance(problem, CapaModule): yield problem + def answer_distributions(request, course): """ Given a course_descriptor, compute frequencies of answers for each problem: @@ -150,7 +153,7 @@ def grade(student, request, course, student_module_cache=None, keep_raw_scores=F section_name = section_descriptor.metadata.get('display_name') should_grade_section = False - # If we haven't seen a single problem in the section, we don't have to grade it at all! We can assume 0% + # If we haven't seen a single problem in the section, we don't have to grade it at all! We can assume 0% for moduledescriptor in section['xmoduledescriptors']: if student_module_cache.lookup( course.id, moduledescriptor.category, moduledescriptor.location.url()): @@ -159,20 +162,20 @@ def grade(student, request, course, student_module_cache=None, keep_raw_scores=F if should_grade_section: scores = [] - + def create_module(descriptor): # TODO: We need the request to pass into here. If we could forgo that, our arguments # would be simpler - return get_module(student, request, descriptor.location, + return get_module(student, request, descriptor.location, student_module_cache, course.id) - + for module_descriptor in yield_dynamic_descriptor_descendents(section_descriptor, create_module): - + (correct, total) = get_score(course.id, student, module_descriptor, create_module, student_module_cache) if correct is None and total is None: continue - if settings.GENERATE_PROFILE_SCORES: # for debugging! + if settings.GENERATE_PROFILE_SCORES: # for debugging! if total > 1: correct = random.randrange(max(total - 2, 1), total + 1) else: @@ -208,12 +211,13 @@ def grade(student, request, course, student_module_cache=None, keep_raw_scores=F letter_grade = grade_for_percentage(course.grade_cutoffs, grade_summary['percent']) grade_summary['grade'] = letter_grade - grade_summary['totaled_scores'] = totaled_scores # make this available, eg for instructor download & debugging + grade_summary['totaled_scores'] = totaled_scores # make this available, eg for instructor download & debugging if keep_raw_scores: grade_summary['raw_scores'] = raw_scores # way to get all RAW scores out to instructor # so grader can be double-checked return grade_summary + def grade_for_percentage(grade_cutoffs, percentage): """ Returns a letter grade as defined in grading_policy (e.g. 'A' 'B' 'C' for 6.002x) or None. @@ -225,7 +229,7 @@ def grade_for_percentage(grade_cutoffs, percentage): """ letter_grade = None - + # Possible grades, sorted in descending order of score descending_grades = sorted(grade_cutoffs, key=lambda x: grade_cutoffs[x], reverse=True) for possible_grade in descending_grades: @@ -255,13 +259,13 @@ def progress_summary(student, request, course, student_module_cache): course: A Descriptor containing the course to grade student_module_cache: A StudentModuleCache initialized with all instance_modules for the student - + If the student does not have access to load the course module, this function will return None. - + """ - - + + # TODO: We need the request to pass into here. If we could forgo that, our arguments # would be simpler course_module = get_module(student, request, @@ -270,30 +274,30 @@ def progress_summary(student, request, course, student_module_cache): if not course_module: # This student must not have access to the course. return None - + chapters = [] # Don't include chapters that aren't displayable (e.g. due to error) for chapter_module in course_module.get_display_items(): # Skip if the chapter is hidden - hidden = chapter_module.metadata.get('hide_from_toc','false') + hidden = chapter_module.metadata.get('hide_from_toc', 'false') if hidden.lower() == 'true': continue - + sections = [] for section_module in chapter_module.get_display_items(): # Skip if the section is hidden - hidden = section_module.metadata.get('hide_from_toc','false') + hidden = section_module.metadata.get('hide_from_toc', 'false') if hidden.lower() == 'true': continue - + # Same for sections graded = section_module.metadata.get('graded', False) scores = [] - + module_creator = section_module.system.get_module - + for module_descriptor in yield_dynamic_descriptor_descendents(section_module.descriptor, module_creator): - + course_id = course.id (correct, total) = get_score(course_id, student, module_descriptor, module_creator, student_module_cache) if correct is None and total is None: diff --git a/lms/djangoapps/courseware/management/commands/clean_xml.py b/lms/djangoapps/courseware/management/commands/clean_xml.py index 425dd156c1..1989361b85 100644 --- a/lms/djangoapps/courseware/management/commands/clean_xml.py +++ b/lms/djangoapps/courseware/management/commands/clean_xml.py @@ -12,6 +12,7 @@ from django.core.management.base import BaseCommand from xmodule.modulestore.xml import XMLModuleStore from xmodule.errortracker import make_error_tracker + def traverse_tree(course): '''Load every descriptor in course. Return bool success value.''' queue = [course] diff --git a/lms/djangoapps/courseware/management/commands/metadata_to_json.py b/lms/djangoapps/courseware/management/commands/metadata_to_json.py index 8ef0dee7b3..b80736f693 100644 --- a/lms/djangoapps/courseware/management/commands/metadata_to_json.py +++ b/lms/djangoapps/courseware/management/commands/metadata_to_json.py @@ -14,6 +14,7 @@ from django.core.management.base import BaseCommand from xmodule.modulestore.xml import XMLModuleStore from xmodule.x_module import policy_key + def import_course(course_dir, verbose=True): course_dir = path(course_dir) data_dir = course_dir.dirname() @@ -44,6 +45,7 @@ def import_course(course_dir, verbose=True): return course + def node_metadata(node): # make a copy to_export = ('format', 'display_name', @@ -55,6 +57,7 @@ def node_metadata(node): d = {k: orig[k] for k in to_export if k in orig} return d + def get_metadata(course): d = OrderedDict({}) queue = [course] diff --git a/lms/djangoapps/courseware/migrations/0005_auto__add_offlinecomputedgrade__add_unique_offlinecomputedgrade_user_c.py b/lms/djangoapps/courseware/migrations/0005_auto__add_offlinecomputedgrade__add_unique_offlinecomputedgrade_user_c.py index 674f97cec8..4c21d22937 100644 --- a/lms/djangoapps/courseware/migrations/0005_auto__add_offlinecomputedgrade__add_unique_offlinecomputedgrade_user_c.py +++ b/lms/djangoapps/courseware/migrations/0005_auto__add_offlinecomputedgrade__add_unique_offlinecomputedgrade_user_c.py @@ -114,4 +114,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['courseware'] \ No newline at end of file + complete_apps = ['courseware'] diff --git a/lms/djangoapps/courseware/models.py b/lms/djangoapps/courseware/models.py index bd01318f63..93a4beaafd 100644 --- a/lms/djangoapps/courseware/models.py +++ b/lms/djangoapps/courseware/models.py @@ -113,7 +113,7 @@ class StudentModuleCache(object): descriptor_filter=lambda descriptor: True, select_for_update=False): """ - obtain and return cache for descriptor descendents (ie children) AND modules required by the descriptor, + obtain and return cache for descriptor descendents (ie children) AND modules required by the descriptor, but which are not children of the module course_id: the course in the context of which we want StudentModules. @@ -212,7 +212,7 @@ class OfflineComputedGradeLog(models.Model): course_id = models.CharField(max_length=255, db_index=True) created = models.DateTimeField(auto_now_add=True, null=True, db_index=True) - seconds = models.IntegerField(default=0) # seconds elapsed for computation + seconds = models.IntegerField(default=0) # seconds elapsed for computation nstudents = models.IntegerField(default=0) def __unicode__(self): diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index b19796b357..ded84a971e 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -91,7 +91,7 @@ def toc_for_course(user, request, course, active_chapter, active_section): chapters = list() for chapter in course_module.get_display_items(): - hide_from_toc = chapter.metadata.get('hide_from_toc','false').lower() == 'true' + hide_from_toc = chapter.metadata.get('hide_from_toc', 'false').lower() == 'true' if hide_from_toc: continue @@ -166,6 +166,7 @@ def get_module_for_descriptor(user, request, descriptor, student_module_cache, c return _get_module(user, request, descriptor, student_module_cache, course_id, position=position, wrap_xmodule_display=wrap_xmodule_display) + def _get_module(user, request, descriptor, student_module_cache, course_id, position=None, wrap_xmodule_display=True): """ @@ -287,7 +288,7 @@ def _get_module(user, request, descriptor, student_module_cache, course_id, module.get_html = replace_static_urls( _get_html, module.metadata.get('data_dir', ''), - course_namespace = module.location._replace(category=None, name=None)) + course_namespace=module.location._replace(category=None, name=None)) # Allow URLs of the form '/course/' refer to the root of multicourse directory # hierarchy of this course @@ -300,6 +301,8 @@ def _get_module(user, request, descriptor, student_module_cache, course_id, return module # TODO (vshnayder): Rename this? It's very confusing. + + def get_instance_module(course_id, user, module, student_module_cache): """ Returns the StudentModule specific to this module for this student, @@ -329,6 +332,7 @@ def get_instance_module(course_id, user, module, student_module_cache): else: return None + def get_shared_instance_module(course_id, user, module, student_module_cache): """ Return shared_module is a StudentModule specific to all modules with the same @@ -359,6 +363,7 @@ def get_shared_instance_module(course_id, user, module, student_module_cache): else: return None + @csrf_exempt def xqueue_callback(request, course_id, userid, id, dispatch): ''' @@ -415,8 +420,8 @@ def xqueue_callback(request, course_id, userid, id, dispatch): instance_module.save() #Bin score into range and increment stats - score_bucket=get_score_bucket(instance_module.grade, instance_module.max_grade) - org, course_num, run=course_id.split("/") + score_bucket = get_score_bucket(instance_module.grade, instance_module.max_grade) + org, course_num, run = course_id.split("/") statsd.increment("lms.courseware.question_answered", tags=["org:{0}".format(org), "course:{0}".format(course_num), @@ -456,9 +461,9 @@ def modx_dispatch(request, dispatch, location, course_id): return HttpResponse(json.dumps({'success': too_many_files_msg})) for inputfile in inputfiles: - if inputfile.size > settings.STUDENT_FILEUPLOAD_MAX_SIZE: # Bytes + if inputfile.size > settings.STUDENT_FILEUPLOAD_MAX_SIZE: # Bytes file_too_big_msg = 'Submission aborted! Your file "%s" is too large (max size: %d MB)' %\ - (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE/(1000**2)) + (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE / (1000 ** 2)) return HttpResponse(json.dumps({'success': file_too_big_msg})) p[fileinput_id] = inputfiles @@ -499,7 +504,7 @@ def modx_dispatch(request, dispatch, location, course_id): # Don't track state for anonymous users (who don't have student modules) if instance_module is not None: instance_module.state = instance.get_instance_state() - instance_module.max_grade=instance.max_score() + instance_module.max_grade = instance.max_score() if instance.get_score(): instance_module.grade = instance.get_score()['score'] if (instance_module.grade != oldgrade or @@ -508,8 +513,8 @@ def modx_dispatch(request, dispatch, location, course_id): instance_module.save() #Bin score into range and increment stats - score_bucket=get_score_bucket(instance_module.grade, instance_module.max_grade) - org, course_num, run=course_id.split("/") + score_bucket = get_score_bucket(instance_module.grade, instance_module.max_grade) + org, course_num, run = course_id.split("/") statsd.increment("lms.courseware.question_answered", tags=["org:{0}".format(org), "course:{0}".format(course_num), @@ -526,6 +531,7 @@ def modx_dispatch(request, dispatch, location, course_id): # Return whatever the module wanted to return to the client/caller return HttpResponse(ajax_return) + def preview_chemcalc(request): """ Render an html preview of a chemical formula or equation. The fact that @@ -544,7 +550,7 @@ def preview_chemcalc(request): raise Http404 result = {'preview': '', - 'error': '' } + 'error': ''} formula = request.GET.get('formula') if formula is None: result['error'] = "No formula specified." @@ -563,17 +569,15 @@ def preview_chemcalc(request): return HttpResponse(json.dumps(result)) -def get_score_bucket(grade,max_grade): +def get_score_bucket(grade, max_grade): """ Function to split arbitrary score ranges into 3 buckets. Used with statsd tracking. """ - score_bucket="incorrect" - if(grade>0 and grade 0 and grade < max_grade): + score_bucket = "partial" + elif(grade == max_grade): + score_bucket = "correct" return score_bucket - - diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 4f5a881d97..a47141b183 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -33,6 +33,7 @@ from open_ended_grading import open_ended_notifications log = logging.getLogger(__name__) + class InvalidTabsException(Exception): """ A complaint about invalid tabs. @@ -41,6 +42,7 @@ class InvalidTabsException(Exception): CourseTabBase = namedtuple('CourseTab', 'name link is_active has_img img') + def CourseTab(name, link, is_active, has_img=False, img=""): return CourseTabBase(name, link, is_active, has_img, img) @@ -64,22 +66,26 @@ def _courseware(tab, user, course, active_page): link = reverse('courseware', args=[course.id]) return [CourseTab('Courseware', link, active_page == "courseware")] + def _course_info(tab, user, course, active_page): link = reverse('info', args=[course.id]) return [CourseTab(tab['name'], link, active_page == "info")] + def _progress(tab, user, course, active_page): if user.is_authenticated(): link = reverse('progress', args=[course.id]) return [CourseTab(tab['name'], link, active_page == "progress")] return [] + def _wiki(tab, user, course, active_page): if settings.WIKI_ENABLED: link = reverse('course_wiki', args=[course.id]) return [CourseTab(tab['name'], link, active_page == 'wiki')] return [] + def _discussion(tab, user, course, active_page): """ This tab format only supports the new Berkeley discussion forums. @@ -87,17 +93,19 @@ def _discussion(tab, user, course, active_page): if settings.MITX_FEATURES.get('ENABLE_DISCUSSION_SERVICE'): link = reverse('django_comment_client.forum.views.forum_form_discussion', args=[course.id]) - return [CourseTab(tab['name'], link, active_page=='discussion')] + return [CourseTab(tab['name'], link, active_page == 'discussion')] return [] + def _external_link(tab, user, course, active_page): # external links are never active return [CourseTab(tab['name'], tab['link'], False)] + def _static_tab(tab, user, course, active_page): link = reverse('static_tab', args=[course.id, tab['url_slug']]) active_str = 'static_tab_{0}'.format(tab['url_slug']) - return [CourseTab(tab['name'], link, active_page==active_str)] + return [CourseTab(tab['name'], link, active_page == active_str)] def _textbooks(tab, user, course, active_page): @@ -107,7 +115,7 @@ def _textbooks(tab, user, course, active_page): if user.is_authenticated() and settings.MITX_FEATURES.get('ENABLE_TEXTBOOK'): # since there can be more than one textbook, active_page is e.g. "book/0". return [CourseTab(textbook.title, reverse('book', args=[course.id, index]), - active_page=="textbook/{0}".format(index)) + active_page == "textbook/{0}".format(index)) for index, textbook in enumerate(course.textbooks)] return [] @@ -126,6 +134,7 @@ def _staff_grading(tab, user, course, active_page): return tab return [] + def _peer_grading(tab, user, course, active_page): if user.is_authenticated(): @@ -140,6 +149,7 @@ def _peer_grading(tab, user, course, active_page): return tab return [] + def _combined_open_ended_grading(tab, user, course, active_page): if user.is_authenticated(): link = reverse('open_ended_notifications', args=[course.id]) @@ -171,6 +181,7 @@ def key_checker(expected_keys): need_name = key_checker(['name']) + def null_validator(d): """ Don't check anything--use for tabs that don't need any params. (e.g. textbook) @@ -235,7 +246,7 @@ def get_course_tabs(user, course, active_page): """ Return the tabs to show a particular user, as a list of CourseTab items. """ - if not hasattr(course,'tabs') or not course.tabs: + if not hasattr(course, 'tabs') or not course.tabs: return get_default_tabs(user, course, active_page) # TODO (vshnayder): There needs to be a place to call this right after course @@ -269,7 +280,7 @@ def get_default_tabs(user, course, active_page): if hasattr(course, 'syllabus_present') and course.syllabus_present: link = reverse('syllabus', args=[course.id]) - tabs.append(CourseTab('Syllabus', link, active_page=='syllabus')) + tabs.append(CourseTab('Syllabus', link, active_page == 'syllabus')) tabs.extend(_textbooks({}, user, course, active_page)) @@ -290,10 +301,11 @@ def get_default_tabs(user, course, active_page): if has_access(user, course, 'staff'): link = reverse('instructor_dashboard', args=[course.id]) - tabs.append(CourseTab('Instructor', link, active_page=='instructor')) + tabs.append(CourseTab('Instructor', link, active_page == 'instructor')) return tabs + def get_static_tab_by_slug(course, tab_slug): """ Look for a tab with type 'static_tab' and the specified 'tab_slug'. Returns @@ -308,6 +320,7 @@ def get_static_tab_by_slug(course, tab_slug): return None + def get_static_tab_contents(request, cache, course, tab): loc = Location(course.location.tag, course.location.org, course.location.course, 'static_tab', tab['url_slug']) diff --git a/lms/djangoapps/courseware/tests/__init__.py b/lms/djangoapps/courseware/tests/__init__.py index 8b13789179..e69de29bb2 100644 --- a/lms/djangoapps/courseware/tests/__init__.py +++ b/lms/djangoapps/courseware/tests/__init__.py @@ -1 +0,0 @@ - diff --git a/lms/djangoapps/courseware/tests/factories.py b/lms/djangoapps/courseware/tests/factories.py index 6950e28565..a84b2b8475 100644 --- a/lms/djangoapps/courseware/tests/factories.py +++ b/lms/djangoapps/courseware/tests/factories.py @@ -5,6 +5,7 @@ from django.contrib.auth.models import Group from datetime import datetime import uuid + class UserProfileFactory(factory.Factory): FACTORY_FOR = UserProfile @@ -12,12 +13,14 @@ class UserProfileFactory(factory.Factory): name = 'Robot Studio' courseware = 'course.xml' + class RegistrationFactory(factory.Factory): FACTORY_FOR = Registration user = None activation_key = uuid.uuid4().hex + class UserFactory(factory.Factory): FACTORY_FOR = User @@ -32,11 +35,13 @@ class UserFactory(factory.Factory): last_login = datetime.now() date_joined = datetime.now() + class GroupFactory(factory.Factory): FACTORY_FOR = Group name = 'test_group' + class CourseEnrollmentAllowedFactory(factory.Factory): FACTORY_FOR = CourseEnrollmentAllowed diff --git a/lms/djangoapps/courseware/tests/test_access.py b/lms/djangoapps/courseware/tests/test_access.py index ed9335d382..c0b28e7803 100644 --- a/lms/djangoapps/courseware/tests/test_access.py +++ b/lms/djangoapps/courseware/tests/test_access.py @@ -3,10 +3,11 @@ import time from mock import Mock from django.test import TestCase -from xmodule.modulestore import Location +from xmodule.modulestore import Location from factories import CourseEnrollmentAllowedFactory import courseware.access as access + class AccessTestCase(TestCase): def test__has_global_staff_access(self): u = Mock(is_staff=False) @@ -44,13 +45,13 @@ class AccessTestCase(TestCase): self.assertTrue(access._has_access_to_location(u, location, 'instructor', None)) - # A user does not have staff access if they are + # A user does not have staff access if they are # not in either the staff or the the instructor group g.name = 'student_only' self.assertFalse(access._has_access_to_location(u, location, 'staff', None)) - # A user does not have instructor access if they are + # A user does not have instructor access if they are # not in the instructor group g.name = 'student_only' self.assertFalse(access._has_access_to_location(u, location, @@ -69,7 +70,7 @@ class AccessTestCase(TestCase): # TODO: override DISABLE_START_DATES and test the start date branch of the method u = Mock() d = Mock() - d.start = time.gmtime(time.time() - 86400) # make sure the start time is in the past + d.start = time.gmtime(time.time() - 86400) # make sure the start time is in the past # Always returns true because DISABLE_START_DATES is set in test.py self.assertTrue(access._has_access_descriptor(u, d, 'load')) @@ -105,5 +106,5 @@ class AccessTestCase(TestCase): c.metadata.get = 'is_public' self.assertTrue(access._has_access_course_desc(u, c, 'enroll')) - # TODO: + # TODO: # Non-staff cannot enroll outside the open enrollment period if not specifically allowed diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py index 6c41cbac14..efa5ad823e 100644 --- a/lms/djangoapps/courseware/tests/tests.py +++ b/lms/djangoapps/courseware/tests/tests.py @@ -31,6 +31,7 @@ from xmodule.modulestore.xml_importer import import_from_xml from xmodule.modulestore.xml import XMLModuleStore from xmodule.timeparse import stringify_time + def parse_json(response): """Parse response, which is assumed to be json""" return json.loads(response.content) @@ -49,6 +50,7 @@ def registration(email): # jump_to works with the xmlmodulestore or we have an even better solution # NOTE: this means this test requires mongo to be running. + def mongo_store_config(data_dir): return { 'default': { @@ -64,6 +66,7 @@ def mongo_store_config(data_dir): } } + def draft_mongo_store_config(data_dir): return { 'default': { @@ -79,6 +82,7 @@ def draft_mongo_store_config(data_dir): } } + def xml_store_config(data_dir): return { 'default': { @@ -95,6 +99,7 @@ TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) TEST_DATA_MONGO_MODULESTORE = mongo_store_config(TEST_DATA_DIR) TEST_DATA_DRAFT_MONGO_MODULESTORE = draft_mongo_store_config(TEST_DATA_DIR) + class ActivateLoginTestCase(TestCase): '''Check that we can activate and log in''' @@ -286,13 +291,13 @@ class PageLoader(ActivateLoginTestCase): all_ok = False num_bad += 1 elif descriptor.location.category == 'static_tab': - resp = self.client.get(reverse('static_tab', kwargs={'course_id': course_id, 'tab_slug' : descriptor.location.name})) + resp = self.client.get(reverse('static_tab', kwargs={'course_id': course_id, 'tab_slug': descriptor.location.name})) msg = str(resp.status_code) if resp.status_code != 200: msg = "ERROR " + msg all_ok = False - num_bad += 1 + num_bad += 1 elif descriptor.location.category == 'course_info': resp = self.client.get(reverse('info', kwargs={'course_id': course_id})) msg = str(resp.status_code) @@ -300,7 +305,7 @@ class PageLoader(ActivateLoginTestCase): if resp.status_code != 200: msg = "ERROR " + msg all_ok = False - num_bad += 1 + num_bad += 1 elif descriptor.location.category == 'custom_tag_template': pass else: @@ -321,7 +326,7 @@ class PageLoader(ActivateLoginTestCase): # check content to make sure there were no rendering failures content = resp.content - if content.find("this module is temporarily unavailable")>=0: + if content.find("this module is temporarily unavailable") >= 0: msg = "ERROR unavailable module " all_ok = False num_bad += 1 @@ -335,7 +340,7 @@ class PageLoader(ActivateLoginTestCase): self.assertTrue(all_ok) # fail fast print "{0}/{1} good".format(n - num_bad, n) - log.info( "{0}/{1} good".format(n - num_bad, n)) + log.info("{0}/{1} good".format(n - num_bad, n)) self.assertTrue(all_ok) @@ -347,7 +352,7 @@ class TestCoursesLoadTestCase_XmlModulestore(PageLoader): def setUp(self): ActivateLoginTestCase.setUp(self) xmodule.modulestore.django._MODULESTORES = {} - + def test_toy_course_loads(self): module_store = XMLModuleStore( TEST_DATA_DIR, @@ -376,7 +381,7 @@ class TestCoursesLoadTestCase_MongoModulestore(PageLoader): ActivateLoginTestCase.setUp(self) xmodule.modulestore.django._MODULESTORES = {} modulestore().collection.drop() - + def test_toy_course_loads(self): module_store = modulestore() import_from_xml(module_store, TEST_DATA_DIR, ['toy']) @@ -431,7 +436,7 @@ class TestNavigation(PageLoader): # Now we directly navigate to a section in a different chapter self.check_for_get_code(200, reverse('courseware_section', kwargs={'course_id': self.toy.id, - 'chapter':'secret:magic', 'section':'toyvideo'})) + 'chapter': 'secret:magic', 'section': 'toyvideo'})) # And now hitting the courseware tab should redirect to 'secret:magic' resp = self.client.get(reverse('courseware', kwargs={'course_id': self.toy.id})) @@ -565,7 +570,7 @@ class TestViewAuth(PageLoader): """Actually do the test, relying on settings to be right.""" # Make courses start in the future - tomorrow = time.time() + 24*3600 + tomorrow = time.time() + 24 * 3600 self.toy.metadata['start'] = stringify_time(time.gmtime(tomorrow)) self.full.metadata['start'] = stringify_time(time.gmtime(tomorrow)) @@ -603,7 +608,7 @@ class TestViewAuth(PageLoader): def instructor_urls(course): """list of urls that only instructors/staff should be able to see""" - urls = reverse_urls(['instructor_dashboard','gradebook','grade_summary'], + urls = reverse_urls(['instructor_dashboard', 'gradebook', 'grade_summary'], course) return urls @@ -770,7 +775,7 @@ class TestCourseGrader(PageLoader): def find_course(course_id): """Assumes the course is present""" - return [c for c in courses if c.id==course_id][0] + return [c for c in courses if c.id == course_id][0] self.graded_course = find_course("edX/graded/2012_Fall") @@ -825,17 +830,17 @@ class TestCourseGrader(PageLoader): modx_url = reverse('modx_dispatch', kwargs={ - 'course_id' : self.graded_course.id, - 'location' : problem_location, - 'dispatch' : 'problem_check', } + 'course_id': self.graded_course.id, + 'location': problem_location, + 'dispatch': 'problem_check', } ) resp = self.client.post(modx_url, { 'input_i4x-edX-graded-problem-{0}_2_1'.format(problem_url_name): responses[0], 'input_i4x-edX-graded-problem-{0}_2_2'.format(problem_url_name): responses[1], }) - print "modx_url" , modx_url, "responses" , responses - print "resp" , resp + print "modx_url", modx_url, "responses", responses + print "resp", resp return resp @@ -847,9 +852,9 @@ class TestCourseGrader(PageLoader): modx_url = reverse('modx_dispatch', kwargs={ - 'course_id' : self.graded_course.id, - 'location' : problem_location, - 'dispatch' : 'problem_reset', } + 'course_id': self.graded_course.id, + 'location': problem_location, + 'dispatch': 'problem_reset', } ) resp = self.client.post(modx_url) @@ -873,7 +878,7 @@ class TestCourseGrader(PageLoader): # Only get half of the first problem correct self.submit_question_answer('H1P1', ['Correct', 'Incorrect']) self.check_grade_percent(0.06) - self.assertEqual(earned_hw_scores(), [1.0, 0, 0]) # Order matters + self.assertEqual(earned_hw_scores(), [1.0, 0, 0]) # Order matters self.assertEqual(score_for_hw('Homework1'), [1.0, 0.0]) # Get both parts of the first problem correct @@ -905,14 +910,13 @@ class TestCourseGrader(PageLoader): # Third homework self.submit_question_answer('H3P1', ['Correct', 'Correct']) - self.check_grade_percent(0.42) # Score didn't change + self.check_grade_percent(0.42) # Score didn't change self.assertEqual(earned_hw_scores(), [4.0, 4.0, 2.0]) self.submit_question_answer('H3P2', ['Correct', 'Correct']) - self.check_grade_percent(0.5) # Now homework2 dropped. Score changes + self.check_grade_percent(0.5) # Now homework2 dropped. Score changes self.assertEqual(earned_hw_scores(), [4.0, 4.0, 4.0]) # Now we answer the final question (worth half of the grade) self.submit_question_answer('FinalQuestion', ['Correct', 'Correct']) - self.check_grade_percent(1.0) # Hooray! We got 100% - + self.check_grade_percent(1.0) # Hooray! We got 100% diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index 5d65d7c632..02a4b5f5f2 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -137,6 +137,7 @@ def redirect_to_course_position(course_module, first_time): 'chapter': chapter.url_name, 'section': section.url_name})) + def save_child_position(seq_module, child_name, instance_module): """ child_name: url_name of the child @@ -152,6 +153,7 @@ def save_child_position(seq_module, child_name, instance_module): instance_module.state = seq_module.get_instance_state() instance_module.save() + @login_required @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) @@ -184,7 +186,7 @@ def index(request, course_id, chapter=None, section=None, registered = registered_for_course(course, request.user) if not registered: # TODO (vshnayder): do course instructors need to be registered to see course? - log.debug('User %s tried to view course %s but is not enrolled' % (request.user,course.location.url())) + log.debug('User %s tried to view course %s but is not enrolled' % (request.user, course.location.url())) return redirect(reverse('about_course', args=[course.id])) try: @@ -212,7 +214,7 @@ def index(request, course_id, chapter=None, section=None, 'init': '', 'content': '', 'staff_access': staff_access, - 'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER','http://xqa:server@content-qa.mitx.mit.edu/xqa') + 'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://xqa:server@content-qa.mitx.mit.edu/xqa') } chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter) @@ -288,7 +290,7 @@ def index(request, course_id, chapter=None, section=None, try: result = render_to_response('courseware/courseware-error.html', {'staff_access': staff_access, - 'course' : course}) + 'course': course}) except: # Let the exception propagate, relying on global config to at # at least return a nice error message @@ -297,6 +299,7 @@ def index(request, course_id, chapter=None, section=None, return result + @ensure_csrf_cookie def jump_to(request, course_id, location): ''' @@ -333,6 +336,7 @@ def jump_to(request, course_id, location): else: return redirect('courseware_position', course_id=course_id, chapter=chapter, section=section, position=position) + @ensure_csrf_cookie def course_info(request, course_id): """ @@ -343,9 +347,10 @@ def course_info(request, course_id): course = get_course_with_access(request.user, course_id, 'load') staff_access = has_access(request.user, course, 'staff') - return render_to_response('courseware/info.html', {'request' : request, 'course_id' : course_id, 'cache' : None, + return render_to_response('courseware/info.html', {'request': request, 'course_id': course_id, 'cache': None, 'course': course, 'staff_access': staff_access}) + @ensure_csrf_cookie def static_tab(request, course_id, tab_slug): """ @@ -368,9 +373,11 @@ def static_tab(request, course_id, tab_slug): {'course': course, 'tab': tab, 'tab_contents': contents, - 'staff_access': staff_access,}) + 'staff_access': staff_access, }) # TODO arjun: remove when custom tabs in place, see courseware/syllabus.py + + @ensure_csrf_cookie def syllabus(request, course_id): """ @@ -382,7 +389,7 @@ def syllabus(request, course_id): staff_access = has_access(request.user, course, 'staff') return render_to_response('courseware/syllabus.html', {'course': course, - 'staff_access': staff_access,}) + 'staff_access': staff_access, }) def registered_for_course(course, user): @@ -394,6 +401,7 @@ def registered_for_course(course, user): else: return False + @ensure_csrf_cookie @cache_if_anonymous def course_about(request, course_id): @@ -412,7 +420,7 @@ def course_about(request, course_id): {'course': course, 'registered': registered, 'course_target': course_target, - 'show_courseware_link' : show_courseware_link}) + 'show_courseware_link': show_courseware_link}) @ensure_csrf_cookie @@ -425,6 +433,7 @@ def static_university_profile(request, org_id): context = dict(courses=[], org_id=org_id) return render_to_response(template_file, context) + @ensure_csrf_cookie @cache_if_anonymous def university_profile(request, org_id): @@ -446,6 +455,7 @@ def university_profile(request, org_id): return render_to_response(template_file, context) + def render_notifications(request, course, notifications): context = { 'notifications': notifications, @@ -454,6 +464,7 @@ def render_notifications(request, course, notifications): } return render_to_string('courseware/notifications.html', context) + @login_required def news(request, course_id): course = get_course_with_access(request.user, course_id, 'load') @@ -467,6 +478,7 @@ def news(request, course_id): return render_to_response('courseware/news.html', context) + @login_required @cache_control(no_cache=True, no_store=True, must_revalidate=True) def progress(request, course_id, student_id=None): diff --git a/lms/djangoapps/dashboard/views.py b/lms/djangoapps/dashboard/views.py index 964b3fac4a..f5929f241b 100644 --- a/lms/djangoapps/dashboard/views.py +++ b/lms/djangoapps/dashboard/views.py @@ -3,6 +3,7 @@ import json from datetime import datetime from django.http import HttpResponse, Http404 + def dictfetchall(cursor): '''Returns all rows from a cursor as a dict. Borrowed from Django documentation''' @@ -12,23 +13,24 @@ def dictfetchall(cursor): for row in cursor.fetchall() ] + def dashboard(request): """ Quick hack to show staff enrollment numbers. This should be replaced with a real dashboard later. This version is a short-term - bandaid for the next couple weeks. + bandaid for the next couple weeks. """ if not request.user.is_staff: raise Http404 - queries=[] + queries = [] queries.append("select count(user_id) as students, course_id from student_courseenrollment group by course_id order by students desc;") queries.append("select count(distinct user_id) as unique_students from student_courseenrollment;") queries.append("select registrations, count(registrations) from (select count(user_id) as registrations from student_courseenrollment group by user_id) as registrations_per_user group by registrations;") - + from django.db import connection cursor = connection.cursor() - results =[] + results = [] for query in queries: cursor.execute(query) diff --git a/lms/djangoapps/django_comment_client/base/urls.py b/lms/djangoapps/django_comment_client/base/urls.py index 23f2afa037..d8fd4927fb 100644 --- a/lms/djangoapps/django_comment_client/base/urls.py +++ b/lms/djangoapps/django_comment_client/base/urls.py @@ -23,7 +23,7 @@ urlpatterns = patterns('django_comment_client.base.views', url(r'comments/(?P[\w\-]+)/upvote$', 'vote_for_comment', {'value': 'up'}, name='upvote_comment'), url(r'comments/(?P[\w\-]+)/downvote$', 'vote_for_comment', {'value': 'down'}, name='downvote_comment'), url(r'comments/(?P[\w\-]+)/unvote$', 'undo_vote_for_comment', name='undo_vote_for_comment'), - + url(r'^(?P[\w\-.]+)/threads/create$', 'create_thread', name='create_thread'), # TODO should we search within the board? url(r'^(?P[\w\-.]+)/threads/search_similar$', 'search_similar_threads', name='search_similar_threads'), diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index 777c7bafce..7ca00cb37c 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -30,6 +30,7 @@ from django_comment_client.models import Role log = logging.getLogger(__name__) + def permitted(fn): @functools.wraps(fn) def wrapper(request, *args, **kwargs): @@ -47,6 +48,7 @@ def permitted(fn): return JsonError("unauthorized", status=401) return wrapper + def ajax_content_response(request, course_id, content, template_name): context = { 'course_id': course_id, @@ -82,11 +84,11 @@ def create_thread(request, course_id, commentable_id): thread = cc.Thread(**extract(post, ['body', 'title', 'tags'])) thread.update_attributes(**{ - 'anonymous' : anonymous, - 'anonymous_to_peers' : anonymous_to_peers, - 'commentable_id' : commentable_id, - 'course_id' : course_id, - 'user_id' : request.user.id, + 'anonymous': anonymous, + 'anonymous_to_peers': anonymous_to_peers, + 'commentable_id': commentable_id, + 'course_id': course_id, + 'user_id': request.user.id, }) @@ -118,6 +120,7 @@ def create_thread(request, course_id, commentable_id): else: return JsonResponse(utils.safe_content(data)) + @require_POST @login_required @permitted @@ -130,6 +133,7 @@ def update_thread(request, course_id, thread_id): else: return JsonResponse(utils.safe_content(thread.to_dict())) + def _create_comment(request, course_id, thread_id=None, parent_id=None): post = request.POST comment = cc.Comment(**extract(post, ['body'])) @@ -146,12 +150,12 @@ def _create_comment(request, course_id, thread_id=None, parent_id=None): anonymous_to_peers = False comment.update_attributes(**{ - 'anonymous' : anonymous, - 'anonymous_to_peers' : anonymous_to_peers, - 'user_id' : request.user.id, - 'course_id' : course_id, - 'thread_id' : thread_id, - 'parent_id' : parent_id, + 'anonymous': anonymous, + 'anonymous_to_peers': anonymous_to_peers, + 'user_id': request.user.id, + 'course_id': course_id, + 'thread_id': thread_id, + 'parent_id': parent_id, }) comment.save() if post.get('auto_subscribe', 'false').lower() == 'true': @@ -162,6 +166,7 @@ def _create_comment(request, course_id, thread_id=None, parent_id=None): else: return JsonResponse(utils.safe_content(comment.to_dict())) + @require_POST @login_required @permitted @@ -171,6 +176,7 @@ def create_comment(request, course_id, thread_id): return JsonError("Comment level too deep") return _create_comment(request, course_id, thread_id=thread_id) + @require_POST @login_required @permitted @@ -179,6 +185,7 @@ def delete_thread(request, course_id, thread_id): thread.delete() return JsonResponse(utils.safe_content(thread.to_dict())) + @require_POST @login_required @permitted @@ -191,6 +198,7 @@ def update_comment(request, course_id, comment_id): else: return JsonResponse(utils.safe_content(comment.to_dict())) + @require_POST @login_required @permitted @@ -200,6 +208,7 @@ def endorse_comment(request, course_id, comment_id): comment.save() return JsonResponse(utils.safe_content(comment.to_dict())) + @require_POST @login_required @permitted @@ -213,6 +222,7 @@ def openclose_thread(request, course_id, thread_id): 'ability': utils.get_ability(course_id, thread, request.user), }) + @require_POST @login_required @permitted @@ -222,6 +232,7 @@ def create_sub_comment(request, course_id, comment_id): return JsonError("Comment level too deep") return _create_comment(request, course_id, parent_id=comment_id) + @require_POST @login_required @permitted @@ -230,6 +241,7 @@ def delete_comment(request, course_id, comment_id): comment.delete() return JsonResponse(utils.safe_content(comment.to_dict())) + @require_POST @login_required @permitted @@ -239,6 +251,7 @@ def vote_for_comment(request, course_id, comment_id, value): user.vote(comment, value) return JsonResponse(utils.safe_content(comment.to_dict())) + @require_POST @login_required @permitted @@ -248,6 +261,7 @@ def undo_vote_for_comment(request, course_id, comment_id): user.unvote(comment) return JsonResponse(utils.safe_content(comment.to_dict())) + @require_POST @login_required @permitted @@ -257,6 +271,7 @@ def vote_for_thread(request, course_id, thread_id, value): user.vote(thread, value) return JsonResponse(utils.safe_content(thread.to_dict())) + @require_POST @login_required @permitted @@ -276,6 +291,7 @@ def follow_thread(request, course_id, thread_id): user.follow(thread) return JsonResponse({}) + @require_POST @login_required @permitted @@ -285,6 +301,7 @@ def follow_commentable(request, course_id, commentable_id): user.follow(commentable) return JsonResponse({}) + @require_POST @login_required @permitted @@ -294,6 +311,7 @@ def follow_user(request, course_id, followed_user_id): user.follow(followed_user) return JsonResponse({}) + @require_POST @login_required @permitted @@ -303,6 +321,7 @@ def unfollow_thread(request, course_id, thread_id): user.unfollow(thread) return JsonResponse({}) + @require_POST @login_required @permitted @@ -312,6 +331,7 @@ def unfollow_commentable(request, course_id, commentable_id): user.unfollow(commentable) return JsonResponse({}) + @require_POST @login_required @permitted @@ -321,6 +341,7 @@ def unfollow_user(request, course_id, followed_user_id): user.unfollow(followed_user) return JsonResponse({}) + @require_POST @login_required @permitted @@ -351,6 +372,7 @@ def update_moderator_status(request, course_id, user_id): else: return JsonResponse({}) + @require_GET def search_similar_threads(request, course_id, commentable_id): text = request.GET.get('text', None) @@ -362,11 +384,12 @@ def search_similar_threads(request, course_id, commentable_id): threads = cc.search_similar_threads(course_id, recursive=False, query_params=query_params) else: theads = [] - context = { 'threads': map(utils.extend_content, threads) } + context = {'threads': map(utils.extend_content, threads)} return JsonResponse({ 'html': render_to_string('discussion/_similar_posts.html', context) }) + @require_GET def tags_autocomplete(request, course_id): value = request.GET.get('q', None) @@ -375,10 +398,11 @@ def tags_autocomplete(request, course_id): results = cc.tags_autocomplete(value) return JsonResponse(results) + @require_POST @login_required @csrf.csrf_exempt -def upload(request, course_id):#ajax upload file to a question or answer +def upload(request, course_id): # ajax upload file to a question or answer """view that handles file upload via Ajax """ @@ -409,7 +433,7 @@ def upload(request, course_id):#ajax upload file to a question or answer time.time() ).replace( '.', - str(random.randint(0,100000)) + str(random.randint(0, 100000)) ) + file_extension file_storage = get_storage_class()() diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index 2c1d3c68d5..70d9f40fcf 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -30,6 +30,7 @@ PAGES_NEARBY_DELTA = 2 escapedict = {'"': '"'} log = logging.getLogger("edx.discussions") + def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAGE): """ This may raise cc.utils.CommentClientError or @@ -78,6 +79,7 @@ def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAG return threads, query_params + def inline_discussion(request, course_id, discussion_id): """ Renders JSON for DiscussionModules @@ -111,6 +113,7 @@ def inline_discussion(request, course_id, discussion_id): 'allow_anonymous': allow_anonymous, }) + @login_required def forum_form_discussion(request, course_id): """ @@ -136,7 +139,7 @@ def forum_form_discussion(request, course_id): thread.update(courseware_context) if request.is_ajax(): return utils.JsonResponse({ - 'discussion_data': threads, # TODO: Standardize on 'discussion_data' vs 'threads' + 'discussion_data': threads, # TODO: Standardize on 'discussion_data' vs 'threads' 'annotated_content_info': annotated_content_info, 'num_pages': query_params['num_pages'], 'page': query_params['page'], @@ -157,11 +160,11 @@ def forum_form_discussion(request, course_id): 'course': course, #'recent_active_threads': recent_active_threads, #'trending_tags': trending_tags, - 'staff_access' : has_access(request.user, course, 'staff'), - 'threads': saxutils.escape(json.dumps(threads),escapedict), + 'staff_access': has_access(request.user, course, 'staff'), + 'threads': saxutils.escape(json.dumps(threads), escapedict), 'thread_pages': query_params['num_pages'], - 'user_info': saxutils.escape(json.dumps(user_info),escapedict), - 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info),escapedict), + 'user_info': saxutils.escape(json.dumps(user_info), escapedict), + 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), 'course_id': course.id, 'category_map': category_map, 'roles': saxutils.escape(json.dumps(utils.get_role_ids(course_id)), escapedict), @@ -169,6 +172,7 @@ def forum_form_discussion(request, course_id): # print "start rendering.." return render_to_response('discussion/index.html', context) + @login_required def single_thread(request, course_id, discussion_id, thread_id): @@ -234,13 +238,13 @@ def single_thread(request, course_id, discussion_id, thread_id): context = { 'discussion_id': discussion_id, 'csrf': csrf(request)['csrf_token'], - 'init': '', #TODO: What is this? - 'user_info': saxutils.escape(json.dumps(user_info),escapedict), + 'init': '', # TODO: What is this? + 'user_info': saxutils.escape(json.dumps(user_info), escapedict), 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), 'course': course, #'recent_active_threads': recent_active_threads, #'trending_tags': trending_tags, - 'course_id': course.id, #TODO: Why pass both course and course.id to template? + 'course_id': course.id, # TODO: Why pass both course and course.id to template? 'thread_id': thread_id, 'threads': saxutils.escape(json.dumps(threads), escapedict), 'category_map': category_map, @@ -250,6 +254,7 @@ def single_thread(request, course_id, discussion_id, thread_id): return render_to_response('discussion/single_thread.html', context) + @login_required def user_profile(request, course_id, user_id): #TODO: Allow sorting? @@ -259,7 +264,7 @@ def user_profile(request, course_id, user_id): query_params = { 'page': request.GET.get('page', 1), - 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities + 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities } threads, page, num_pages = profiled_user.active_threads(query_params) @@ -274,7 +279,7 @@ def user_profile(request, course_id, user_id): 'discussion_data': map(utils.safe_content, threads), 'page': query_params['page'], 'num_pages': query_params['num_pages'], - 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info),escapedict), + 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), }) else: @@ -285,8 +290,8 @@ def user_profile(request, course_id, user_id): 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': saxutils.escape(json.dumps(threads), escapedict), - 'user_info': saxutils.escape(json.dumps(user_info),escapedict), - 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info),escapedict), + 'user_info': saxutils.escape(json.dumps(user_info), escapedict), + 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), # 'content': content, } @@ -302,7 +307,7 @@ def followed_threads(request, course_id, user_id): query_params = { 'page': request.GET.get('page', 1), - 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities + 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities 'sort_key': request.GET.get('sort_key', 'date'), 'sort_order': request.GET.get('sort_order', 'desc'), } @@ -328,8 +333,8 @@ def followed_threads(request, course_id, user_id): 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': saxutils.escape(json.dumps(threads), escapedict), - 'user_info': saxutils.escape(json.dumps(user_info),escapedict), - 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info),escapedict), + 'user_info': saxutils.escape(json.dumps(user_info), escapedict), + 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), # 'content': content, } diff --git a/lms/djangoapps/django_comment_client/helpers.py b/lms/djangoapps/django_comment_client/helpers.py index 0a1e8639ef..733856e2a9 100644 --- a/lms/djangoapps/django_comment_client/helpers.py +++ b/lms/djangoapps/django_comment_client/helpers.py @@ -15,12 +15,16 @@ import os # This method is used to pluralize the words "discussion" and "comment" # when referring to how many discussion threads or comments the user # has contributed to. + + def pluralize(singular_term, count): if int(count) >= 2 or int(count) == 0: return singular_term + 's' return singular_term # TODO there should be a better way to handle this + + def include_mustache_templates(): mustache_dir = settings.PROJECT_ROOT / 'templates' / 'discussion' / 'mustache' valid_file_name = lambda file_name: file_name.endswith('.mustache') @@ -31,6 +35,7 @@ def include_mustache_templates(): file_contents = map(read_file, filter(valid_file_name, os.listdir(mustache_dir))) return '\n'.join(map(wrap_in_tag, map(strip_file_name, file_contents))) + def render_content(content, additional_context={}): context = { diff --git a/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py b/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py index 82f2290bc7..304907cdae 100644 --- a/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py +++ b/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py @@ -8,6 +8,7 @@ from django.core.management.base import BaseCommand, CommandError from student.models import CourseEnrollment, assign_default_role + class Command(BaseCommand): args = 'course_id' help = 'Add roles for all users in a course' diff --git a/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py b/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py index d1244a6690..638d59f5fe 100644 --- a/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py +++ b/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py @@ -8,6 +8,7 @@ from django.core.management.base import BaseCommand, CommandError from student.models import CourseEnrollment, assign_default_role + class Command(BaseCommand): args = 'course_id' help = 'Seed default permisssions and roles' diff --git a/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py b/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py index 958b67cdb3..6a31e73af3 100644 --- a/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py +++ b/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py @@ -18,7 +18,7 @@ class Command(BaseCommand): student_role = Role.objects.get_or_create(name="Student", course_id=course_id)[0] for per in ["vote", "update_thread", "follow_thread", "unfollow_thread", - "update_comment", "create_sub_comment", "unvote" , "create_thread", + "update_comment", "create_sub_comment", "unvote", "create_thread", "follow_commentable", "unfollow_commentable", "create_comment", ]: student_role.add_permission(per) diff --git a/lms/djangoapps/django_comment_client/middleware.py b/lms/djangoapps/django_comment_client/middleware.py index 08e20b0296..abf2d40cab 100644 --- a/lms/djangoapps/django_comment_client/middleware.py +++ b/lms/djangoapps/django_comment_client/middleware.py @@ -2,7 +2,8 @@ from comment_client import CommentClientError from django_comment_client.utils import JsonError import json -class AjaxExceptionMiddleware(object): + +class AjaxExceptionMiddleware(object): def process_exception(self, request, exception): if isinstance(exception, CommentClientError) and request.is_ajax(): return JsonError(json.loads(exception.message)) diff --git a/lms/djangoapps/django_comment_client/migrations/0001_initial.py b/lms/djangoapps/django_comment_client/migrations/0001_initial.py index 4993984d74..0b5f88e2f2 100644 --- a/lms/djangoapps/django_comment_client/migrations/0001_initial.py +++ b/lms/djangoapps/django_comment_client/migrations/0001_initial.py @@ -129,4 +129,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['django_comment_client'] \ No newline at end of file + complete_apps = ['django_comment_client'] diff --git a/lms/djangoapps/django_comment_client/models.py b/lms/djangoapps/django_comment_client/models.py index 10c05c75e9..023b355a29 100644 --- a/lms/djangoapps/django_comment_client/models.py +++ b/lms/djangoapps/django_comment_client/models.py @@ -35,7 +35,7 @@ class Role(models.Model): def __unicode__(self): return self.name + " for " + (self.course_id if self.course_id else "all courses") - def inherit_permissions(self, role): # TODO the name of this method is a little bit confusing, + def inherit_permissions(self, role): # TODO the name of this method is a little bit confusing, # since it's one-off and doesn't handle inheritance later if role.course_id and role.course_id != self.course_id: logging.warning("{0} cannot inherit permissions from {1} due to course_id inconsistency", \ @@ -52,7 +52,7 @@ class Role(models.Model): (permission.startswith('edit') or permission.startswith('update') or permission.startswith('create')) and \ (not course.forum_posts_allowed): return False - + return self.permissions.filter(name=permission).exists() diff --git a/lms/djangoapps/django_comment_client/mustache_helpers.py b/lms/djangoapps/django_comment_client/mustache_helpers.py index 9756294696..5743dba9cb 100644 --- a/lms/djangoapps/django_comment_client/mustache_helpers.py +++ b/lms/djangoapps/django_comment_client/mustache_helpers.py @@ -7,6 +7,8 @@ import inspect # This method is used to pluralize the words "discussion" and "comment" # which is why you need to tack on an "s" for the case of 0 or two or more. + + def pluralize(content, text): num, word = text.split(' ') num = int(num or '0') @@ -15,12 +17,15 @@ def pluralize(content, text): else: return word + def url_for_user(content, user_id): return urlresolvers.reverse('django_comment_client.forum.views.user_profile', args=[content['course_id'], user_id]) -def url_for_tags(content, tags): # assume that attribute 'tags' is in the format u'a, b, c' + +def url_for_tags(content, tags): # assume that attribute 'tags' is in the format u'a, b, c' return _url_for_tags(content['course_id'], tags) + def close_thread_text(content): if content.get('closed'): return 'Re-open thread' diff --git a/lms/djangoapps/django_comment_client/permissions.py b/lms/djangoapps/django_comment_client/permissions.py index b95a890dda..dfdcd3e7ba 100644 --- a/lms/djangoapps/django_comment_client/permissions.py +++ b/lms/djangoapps/django_comment_client/permissions.py @@ -8,6 +8,7 @@ from util.cache import cache from django.core import cache cache = cache.get_cache('default') + def cached_has_permission(user, permission, course_id=None): """ Call has_permission if it's not cached. A change in a user's role or @@ -21,6 +22,7 @@ def cached_has_permission(user, permission, course_id=None): cache.set(key, val, CACHE_LIFESPAN) return val + def has_permission(user, permission, course_id=None): for role in user.roles.filter(course_id=course_id): if role.has_permission(permission): @@ -29,6 +31,8 @@ def has_permission(user, permission, course_id=None): CONDITIONS = ['is_open', 'is_author'] + + def check_condition(user, condition, course_id, data): def check_open(user, condition, course_id, data): try: @@ -43,8 +47,8 @@ def check_condition(user, condition, course_id, data): return False handlers = { - 'is_open' : check_open, - 'is_author' : check_author, + 'is_open': check_open, + 'is_author': check_author, } return handlers[condition](user, condition, course_id, data) @@ -93,7 +97,7 @@ VIEW_PERMISSIONS = { 'unfollow_commentable': ['unfollow_commentable'], 'unfollow_user' : ['unfollow_user'], 'create_thread' : ['create_thread'], - 'update_moderator_status' : ['manage_moderator'], + 'update_moderator_status': ['manage_moderator'], } diff --git a/lms/djangoapps/django_comment_client/settings.py b/lms/djangoapps/django_comment_client/settings.py index 3234c32478..b9a8d18081 100644 --- a/lms/djangoapps/django_comment_client/settings.py +++ b/lms/djangoapps/django_comment_client/settings.py @@ -1,7 +1,7 @@ from django.conf import settings MAX_COMMENT_DEPTH = None -MAX_UPLOAD_FILE_SIZE = 1024 * 1024 #result in bytes +MAX_UPLOAD_FILE_SIZE = 1024 * 1024 # result in bytes ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff') if hasattr(settings, 'DISCUSSION_SETTINGS'): diff --git a/lms/djangoapps/django_comment_client/tests/test_helpers.py b/lms/djangoapps/django_comment_client/tests/test_helpers.py index bd67830841..e2c074231f 100644 --- a/lms/djangoapps/django_comment_client/tests/test_helpers.py +++ b/lms/djangoapps/django_comment_client/tests/test_helpers.py @@ -2,10 +2,11 @@ import string import random import collections -from django.test import TestCase +from django.test import TestCase from django_comment_client.helpers import pluralize + class PluralizeTestCase(TestCase): def testPluralize(self): diff --git a/lms/djangoapps/django_comment_client/tests/test_middleware.py b/lms/djangoapps/django_comment_client/tests/test_middleware.py index e3249551b3..55e4c72c75 100644 --- a/lms/djangoapps/django_comment_client/tests/test_middleware.py +++ b/lms/djangoapps/django_comment_client/tests/test_middleware.py @@ -2,27 +2,28 @@ import string import random import collections -from django.test import TestCase +from django.test import TestCase import comment_client import django.http import django_comment_client.middleware as middleware + class AjaxExceptionTestCase(TestCase): -# TODO: check whether the correct error message is produced. +# TODO: check whether the correct error message is produced. # The error message should be the same as the argument to CommentClientError - def setUp(self): - self.a = middleware.AjaxExceptionMiddleware() - self.request1 = django.http.HttpRequest() - self.request0 = django.http.HttpRequest() - self.exception1 = comment_client.CommentClientError('{}') - self.exception0 = ValueError() - self.request1.META['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest" - self.request0.META['HTTP_X_REQUESTED_WITH'] = "SHADOWFAX" - - def test_process_exception(self): - self.assertIsInstance(self.a.process_exception(self.request1, self.exception1), middleware.JsonError) - self.assertIsNone(self.a.process_exception(self.request1, self.exception0)) - self.assertIsNone(self.a.process_exception(self.request0, self.exception1)) - self.assertIsNone(self.a.process_exception(self.request0, self.exception0)) + def setUp(self): + self.a = middleware.AjaxExceptionMiddleware() + self.request1 = django.http.HttpRequest() + self.request0 = django.http.HttpRequest() + self.exception1 = comment_client.CommentClientError('{}') + self.exception0 = ValueError() + self.request1.META['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest" + self.request0.META['HTTP_X_REQUESTED_WITH'] = "SHADOWFAX" + + def test_process_exception(self): + self.assertIsInstance(self.a.process_exception(self.request1, self.exception1), middleware.JsonError) + self.assertIsNone(self.a.process_exception(self.request1, self.exception0)) + self.assertIsNone(self.a.process_exception(self.request0, self.exception1)) + self.assertIsNone(self.a.process_exception(self.request0, self.exception0)) diff --git a/lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py b/lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py index 8638aba67e..5b788b3cc4 100644 --- a/lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py +++ b/lms/djangoapps/django_comment_client/tests/test_mustache_helpers.py @@ -2,25 +2,27 @@ import string import random import collections -from django.test import TestCase +from django.test import TestCase import django_comment_client.mustache_helpers as mustache_helpers + class PluralizeTestCase(TestCase): - def test_pluralize(self): - self.text1 = '0 goat' - self.text2 = '1 goat' - self.text3 = '7 goat' - self.content = 'unused argument' - self.assertEqual(mustache_helpers.pluralize(self.content, self.text1), 'goats') - self.assertEqual(mustache_helpers.pluralize(self.content, self.text2), 'goat') - self.assertEqual(mustache_helpers.pluralize(self.content, self.text3), 'goats') + def test_pluralize(self): + self.text1 = '0 goat' + self.text2 = '1 goat' + self.text3 = '7 goat' + self.content = 'unused argument' + self.assertEqual(mustache_helpers.pluralize(self.content, self.text1), 'goats') + self.assertEqual(mustache_helpers.pluralize(self.content, self.text2), 'goat') + self.assertEqual(mustache_helpers.pluralize(self.content, self.text3), 'goats') + class CloseThreadTextTestCase(TestCase): - - def test_close_thread_text(self): - self.contentClosed = {'closed': True} - self.contentOpen = {'closed': False} - self.assertEqual(mustache_helpers.close_thread_text(self.contentClosed), 'Re-open thread') - self.assertEqual(mustache_helpers.close_thread_text(self.contentOpen), 'Close thread') + + def test_close_thread_text(self): + self.contentClosed = {'closed': True} + self.contentOpen = {'closed': False} + self.assertEqual(mustache_helpers.close_thread_text(self.contentClosed), 'Re-open thread') + self.assertEqual(mustache_helpers.close_thread_text(self.contentOpen), 'Close thread') diff --git a/lms/djangoapps/django_comment_client/tests/test_utils.py b/lms/djangoapps/django_comment_client/tests/test_utils.py index 2e24cbd837..cec006e630 100644 --- a/lms/djangoapps/django_comment_client/tests/test_utils.py +++ b/lms/djangoapps/django_comment_client/tests/test_utils.py @@ -2,7 +2,7 @@ import string import random import collections -from django.test import TestCase +from django.test import TestCase import factory from django.contrib.auth.models import User @@ -14,6 +14,7 @@ import django_comment_client.utils as utils import xmodule.modulestore.django as django + class UserFactory(factory.Factory): FACTORY_FOR = User username = 'robot' @@ -22,20 +23,24 @@ class UserFactory(factory.Factory): is_active = True is_staff = False + class CourseEnrollmentFactory(factory.Factory): - FACTORY_FOR = CourseEnrollment + FACTORY_FOR = CourseEnrollment user = factory.SubFactory(UserFactory) course_id = 'edX/toy/2012_Fall' + class RoleFactory(factory.Factory): FACTORY_FOR = Role name = 'Student' course_id = 'edX/toy/2012_Fall' + class PermissionFactory(factory.Factory): - FACTORY_FOR = Permission + FACTORY_FOR = Permission name = 'create_comment' + class DictionaryTestCase(TestCase): def test_extract(self): d = {'cats': 'meow', 'dogs': 'woof'} @@ -54,11 +59,12 @@ class DictionaryTestCase(TestCase): self.assertEqual(utils.strip_blank(d), expected) def test_merge_dict(self): - d1 ={'cats': 'meow', 'dogs': 'woof'} - d2 ={'lions': 'roar','ducks': 'quack'} - expected ={'cats': 'meow', 'dogs': 'woof','lions': 'roar','ducks': 'quack'} + d1 = {'cats': 'meow', 'dogs': 'woof'} + d2 = {'lions': 'roar', 'ducks': 'quack'} + expected = {'cats': 'meow', 'dogs': 'woof', 'lions': 'roar', 'ducks': 'quack'} self.assertEqual(utils.merge_dict(d1, d2), expected) + class AccessUtilsTestCase(TestCase): def setUp(self): self.course_id = 'edX/toy/2012_Fall' diff --git a/lms/djangoapps/django_comment_client/utils.py b/lms/djangoapps/django_comment_client/utils.py index b58e3b30e6..1f1a80e2b4 100644 --- a/lms/djangoapps/django_comment_client/utils.py +++ b/lms/djangoapps/django_comment_client/utils.py @@ -24,21 +24,27 @@ log = logging.getLogger(__name__) _FULLMODULES = None _DISCUSSIONINFO = defaultdict(dict) + def extract(dic, keys): return {k: dic.get(k) for k in keys} + def strip_none(dic): return dict([(k, v) for k, v in dic.iteritems() if v is not None]) + def strip_blank(dic): def _is_blank(v): return isinstance(v, str) and len(v.strip()) == 0 return dict([(k, v) for k, v in dic.iteritems() if not _is_blank(v)]) # TODO should we be checking if d1 and d2 have the same keys with different values? + + def merge_dict(dic1, dic2): return dict(dic1.items() + dic2.items()) + def get_role_ids(course_id): roles = Role.objects.filter(course_id=course_id) staff = list(User.objects.filter(is_staff=True).values_list('id', flat=True)) @@ -47,6 +53,7 @@ def get_role_ids(course_id): roles_with_ids[role.name] = list(role.users.values_list('id', flat=True)) return roles_with_ids + def has_forum_access(uname, course_id, rolename): try: role = Role.objects.get(name=rolename, course_id=course_id) @@ -54,12 +61,14 @@ def has_forum_access(uname, course_id, rolename): return False return role.users.filter(username=uname).exists() + def get_full_modules(): global _FULLMODULES if not _FULLMODULES: _FULLMODULES = modulestore().modules return _FULLMODULES + def get_discussion_id_map(course): """ return a dict of the form {category: modules} @@ -68,18 +77,21 @@ def get_discussion_id_map(course): initialize_discussion_info(course) return _DISCUSSIONINFO[course.id]['id_map'] + def get_discussion_title(course, discussion_id): global _DISCUSSIONINFO initialize_discussion_info(course) title = _DISCUSSIONINFO[course.id]['id_map'].get(discussion_id, {}).get('title', '(no title)') return title + def get_discussion_category_map(course): global _DISCUSSIONINFO initialize_discussion_info(course) return filter_unstarted_categories(_DISCUSSIONINFO[course.id]['category_map']) + def filter_unstarted_categories(category_map): now = time.gmtime() @@ -117,6 +129,7 @@ def filter_unstarted_categories(category_map): return result_map + def sort_map_entries(category_map): things = [] for title, entry in category_map["entries"].items(): @@ -211,7 +224,7 @@ def initialize_discussion_info(course): # TODO. BUG! : course location is not unique across multiple course runs! # (I think Kevin already noticed this) Need to send course_id with requests, store it # in the backend. - default_topics = {'General': {'id' :course.location.html_id()}} + default_topics = {'General': {'id': course.location.html_id()}} discussion_topics = course.metadata.get('discussion_topics', default_topics) for topic, entry in discussion_topics.items(): category_map['entries'][topic] = {"id": entry["id"], @@ -223,12 +236,14 @@ def initialize_discussion_info(course): _DISCUSSIONINFO[course.id]['category_map'] = category_map _DISCUSSIONINFO[course.id]['timestamp'] = datetime.now() + class JsonResponse(HttpResponse): def __init__(self, data=None): content = simplejson.dumps(data) super(JsonResponse, self).__init__(content, mimetype='application/json; charset=utf-8') + class JsonError(HttpResponse): def __init__(self, error_messages=[], status=400): if isinstance(error_messages, str): @@ -239,14 +254,17 @@ class JsonError(HttpResponse): super(JsonError, self).__init__(content, mimetype='application/json; charset=utf-8', status=status) + class HtmlResponse(HttpResponse): def __init__(self, html=''): super(HtmlResponse, self).__init__(html, content_type='text/plain') + class ViewNameMiddleware(object): def process_view(self, request, view_func, view_args, view_kwargs): request.view_name = view_func.__name__ + class QueryCountDebugMiddleware(object): """ This middleware will log the number of queries run @@ -272,6 +290,7 @@ class QueryCountDebugMiddleware(object): log.info('%s queries run, total %s seconds' % (len(connection.queries), total_time)) return response + def get_ability(course_id, content, user): return { 'editable': check_permissions_by_view(user, course_id, content, "update_thread" if content['type'] == 'thread' else "update_comment"), @@ -283,6 +302,8 @@ def get_ability(course_id, content, user): } #TODO: RENAME + + def get_annotated_content_info(course_id, content, user, user_info): """ Get metadata for an individual content (thread or comment) @@ -299,6 +320,8 @@ def get_annotated_content_info(course_id, content, user, user_info): } #TODO: RENAME + + def get_annotated_content_infos(course_id, thread, user, user_info): """ Get metadata for a thread and its children @@ -311,6 +334,7 @@ def get_annotated_content_infos(course_id, thread, user, user_info): annotate(thread) return infos + def get_metadata_for_threads(course_id, threads, user, user_info): def infogetter(thread): return get_annotated_content_infos(course_id, thread, user, user_info) @@ -319,13 +343,17 @@ def get_metadata_for_threads(course_id, threads, user, user_info): return metadata # put this method in utils.py to avoid circular import dependency between helpers and mustache_helpers + + def url_for_tags(course_id, tags): return reverse('django_comment_client.forum.views.forum_form_discussion', args=[course_id]) + '?' + urllib.urlencode({'tags': tags}) + def render_mustache(template_name, dictionary, *args, **kwargs): template = middleware.lookup['main'].get_template(template_name).source return pystache.render(template, dictionary) + def permalink(content): if content['type'] == 'thread': return reverse('django_comment_client.forum.views.single_thread', @@ -334,6 +362,7 @@ def permalink(content): return reverse('django_comment_client.forum.views.single_thread', args=[content['course_id'], content['commentable_id'], content['thread_id']]) + '#' + content['id'] + def extend_content(content): roles = {} if content.get('user_id'): @@ -349,10 +378,11 @@ def extend_content(content): 'raw_tags': ','.join(content.get('tags', [])), 'permalink': permalink(content), 'roles': roles, - 'updated': content['created_at']!=content['updated_at'], + 'updated': content['created_at'] != content['updated_at'], } return merge_dict(content, content_info) + def get_courseware_context(content, course): id_map = get_discussion_id_map(course) id = content['commentable_id'] @@ -361,13 +391,14 @@ def get_courseware_context(content, course): location = id_map[id]["location"].url() title = id_map[id]["title"] (course_id, chapter, section, position) = path_to_location(modulestore(), course.id, location) - url = reverse('courseware_position', kwargs={"course_id":course_id, - "chapter":chapter, - "section":section, - "position":position}) + url = reverse('courseware_position', kwargs={"course_id": course_id, + "chapter": chapter, + "section": section, + "position": position}) content_info = {"courseware_url": url, "courseware_title": title} return content_info + def safe_content(content): fields = [ 'id', 'title', 'body', 'course_id', 'anonymous', 'anonymous_to_peers', diff --git a/lms/djangoapps/instructor/management/commands/compute_grades.py b/lms/djangoapps/instructor/management/commands/compute_grades.py index 462833ba3c..92db04f09a 100644 --- a/lms/djangoapps/instructor/management/commands/compute_grades.py +++ b/lms/djangoapps/instructor/management/commands/compute_grades.py @@ -3,7 +3,9 @@ # django management command: dump grades to csv files # for use by batch processes -import os, sys, string +import os +import sys +import string import datetime import json @@ -15,6 +17,7 @@ from xmodule.modulestore.django import modulestore from django.conf import settings from django.core.management.base import BaseCommand + class Command(BaseCommand): help = "Compute grades for all students in a course, and store result in DB.\n" help += "Usage: compute_grades course_id_or_dir \n" @@ -25,7 +28,7 @@ class Command(BaseCommand): print "args = ", args - if len(args)>0: + if len(args) > 0: course_id = args[0] else: print self.help @@ -46,7 +49,3 @@ class Command(BaseCommand): print "Computing grades for %s" % (course.id) offline_grade_calculation(course.id) - - - - diff --git a/lms/djangoapps/instructor/management/commands/dump_grades.py b/lms/djangoapps/instructor/management/commands/dump_grades.py index 65825271f3..13f86c0e0f 100644 --- a/lms/djangoapps/instructor/management/commands/dump_grades.py +++ b/lms/djangoapps/instructor/management/commands/dump_grades.py @@ -3,7 +3,9 @@ # django management command: dump grades to csv files # for use by batch processes -import os, sys, string +import os +import sys +import string import datetime import json @@ -14,6 +16,7 @@ from xmodule.modulestore.django import modulestore from django.conf import settings from django.core.management.base import BaseCommand + class Command(BaseCommand): help = "dump grades to CSV file. Usage: dump_grades course_id_or_dir filename dump_type\n" help += " course_id_or_dir: either course_id or course_dir\n" @@ -32,12 +35,12 @@ class Command(BaseCommand): fn = "grades.csv" get_raw_scores = False - if len(args)>0: + if len(args) > 0: course_id = args[0] - if len(args)>1: + if len(args) > 1: fn = args[1] - if len(args)>2: - get_raw_scores = args[2].lower()=='raw' + if len(args) > 2: + get_raw_scores = args[2].lower() == 'raw' request = self.DummyRequest() try: @@ -54,15 +57,15 @@ class Command(BaseCommand): print "-----------------------------------------------------------------------------" print "Dumping grades from %s to file %s (get_raw_scores=%s)" % (course.id, fn, get_raw_scores) datatable = get_student_grade_summary_data(request, course, course.id, get_raw_scores=get_raw_scores) - - fp = open(fn,'w') - + + fp = open(fn, 'w') + writer = csv.writer(fp, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) writer.writerow(datatable['header']) for datarow in datatable['data']: encoded_row = [unicode(s).encode('utf-8') for s in datarow] writer.writerow(encoded_row) - + fp.close() print "Done: %d records dumped" % len(datatable['data']) @@ -74,6 +77,3 @@ class Command(BaseCommand): return 'edx.mit.edu' def is_secure(self): return False - - - diff --git a/lms/djangoapps/instructor/offline_gradecalc.py b/lms/djangoapps/instructor/offline_gradecalc.py index 7c102805b4..8182c4e58a 100644 --- a/lms/djangoapps/instructor/offline_gradecalc.py +++ b/lms/djangoapps/instructor/offline_gradecalc.py @@ -31,7 +31,7 @@ class MyEncoder(JSONEncoder): def offline_grade_calculation(course_id): ''' - Compute grades for all students for a specified course, and save results to the DB. + Compute grades for all students for a specified course, and save results to the DB. ''' tstart = time.time() @@ -59,16 +59,16 @@ def offline_grade_calculation(course_id): ocg, created = models.OfflineComputedGrade.objects.get_or_create(user=student, course_id=course_id) ocg.gradeset = gs ocg.save() - print "%s done" % student # print statement used because this is run by a management command + print "%s done" % student # print statement used because this is run by a management command tend = time.time() dt = tend - tstart - + ocgl = models.OfflineComputedGradeLog(course_id=course_id, seconds=dt, nstudents=len(enrolled_students)) ocgl.save() print ocgl print "All Done!" - + def offline_grades_available(course_id): ''' @@ -80,7 +80,7 @@ def offline_grades_available(course_id): return False return ocgl.latest('created') - + def student_grades(student, request, course, keep_raw_scores=False, use_offline=False): ''' This is the main interface to get grades. It has the same parameters as grades.grade, as well @@ -89,15 +89,11 @@ def student_grades(student, request, course, keep_raw_scores=False, use_offline= if not use_offline: return grades.grade(student, request, course, keep_raw_scores=keep_raw_scores) - + try: ocg = models.OfflineComputedGrade.objects.get(user=student, course_id=course.id) except models.OfflineComputedGrade.DoesNotExist: - return dict(raw_scores=[], section_breakdown=[], + return dict(raw_scores=[], section_breakdown=[], msg='Error: no offline gradeset available for %s, %s' % (student, course.id)) - + return json.loads(ocg.gradeset) - - - - diff --git a/lms/djangoapps/instructor/tests.py b/lms/djangoapps/instructor/tests.py index e2ee878021..2610e57422 100644 --- a/lms/djangoapps/instructor/tests.py +++ b/lms/djangoapps/instructor/tests.py @@ -71,13 +71,13 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader): response = self.client.post(url, {'action': 'Download CSV of all student grades for this course'}) msg += "instructor dashboard download csv grades: response = '{0}'\n".format(response) - self.assertEqual(response['Content-Type'],'text/csv',msg) + self.assertEqual(response['Content-Type'], 'text/csv', msg) cdisp = response['Content-Disposition'] msg += "Content-Disposition = '%s'\n" % cdisp self.assertEqual(cdisp, 'attachment; filename=grades_{0}.csv'.format(course.id), msg) - body = response.content.replace('\r','') + body = response.content.replace('\r', '') msg += "body = '{0}'\n".format(body) # All the not-actually-in-the-course hw and labs come from the @@ -89,9 +89,10 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader): self.assertEqual(body, expected_body, msg) -FORUM_ROLES = [ FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA ] -FORUM_ADMIN_ACTION_SUFFIX = { FORUM_ROLE_ADMINISTRATOR : 'admin', FORUM_ROLE_MODERATOR : 'moderator', FORUM_ROLE_COMMUNITY_TA : 'community TA'} -FORUM_ADMIN_USER = { FORUM_ROLE_ADMINISTRATOR : 'forumadmin', FORUM_ROLE_MODERATOR : 'forummoderator', FORUM_ROLE_COMMUNITY_TA : 'forummoderator'} +FORUM_ROLES = [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA] +FORUM_ADMIN_ACTION_SUFFIX = {FORUM_ROLE_ADMINISTRATOR: 'admin', FORUM_ROLE_MODERATOR: 'moderator', FORUM_ROLE_COMMUNITY_TA: 'community TA'} +FORUM_ADMIN_USER = {FORUM_ROLE_ADMINISTRATOR: 'forumadmin', FORUM_ROLE_MODERATOR: 'forummoderator', FORUM_ROLE_COMMUNITY_TA: 'forummoderator'} + def action_name(operation, rolename): if operation == 'List': @@ -146,7 +147,7 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): for action in ['Add', 'Remove']: for rolename in FORUM_ROLES: response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username}) - self.assertTrue(response.content.find('Error: unknown username "{0}"'.format(username))>=0) + self.assertTrue(response.content.find('Error: unknown username "{0}"'.format(username)) >= 0) def test_add_forum_admin_users_for_missing_roles(self): course = self.toy @@ -155,7 +156,7 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): for action in ['Add', 'Remove']: for rolename in FORUM_ROLES: response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username}) - self.assertTrue(response.content.find('Error: unknown rolename "{0}"'.format(rolename))>=0) + self.assertTrue(response.content.find('Error: unknown rolename "{0}"'.format(rolename)) >= 0) def test_remove_forum_admin_users_for_missing_users(self): course = self.toy @@ -165,7 +166,7 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): action = 'Remove' for rolename in FORUM_ROLES: response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username}) - self.assertTrue(response.content.find('Error: user "{0}" does not have rolename "{1}"'.format(username, rolename))>=0) + self.assertTrue(response.content.find('Error: user "{0}" does not have rolename "{1}"'.format(username, rolename)) >= 0) def test_add_and_remove_forum_admin_users(self): course = self.toy @@ -174,10 +175,10 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): username = 'u2' for rolename in FORUM_ROLES: response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) - self.assertTrue(response.content.find('Added "{0}" to "{1}" forum role = "{2}"'.format(username, course.id, rolename))>=0) + self.assertTrue(response.content.find('Added "{0}" to "{1}" forum role = "{2}"'.format(username, course.id, rolename)) >= 0) self.assertTrue(has_forum_access(username, course.id, rolename)) response = self.client.post(url, {'action': action_name('Remove', rolename), FORUM_ADMIN_USER[rolename]: username}) - self.assertTrue(response.content.find('Removed "{0}" from "{1}" forum role = "{2}"'.format(username, course.id, rolename))>=0) + self.assertTrue(response.content.find('Removed "{0}" from "{1}" forum role = "{2}"'.format(username, course.id, rolename)) >= 0) self.assertFalse(has_forum_access(username, course.id, rolename)) def test_add_and_read_forum_admin_users(self): @@ -189,7 +190,7 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): # perform an add, and follow with a second identical add: self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) - self.assertTrue(response.content.find('Error: user "{0}" already has rolename "{1}", cannot add'.format(username, rolename))>=0) + self.assertTrue(response.content.find('Error: user "{0}" already has rolename "{1}", cannot add'.format(username, rolename)) >= 0) self.assertTrue(has_forum_access(username, course.id, rolename)) def test_add_nonstaff_forum_admin_users(self): @@ -199,7 +200,7 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): username = 'u1' rolename = FORUM_ROLE_ADMINISTRATOR response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username}) - self.assertTrue(response.content.find('Error: user "{0}" should first be added as staff'.format(username))>=0) + self.assertTrue(response.content.find('Error: user "{0}" should first be added as staff'.format(username)) >= 0) def test_list_forum_admin_users(self): course = self.toy @@ -213,12 +214,10 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): self.assertTrue(has_forum_access(username, course.id, rolename)) response = self.client.post(url, {'action': action_name('List', rolename), FORUM_ADMIN_USER[rolename]: username}) for header in ['Username', 'Full name', 'Roles']: - self.assertTrue(response.content.find('{0}'.format(header))>0) - self.assertTrue(response.content.find('{0}'.format(username))>=0) + self.assertTrue(response.content.find('{0}'.format(header)) > 0) + self.assertTrue(response.content.find('{0}'.format(username)) >= 0) # concatenate all roles for user, in sorted order: added_roles.append(rolename) added_roles.sort() roles = ', '.join(added_roles) - self.assertTrue(response.content.find('{0}'.format(roles))>=0, 'not finding roles "{0}"'.format(roles)) - - + self.assertTrue(response.content.find('{0}'.format(roles)) >= 0, 'not finding roles "{0}"'.format(roles)) diff --git a/lms/djangoapps/instructor/views.py b/lms/djangoapps/instructor/views.py index a707506045..4faf814bc9 100644 --- a/lms/djangoapps/instructor/views.py +++ b/lms/djangoapps/instructor/views.py @@ -50,9 +50,11 @@ template_imports = {'urllib': urllib} FORUM_ROLE_ADD = 'add' FORUM_ROLE_REMOVE = 'remove' + def split_by_comma_and_whitespace(s): return re.split(r'[\s,]', s) + @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) def instructor_dashboard(request, course_id): @@ -69,11 +71,11 @@ def instructor_dashboard(request, course_id): # the instructor dashboard page is modal: grades, psychometrics, admin # keep that state in request.session (defaults to grades mode) - idash_mode = request.POST.get('idash_mode','') + idash_mode = request.POST.get('idash_mode', '') if idash_mode: request.session['idash_mode'] = idash_mode else: - idash_mode = request.session.get('idash_mode','Grades') + idash_mode = request.session.get('idash_mode', 'Grades') def escape(s): """escape HTML special characters in string""" @@ -130,7 +132,7 @@ def instructor_dashboard(request, course_id): # process actions from form POST action = request.POST.get('action', '') - use_offline = request.POST.get('use_offline_grades',False) + use_offline = request.POST.get('use_offline_grades', False) if settings.MITX_FEATURES['ENABLE_MANUAL_GIT_RELOAD']: if 'GIT pull' in action: @@ -155,12 +157,12 @@ def instructor_dashboard(request, course_id): course_errors = modulestore().get_item_errors(course.location) msg += '
              ' for cmsg, cerr in course_errors: - msg += "
            • {0}:
              {1}
              ".format(cmsg,escape(cerr)) + msg += "
            • {0}:
              {1}
              ".format(cmsg, escape(cerr)) msg += '
            ' except Exception as err: msg += '

            Error: {0}

            '.format(escape(err)) - if action == 'Dump list of enrolled students' or action=='List enrolled students': + if action == 'Dump list of enrolled students' or action == 'List enrolled students': log.debug(action) datatable = get_student_grade_summary_data(request, course, course_id, get_grades=False, use_offline=use_offline) datatable['title'] = 'List of students enrolled in {0}'.format(course_id) @@ -195,44 +197,44 @@ def instructor_dashboard(request, course_id): elif "Reset student's attempts" in action: # get the form data - unique_student_identifier=request.POST.get('unique_student_identifier','') - problem_to_reset=request.POST.get('problem_to_reset','') + unique_student_identifier = request.POST.get('unique_student_identifier', '') + problem_to_reset = request.POST.get('problem_to_reset', '') - if problem_to_reset[-4:]==".xml": - problem_to_reset=problem_to_reset[:-4] + if problem_to_reset[-4:] == ".xml": + problem_to_reset = problem_to_reset[:-4] # try to uniquely id student by email address or username try: if "@" in unique_student_identifier: - student_to_reset=User.objects.get(email=unique_student_identifier) + student_to_reset = User.objects.get(email=unique_student_identifier) else: - student_to_reset=User.objects.get(username=unique_student_identifier) - msg+="Found a single student to reset. " + student_to_reset = User.objects.get(username=unique_student_identifier) + msg += "Found a single student to reset. " except: - student_to_reset=None - msg+="Couldn't find student with that email or username. " + student_to_reset = None + msg += "Couldn't find student with that email or username. " if student_to_reset is not None: # find the module in question try: - (org, course_name, run)=course_id.split("/") - module_state_key="i4x://"+org+"/"+course_name+"/problem/"+problem_to_reset - module_to_reset=StudentModule.objects.get(student_id=student_to_reset.id, + (org, course_name, run) = course_id.split("/") + module_state_key = "i4x://" + org + "/" + course_name + "/problem/" + problem_to_reset + module_to_reset = StudentModule.objects.get(student_id=student_to_reset.id, course_id=course_id, module_state_key=module_state_key) - msg+="Found module to reset. " + msg += "Found module to reset. " except Exception as e: - msg+="Couldn't find module with that urlname. " + msg += "Couldn't find module with that urlname. " # modify the problem's state try: # load the state json - problem_state=json.loads(module_to_reset.state) - old_number_of_attempts=problem_state["attempts"] - problem_state["attempts"]=0 + problem_state = json.loads(module_to_reset.state) + old_number_of_attempts = problem_state["attempts"] + problem_state["attempts"] = 0 # save - module_to_reset.state=json.dumps(problem_state) + module_to_reset.state = json.dumps(problem_state) module_to_reset.save() track.views.server_track(request, '{instructor} reset attempts from {old_attempts} to 0 for {student} on problem {problem} in {course}'.format( @@ -243,19 +245,19 @@ def instructor_dashboard(request, course_id): course=course_id), {}, page='idashboard') - msg+="Module state successfully reset!" + msg += "Module state successfully reset!" except: - msg+="Couldn't reset module state. " + msg += "Couldn't reset module state. " elif "Get link to student's progress page" in action: - unique_student_identifier=request.POST.get('unique_student_identifier','') + unique_student_identifier = request.POST.get('unique_student_identifier', '') try: if "@" in unique_student_identifier: - student_to_reset=User.objects.get(email=unique_student_identifier) + student_to_reset = User.objects.get(email=unique_student_identifier) else: - student_to_reset=User.objects.get(username=unique_student_identifier) - progress_url=reverse('student_progress',kwargs={'course_id':course_id,'student_id': student_to_reset.id}) + student_to_reset = User.objects.get(username=unique_student_identifier) + progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': student_to_reset.id}) track.views.server_track(request, '{instructor} requested progress page for {student} in {course}'.format( student=student_to_reset, @@ -263,18 +265,18 @@ def instructor_dashboard(request, course_id): course=course_id), {}, page='idashboard') - msg+=" Progress page for username: {1} with email address: {2}.".format(progress_url,student_to_reset.username,student_to_reset.email) + msg += " Progress page for username: {1} with email address: {2}.".format(progress_url, student_to_reset.username, student_to_reset.email) except: - msg+="Couldn't find student with that username. " + msg += "Couldn't find student with that username. " #---------------------------------------- # export grades to remote gradebook - elif action=='List assignments available in remote gradebook': + elif action == 'List assignments available in remote gradebook': msg2, datatable = _do_remote_gradebook(request.user, course, 'get-assignments') msg += msg2 - elif action=='List assignments available for this course': + elif action == 'List assignments available for this course': log.debug(action) allgrades = get_student_grade_summary_data(request, course, course_id, get_grades=True, use_offline=use_offline) @@ -285,11 +287,11 @@ def instructor_dashboard(request, course_id): msg += 'assignments=
            %s
            ' % assignments - elif action=='List enrolled students matching remote gradebook': + elif action == 'List enrolled students matching remote gradebook': stud_data = get_student_grade_summary_data(request, course, course_id, get_grades=False, use_offline=use_offline) msg2, rg_stud_data = _do_remote_gradebook(request.user, course, 'get-membership') datatable = {'header': ['Student email', 'Match?']} - rg_students = [ x['email'] for x in rg_stud_data['retdata'] ] + rg_students = [x['email'] for x in rg_stud_data['retdata']] def domatch(x): return 'yes' if x.email in rg_students else 'No' datatable['data'] = [[x.email, domatch(x)] for x in stud_data['students']] @@ -300,7 +302,7 @@ def instructor_dashboard(request, course_id): log.debug(action) datatable = {} - aname = request.POST.get('assignment_name','') + aname = request.POST.get('assignment_name', '') if not aname: msg += "Please enter an assignment name" else: @@ -476,13 +478,13 @@ def instructor_dashboard(request, course_id): elif action == 'Enroll student': - student = request.POST.get('enstudent','') + student = request.POST.get('enstudent', '') ret = _do_enroll_students(course, course_id, student) datatable = ret['datatable'] elif action == 'Un-enroll student': - student = request.POST.get('enstudent','') + student = request.POST.get('enstudent', '') datatable = {} isok = False cea = CourseEnrollmentAllowed.objects.filter(course_id=course_id, email=student) @@ -506,7 +508,7 @@ def instructor_dashboard(request, course_id): elif action == 'Enroll multiple students': - students = request.POST.get('enroll_multiple','') + students = request.POST.get('enroll_multiple', '') ret = _do_enroll_students(course, course_id, students) datatable = ret['datatable'] @@ -519,8 +521,8 @@ def instructor_dashboard(request, course_id): 'Overload enrollment list using remote gradebook', 'Merge enrollment list with remote gradebook']: - section = request.POST.get('gradebook_section','') - msg2, datatable = _do_remote_gradebook(request.user, course, 'get-membership', dict(section=section) ) + section = request.POST.get('gradebook_section', '') + msg2, datatable = _do_remote_gradebook(request.user, course, 'get-membership', dict(section=section)) msg += msg2 if not 'List' in action: @@ -539,7 +541,7 @@ def instructor_dashboard(request, course_id): msg += nmsg track.views.server_track(request, 'psychometrics {0}'.format(problem), {}, page='idashboard') - if idash_mode=='Psychometrics': + if idash_mode == 'Psychometrics': problems = psychoanalyze.problems_with_psychometric_data(course_id) @@ -563,10 +565,10 @@ def instructor_dashboard(request, course_id): 'problems': problems, # psychometrics 'plots': plots, # psychometrics 'course_errors': modulestore().get_item_errors(course.location), - 'djangopid' : os.getpid(), - 'mitx_version' : getattr(settings,'MITX_VERSION_STRING',''), - 'offline_grade_log' : offline_grades_available(course_id), - 'cohorts_ajax_url' : reverse('cohorts', kwargs={'course_id': course_id}), + 'djangopid': os.getpid(), + 'mitx_version': getattr(settings, 'MITX_VERSION_STRING', ''), + 'offline_grade_log': offline_grades_available(course_id), + 'cohorts_ajax_url': reverse('cohorts', kwargs={'course_id': course_id}), } return render_to_response('courseware/instructor_dashboard.html', context) @@ -576,17 +578,17 @@ def _do_remote_gradebook(user, course, action, args=None, files=None): ''' Perform remote gradebook action. Returns msg, datatable. ''' - rg = course.metadata.get('remote_gradebook','') + rg = course.metadata.get('remote_gradebook', '') if not rg: msg = "No remote gradebook defined in course metadata" return msg, {} - rgurl = settings.MITX_FEATURES.get('REMOTE_GRADEBOOK_URL','') + rgurl = settings.MITX_FEATURES.get('REMOTE_GRADEBOOK_URL', '') if not rgurl: msg = "No remote gradebook url defined in settings.MITX_FEATURES" return msg, {} - rgname = rg.get('name','') + rgname = rg.get('name', '') if not rgname: msg = "No gradebook name defined in course remote_gradebook metadata" return msg, {} @@ -606,8 +608,8 @@ def _do_remote_gradebook(user, course, action, args=None, files=None): msg += "
            data=%s" % data return msg, {} - msg = '
            %s
            ' % retdict['msg'].replace('\n','
            ') - retdata = retdict['data'] # a list of dicts + msg = '
            %s
            ' % retdict['msg'].replace('\n', '
            ') + retdata = retdict['data'] # a list of dicts if retdata: datatable = {'header': retdata[0].keys()} @@ -619,6 +621,7 @@ def _do_remote_gradebook(user, course, action, args=None, files=None): return msg, datatable + def _list_course_forum_members(course_id, rolename, datatable): """ Fills in datatable with forum membership information, for a given role, @@ -672,7 +675,7 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove): log.debug('rolename={0}'.format(rolename)) if add_or_remove == FORUM_ROLE_REMOVE: if not alreadyexists: - msg ='Error: user "{0}" does not have rolename "{1}", cannot remove'.format(uname, rolename) + msg = 'Error: user "{0}" does not have rolename "{1}", cannot remove'.format(uname, rolename) else: user.roles.remove(role) msg = 'Removed "{0}" from "{1}" forum role = "{2}"'.format(user, course.id, rolename) @@ -688,6 +691,7 @@ def _update_forum_role_membership(uname, course, rolename, add_or_remove): return msg + def _group_members_table(group, title, course_id): """ Return a data table of usernames and names of users in group_name. @@ -756,6 +760,7 @@ def add_user_to_group(request, username_or_email, group, group_title, event_name """ return _add_or_remove_user_group(request, username_or_email, group, group_title, event_name, True) + def remove_user_from_group(request, username_or_email, group, group_title, event_name): """ Look up the given user by username (if no '@') or email (otherwise), and remove them from group. @@ -809,22 +814,22 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, data = [] for student in enrolled_students: - datarow = [ student.id, student.username, student.profile.name, student.email ] + datarow = [student.id, student.username, student.profile.name, student.email] try: datarow.append(student.externalauthmap.external_email) - except: # ExternalAuthMap.DoesNotExist + except: # ExternalAuthMap.DoesNotExist datarow.append('') if get_grades: gradeset = student_grades(student, request, course, keep_raw_scores=get_raw_scores, use_offline=use_offline) - log.debug('student={0}, gradeset={1}'.format(student,gradeset)) + log.debug('student={0}, gradeset={1}'.format(student, gradeset)) if get_raw_scores: # TODO (ichuang) encode Score as dict instead of as list, so score[0] -> score['earned'] - sgrades = [(getattr(score,'earned','') or score[0]) for score in gradeset['raw_scores']] + sgrades = [(getattr(score, 'earned', '') or score[0]) for score in gradeset['raw_scores']] else: sgrades = [x['percent'] for x in gradeset['section_breakdown']] datarow += sgrades - student.grades = sgrades # store in student object + student.grades = sgrades # store in student object data.append(datarow) datatable['data'] = data @@ -832,6 +837,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, #----------------------------------------------------------------------------- + @cache_control(no_cache=True, no_store=True, must_revalidate=True) def gradebook(request, course_id): """ @@ -886,9 +892,9 @@ def _do_enroll_students(course, course_id, students, overload=False): if '' in new_students: new_students.remove('') - status = dict([x,'unprocessed'] for x in new_students) + status = dict([x, 'unprocessed'] for x in new_students) - if overload: # delete all but staff + if overload: # delete all but staff todelete = CourseEnrollment.objects.filter(course_id=course_id) for ce in todelete: if not has_access(ce.user, course, 'staff') and ce.user.email.lower() not in new_students_lc: @@ -903,7 +909,7 @@ def _do_enroll_students(course, course_id, students, overload=False): for student in new_students: try: - user=User.objects.get(email=student) + user = User.objects.get(email=student) except User.DoesNotExist: # user not signed up yet, put in pending enrollment allowed table if CourseEnrollmentAllowed.objects.filter(email=student, course_id=course_id): @@ -928,9 +934,9 @@ def _do_enroll_students(course, course_id, students, overload=False): datatable['data'] = [[x, status[x]] for x in status] datatable['title'] = 'Enrollment of students' - def sf(stat): return [x for x in status if status[x]==stat] + def sf(stat): return [x for x in status if status[x] == stat] - data = dict(added=sf('added'), rejected=sf('rejected')+sf('exists'), + data = dict(added=sf('added'), rejected=sf('rejected') + sf('exists'), deleted=sf('deleted'), datatable=datatable) return data @@ -1013,5 +1019,5 @@ def compute_course_stats(course): walk(c) walk(course) - stats = dict(counts) # number of each kind of module + stats = dict(counts) # number of each kind of module return stats diff --git a/lms/djangoapps/licenses/migrations/0001_initial.py b/lms/djangoapps/licenses/migrations/0001_initial.py index bdc1d3ead4..365046272d 100644 --- a/lms/djangoapps/licenses/migrations/0001_initial.py +++ b/lms/djangoapps/licenses/migrations/0001_initial.py @@ -115,4 +115,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['licenses'] \ No newline at end of file + complete_apps = ['licenses'] diff --git a/lms/djangoapps/lms_migration/management/commands/create_groups.py b/lms/djangoapps/lms_migration/management/commands/create_groups.py index 7b52795606..95c9e4238b 100644 --- a/lms/djangoapps/lms_migration/management/commands/create_groups.py +++ b/lms/djangoapps/lms_migration/management/commands/create_groups.py @@ -4,7 +4,10 @@ # # Create all staff_* groups for classes in data directory. -import os, sys, string, re +import os +import sys +import string +import re from django.core.management.base import BaseCommand from django.conf import settings @@ -12,6 +15,7 @@ from django.contrib.auth.models import User, Group from path import path from lxml import etree + def create_groups(): ''' Create staff and instructor groups for all classes in the data_dir @@ -26,7 +30,7 @@ def create_groups(): continue if not os.path.isdir(path(data_dir) / course_dir): continue - + cxfn = path(data_dir) / course_dir / 'course.xml' try: coursexml = etree.parse(cxfn) @@ -38,11 +42,12 @@ def create_groups(): if course is None: print "oops, can't get course id for %s" % course_dir continue - print "course=%s for course_dir=%s" % (course,course_dir) - + print "course=%s for course_dir=%s" % (course, course_dir) + create_group('staff_%s' % course) # staff group create_group('instructor_%s' % course) # instructor group (can manage staff group list) + def create_group(gname): if Group.objects.filter(name=gname): print " group exists for %s" % gname @@ -51,6 +56,7 @@ def create_group(gname): g.save() print " created group %s" % gname + class Command(BaseCommand): help = "Create groups associated with all courses in data_dir." diff --git a/lms/djangoapps/lms_migration/management/commands/create_user.py b/lms/djangoapps/lms_migration/management/commands/create_user.py index 7d39accc44..86b355e571 100644 --- a/lms/djangoapps/lms_migration/management/commands/create_user.py +++ b/lms/djangoapps/lms_migration/management/commands/create_user.py @@ -4,7 +4,10 @@ # # Create user. Prompt for groups and ExternalAuthMap -import os, sys, string, re +import os +import sys +import string +import re import datetime from getpass import getpass import json @@ -16,6 +19,7 @@ from student.models import UserProfile, Registration from external_auth.models import ExternalAuthMap from django.contrib.auth.models import User, Group + class MyCompleter(object): # Custom completer def __init__(self, options): @@ -24,23 +28,25 @@ class MyCompleter(object): # Custom completer def complete(self, text, state): if state == 0: # on first trigger, build possible matches if text: # cache matches (entries that start with entered text) - self.matches = [s for s in self.options + self.matches = [s for s in self.options if s and s.startswith(text)] else: # no text entered, all matches possible self.matches = self.options[:] # return match indexed by state - try: + try: return self.matches[state] except IndexError: return None + def GenPasswd(length=8, chars=string.letters + string.digits): return ''.join([choice(chars) for i in range(length)]) #----------------------------------------------------------------------------- # main command + class Command(BaseCommand): help = "Create user, interactively; can add ExternalAuthMap for MIT user if email@MIT.EDU resolves properly." @@ -52,27 +58,27 @@ class Command(BaseCommand): print "username %s already taken" % uname else: break - + make_eamap = False - if raw_input('Create MIT ExternalAuth? [n] ').lower()=='y': + if raw_input('Create MIT ExternalAuth? [n] ').lower() == 'y': email = '%s@MIT.EDU' % uname if not email.endswith('@MIT.EDU'): print "Failed - email must be @MIT.EDU" sys.exit(-1) mit_domain = 'ssl:MIT' - if ExternalAuthMap.objects.filter(external_id = email, external_domain = mit_domain): + if ExternalAuthMap.objects.filter(external_id=email, external_domain=mit_domain): print "Failed - email %s already exists as external_id" % email sys.exit(-1) make_eamap = True password = GenPasswd(12) - + # get name from kerberos try: kname = os.popen("finger %s | grep 'name:'" % email).read().strip().split('name: ')[1].strip() except: kname = '' name = raw_input('Full name: [%s] ' % kname).strip() - if name=='': + if name == '': name = kname print "name = %s" % name else: @@ -82,17 +88,17 @@ class Command(BaseCommand): if password == password2: break print "Oops, passwords do not match, please retry" - + while True: email = raw_input('email: ') if User.objects.filter(email=email): print "email %s already taken" % email else: break - + name = raw_input('Full name: ') - - + + user = User(username=uname, email=email, is_active=True) user.set_password(password) try: @@ -100,41 +106,41 @@ class Command(BaseCommand): except IntegrityError: print "Oops, failed to create user %s, IntegrityError" % user raise - + r = Registration() r.register(user) - + up = UserProfile(user=user) up.name = name up.save() - + if make_eamap: - credentials = "/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN=%s/emailAddress=%s" % (name,email) - eamap = ExternalAuthMap(external_id = email, - external_email = email, - external_domain = mit_domain, - external_name = name, - internal_password = password, - external_credentials = json.dumps(credentials), + credentials = "/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN=%s/emailAddress=%s" % (name, email) + eamap = ExternalAuthMap(external_id=email, + external_email=email, + external_domain=mit_domain, + external_name=name, + internal_password=password, + external_credentials=json.dumps(credentials), ) eamap.user = user eamap.dtsignup = datetime.datetime.now() eamap.save() - + print "User %s created successfully!" % user - - if not raw_input('Add user %s to any groups? [n] ' % user).lower()=='y': + + if not raw_input('Add user %s to any groups? [n] ' % user).lower() == 'y': sys.exit(0) - + print "Here are the groups available:" - + groups = [str(g.name) for g in Group.objects.all()] print groups - + completer = MyCompleter(groups) readline.set_completer(completer.complete) readline.parse_and_bind('tab: complete') - + while True: gname = raw_input("Add group (tab to autocomplete, empty line to end): ") if not gname: @@ -144,6 +150,6 @@ class Command(BaseCommand): continue g = Group.objects.get(name=gname) user.groups.add(g) - print "Added %s to group %s" % (user,g) - + print "Added %s to group %s" % (user, g) + print "Done!" diff --git a/lms/djangoapps/lms_migration/management/commands/manage_course_groups.py b/lms/djangoapps/lms_migration/management/commands/manage_course_groups.py index f3a39db5ca..b63ef7859b 100644 --- a/lms/djangoapps/lms_migration/management/commands/manage_course_groups.py +++ b/lms/djangoapps/lms_migration/management/commands/manage_course_groups.py @@ -4,7 +4,10 @@ # # interactively list and edit membership in course staff and instructor groups -import os, sys, string, re +import os +import sys +import string +import re import datetime from getpass import getpass import json @@ -17,26 +20,27 @@ from django.contrib.auth.models import User, Group #----------------------------------------------------------------------------- # get all staff groups + class Command(BaseCommand): help = "Manage course group membership, interactively." def handle(self, *args, **options): gset = Group.objects.all() - + print "Groups:" - for cnt,g in zip(range(len(gset)), gset): - print "%d. %s" % (cnt,g) - + for cnt, g in zip(range(len(gset)), gset): + print "%d. %s" % (cnt, g) + gnum = int(raw_input('Choose group to manage (enter #): ')) - + group = gset[gnum] - + #----------------------------------------------------------------------------- # users in group - + uall = User.objects.all() - if uall.count()<50: + if uall.count() < 50: print "----" print "List of All Users: %s" % [str(x.username) for x in uall] print "----" @@ -44,24 +48,24 @@ class Command(BaseCommand): print "----" print "There are %d users, which is too many to list" % uall.count() print "----" - + while True: - + print "Users in the group:" - + uset = group.user_set.all() for cnt, u in zip(range(len(uset)), uset): print "%d. %s" % (cnt, u) - + action = raw_input('Choose user to delete (enter #) or enter usernames (comma delim) to add: ') - - m = re.match('^[0-9]+$',action) + + m = re.match('^[0-9]+$', action) if m: unum = int(action) u = uset[unum] print "Deleting user %s" % u u.groups.remove(group) - + else: for uname in action.split(','): try: @@ -71,6 +75,3 @@ class Command(BaseCommand): continue print "adding %s to group %s" % (user, group) user.groups.add(group) - - - diff --git a/lms/djangoapps/lms_migration/migrate.py b/lms/djangoapps/lms_migration/migrate.py index ecde31d6dd..9cdc783bb9 100644 --- a/lms/djangoapps/lms_migration/migrate.py +++ b/lms/djangoapps/lms_migration/migrate.py @@ -22,29 +22,32 @@ log = logging.getLogger("mitx.lms_migrate") LOCAL_DEBUG = True ALLOWED_IPS = settings.LMS_MIGRATION_ALLOWED_IPS + def escape(s): """escape HTML special characters in string""" - return str(s).replace('<','<').replace('>','>') + return str(s).replace('<', '<').replace('>', '>') + def getip(request): ''' Extract IP address of requester from header, even if behind proxy ''' - ip = request.META.get('HTTP_X_REAL_IP','') # nginx reverse proxy + ip = request.META.get('HTTP_X_REAL_IP', '') # nginx reverse proxy if not ip: - ip = request.META.get('REMOTE_ADDR','None') + ip = request.META.get('REMOTE_ADDR', 'None') return ip def get_commit_id(course): - return course.metadata.get('GIT_COMMIT_ID','No commit id') + return course.metadata.get('GIT_COMMIT_ID', 'No commit id') # getattr(def_ms.courses[reload_dir], 'GIT_COMMIT_ID','No commit id') -def set_commit_id(course,commit_id): +def set_commit_id(course, commit_id): course.metadata['GIT_COMMIT_ID'] = commit_id # setattr(def_ms.courses[reload_dir], 'GIT_COMMIT_ID', new_commit_id) + def manage_modulestores(request, reload_dir=None, commit_id=None): ''' Manage the static in-memory modulestores. @@ -65,7 +68,7 @@ def manage_modulestores(request, reload_dir=None, commit_id=None): html += '

            IP address: %s

            ' % ip html += '

            User: %s

            ' % request.user html += '

            My pid: %s

            ' % os.getpid() - log.debug('request from ip=%s, user=%s' % (ip,request.user)) + log.debug('request from ip=%s, user=%s' % (ip, request.user)) if not (ip in ALLOWED_IPS or 'any' in ALLOWED_IPS): if request.user and request.user.is_staff: @@ -89,7 +92,7 @@ def manage_modulestores(request, reload_dir=None, commit_id=None): log.debug('commit_id="%s"' % commit_id) log.debug('current_commit_id="%s"' % current_commit_id) - if (commit_id is not None) and (commit_id==current_commit_id): + if (commit_id is not None) and (commit_id == current_commit_id): html += "

            Already at commit id %s for %s

            " % (commit_id, reload_dir) track.views.server_track(request, 'reload %s skipped already at %s (pid=%s)' % (reload_dir, @@ -100,7 +103,7 @@ def manage_modulestores(request, reload_dir=None, commit_id=None): else: html += '

            Reloaded course directory "%s"

            ' % reload_dir def_ms.try_load_course(reload_dir) - gdir = settings.DATA_DIR / reload_dir + gdir = settings.DATA_DIR / reload_dir new_commit_id = os.popen('cd %s; git log -n 1 | head -1' % gdir).read().strip().split(' ')[1] set_commit_id(def_ms.courses[reload_dir], new_commit_id) html += '

            commit_id=%s

            ' % new_commit_id @@ -121,21 +124,21 @@ def manage_modulestores(request, reload_dir=None, commit_id=None): #---------------------------------------- - dumpfields = ['definition','location','metadata'] + dumpfields = ['definition', 'location', 'metadata'] for cdir, course in def_ms.courses.items(): html += '
            ' - html += '

            Course: %s (%s)

            ' % (course.display_name,cdir) + html += '

            Course: %s (%s)

            ' % (course.display_name, cdir) html += '

            commit_id=%s

            ' % get_commit_id(course) for field in dumpfields: - data = getattr(course,field) + data = getattr(course, field) html += '

            %s

            ' % field - if type(data)==dict: + if type(data) == dict: html += '
              ' - for k,v in data.items(): - html += '
            • %s:%s
            • ' % (escape(k),escape(v)) + for k, v in data.items(): + html += '
            • %s:%s
            • ' % (escape(k), escape(v)) html += '
            ' else: html += '
            • %s
            ' % escape(data) @@ -159,6 +162,7 @@ def manage_modulestores(request, reload_dir=None, commit_id=None): html += "" return HttpResponse(html) + @csrf_exempt def gitreload(request, reload_dir=None): ''' @@ -172,8 +176,8 @@ def gitreload(request, reload_dir=None): html += '

            IP address: %s ' % ip html += '

            User: %s ' % request.user - ALLOWED_IPS = [] # allow none by default - if hasattr(settings,'ALLOWED_GITRELOAD_IPS'): # allow override in settings + ALLOWED_IPS = [] # allow none by default + if hasattr(settings, 'ALLOWED_GITRELOAD_IPS'): # allow override in settings ALLOWED_IPS = settings.ALLOWED_GITRELOAD_IPS if not (ip in ALLOWED_IPS or 'any' in ALLOWED_IPS): @@ -182,9 +186,9 @@ def gitreload(request, reload_dir=None): else: html += 'Permission denied' html += "" - log.debug('request denied from %s, ALLOWED_IPS=%s' % (ip,ALLOWED_IPS)) - return HttpResponse(html) - + log.debug('request denied from %s, ALLOWED_IPS=%s' % (ip, ALLOWED_IPS)) + return HttpResponse(html) + #---------------------------------------- # see if request is from github (POST with JSON) @@ -195,19 +199,19 @@ def gitreload(request, reload_dir=None): log.debug("gitargs=%s" % gitargs) reload_dir = gitargs['repository']['name'] log.debug("github reload_dir=%s" % reload_dir) - gdir = settings.DATA_DIR / reload_dir + gdir = settings.DATA_DIR / reload_dir if not os.path.exists(gdir): log.debug("====> ERROR in gitreload - no such directory %s" % reload_dir) return HttpResponse('Error') cmd = "cd %s; git reset --hard HEAD; git clean -f -d; git pull origin; chmod g+w course.xml" % gdir log.debug(os.popen(cmd).read()) - if hasattr(settings,'GITRELOAD_HOOK'): # hit this hook after reload, if set + if hasattr(settings, 'GITRELOAD_HOOK'): # hit this hook after reload, if set gh = settings.GITRELOAD_HOOK if gh: - ghurl = '%s/%s' % (gh,reload_dir) + ghurl = '%s/%s' % (gh, reload_dir) r = requests.get(ghurl) log.debug("GITRELOAD_HOOK to %s: %s" % (ghurl, r.text)) - + #---------------------------------------- # reload course if specified @@ -220,4 +224,4 @@ def gitreload(request, reload_dir=None): def_ms.try_load_course(reload_dir) track.views.server_track(request, 'reloaded %s' % reload_dir, {}, page='migrate') - return HttpResponse(html) + return HttpResponse(html) diff --git a/lms/djangoapps/open_ended_grading/controller_query_service.py b/lms/djangoapps/open_ended_grading/controller_query_service.py index 5d2c40b6ce..83d5617bd2 100644 --- a/lms/djangoapps/open_ended_grading/controller_query_service.py +++ b/lms/djangoapps/open_ended_grading/controller_query_service.py @@ -12,12 +12,13 @@ from mitxmako.shortcuts import render_to_string log = logging.getLogger(__name__) + class ControllerQueryService(GradingService): """ Interface to staff grading backend. """ def __init__(self, config): - config['system'] = ModuleSystem(None,None,None,render_to_string,None) + config['system'] = ModuleSystem(None, None, None, render_to_string, None) super(ControllerQueryService, self).__init__(config) self.check_eta_url = self.url + '/get_submission_eta/' self.is_unique_url = self.url + '/is_name_unique/' @@ -29,34 +30,34 @@ class ControllerQueryService(GradingService): def check_if_name_is_unique(self, location, problem_id, course_id): params = { 'course_id': course_id, - 'location' : location, - 'problem_id' : problem_id + 'location': location, + 'problem_id': problem_id } response = self.get(self.is_unique_url, params) return response def check_for_eta(self, location): params = { - 'location' : location, + 'location': location, } response = self.get(self.check_eta_url, params) return response def check_combined_notifications(self, course_id, student_id, user_is_staff, last_time_viewed): - params= { - 'student_id' : student_id, - 'course_id' : course_id, - 'user_is_staff' : user_is_staff, - 'last_time_viewed' : last_time_viewed, + params = { + 'student_id': student_id, + 'course_id': course_id, + 'user_is_staff': user_is_staff, + 'last_time_viewed': last_time_viewed, } log.debug(self.combined_notifications_url) - response = self.get(self.combined_notifications_url,params) + response = self.get(self.combined_notifications_url, params) return response def get_grading_status_list(self, course_id, student_id): params = { - 'student_id' : student_id, - 'course_id' : course_id, + 'student_id': student_id, + 'course_id': course_id, } response = self.get(self.grading_status_list_url, params) @@ -64,7 +65,7 @@ class ControllerQueryService(GradingService): def get_flagged_problem_list(self, course_id): params = { - 'course_id' : course_id, + 'course_id': course_id, } response = self.get(self.flagged_problem_list_url, params) @@ -72,12 +73,11 @@ class ControllerQueryService(GradingService): def take_action_on_flags(self, course_id, student_id, submission_id, action_type): params = { - 'course_id' : course_id, - 'student_id' : student_id, - 'submission_id' : submission_id, - 'action_type' : action_type + 'course_id': course_id, + 'student_id': student_id, + 'submission_id': submission_id, + 'action_type': action_type } response = self.post(self.take_action_on_flags_url, params) return response - diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index b8b323acad..f79013e396 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -14,7 +14,7 @@ from xmodule import peer_grading_service from xmodule.x_module import ModuleSystem from mitxmako.shortcuts import render_to_string -log=logging.getLogger(__name__) +log = logging.getLogger(__name__) NOTIFICATION_CACHE_TIME = 300 KEY_PREFIX = "open_ended_" @@ -26,10 +26,11 @@ NOTIFICATION_TYPES = ( ('flagged_submissions_exist', 'open_ended_flagged_problems', 'Flagged Submissions') ) + def staff_grading_notifications(course, user): staff_gs = StaffGradingService(settings.STAFF_GRADING_INTERFACE) - pending_grading=False - img_path= "" + pending_grading = False + img_path = "" course_id = course.id student_id = unique_id_for_user(user) notification_type = "staff" @@ -42,7 +43,7 @@ def staff_grading_notifications(course, user): notifications = json.loads(staff_gs.get_notifications(course_id)) if notifications['success']: if notifications['staff_needs_to_grade']: - pending_grading=True + pending_grading = True except: #Non catastrophic error, so no real action notifications = {} @@ -51,17 +52,18 @@ def staff_grading_notifications(course, user): if pending_grading: img_path = "/static/images/slider-handle.png" - notification_dict = {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + notification_dict = {'pending_grading': pending_grading, 'img_path': img_path, 'response': notifications} set_value_in_cache(student_id, course_id, notification_type, notification_dict) return notification_dict + def peer_grading_notifications(course, user): - system = ModuleSystem(None,None,None,render_to_string,None) + system = ModuleSystem(None, None, None, render_to_string, None) peer_gs = peer_grading_service.PeerGradingService(settings.PEER_GRADING_INTERFACE, system) - pending_grading=False - img_path= "" + pending_grading = False + img_path = "" course_id = course.id student_id = unique_id_for_user(user) notification_type = "peer" @@ -71,10 +73,10 @@ def peer_grading_notifications(course, user): return notification_dict try: - notifications = json.loads(peer_gs.get_notifications(course_id,student_id)) + notifications = json.loads(peer_gs.get_notifications(course_id, student_id)) if notifications['success']: if notifications['student_needs_to_peer_grade']: - pending_grading=True + pending_grading = True except: #Non catastrophic error, so no real action notifications = {} @@ -83,12 +85,13 @@ def peer_grading_notifications(course, user): if pending_grading: img_path = "/static/images/slider-handle.png" - notification_dict = {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + notification_dict = {'pending_grading': pending_grading, 'img_path': img_path, 'response': notifications} set_value_in_cache(student_id, course_id, notification_type, notification_dict) return notification_dict + def combined_notifications(course, user): controller_url = open_ended_util.get_controller_url() controller_qs = ControllerQueryService(controller_url) @@ -102,24 +105,24 @@ def combined_notifications(course, user): return notification_dict min_time_to_query = user.last_login - last_module_seen = StudentModule.objects.filter(student=user, course_id = course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified') + last_module_seen = StudentModule.objects.filter(student=user, course_id=course_id, modified__gt=min_time_to_query).values('modified').order_by('-modified') last_module_seen_count = last_module_seen.count() - if last_module_seen_count>0: + if last_module_seen_count > 0: last_time_viewed = last_module_seen[0]['modified'] - datetime.timedelta(seconds=(NOTIFICATION_CACHE_TIME + 60)) else: last_time_viewed = user.last_login - pending_grading= False + pending_grading = False - img_path= "" + img_path = "" try: - controller_response = controller_qs.check_combined_notifications(course.id,student_id, user_is_staff, last_time_viewed) + controller_response = controller_qs.check_combined_notifications(course.id, student_id, user_is_staff, last_time_viewed) log.debug(controller_response) notifications = json.loads(controller_response) if notifications['success']: if notifications['overall_need_to_check']: - pending_grading=True + pending_grading = True except: #Non catastrophic error, so no real action notifications = {} @@ -128,36 +131,41 @@ def combined_notifications(course, user): if pending_grading: img_path = "/static/images/slider-handle.png" - notification_dict = {'pending_grading' : pending_grading, 'img_path' : img_path, 'response' : notifications} + notification_dict = {'pending_grading': pending_grading, 'img_path': img_path, 'response': notifications} set_value_in_cache(student_id, course_id, notification_type, notification_dict) return notification_dict + def get_value_from_cache(student_id, course_id, notification_type): key_name = create_key_name(student_id, course_id, notification_type) success, value = _get_value_from_cache(key_name) return success, value + def set_value_in_cache(student_id, course_id, notification_type, value): key_name = create_key_name(student_id, course_id, notification_type) _set_value_in_cache(key_name, value) + def create_key_name(student_id, course_id, notification_type): key_name = "{prefix}{type}_{course}_{student}".format(prefix=KEY_PREFIX, type=notification_type, course=course_id, student=student_id) return key_name + def _get_value_from_cache(key_name): value = cache.get(key_name) success = False if value is None: - return success , value + return success, value try: value = json.loads(value) success = True except: pass - return success , value + return success, value + def _set_value_in_cache(key_name, value): - cache.set(key_name, json.dumps(value), NOTIFICATION_CACHE_TIME) \ No newline at end of file + cache.set(key_name, json.dumps(value), NOTIFICATION_CACHE_TIME) diff --git a/lms/djangoapps/open_ended_grading/open_ended_util.py b/lms/djangoapps/open_ended_grading/open_ended_util.py index 07744d7d2c..1aa0f1ba70 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_util.py +++ b/lms/djangoapps/open_ended_grading/open_ended_util.py @@ -1,12 +1,13 @@ from django.conf import settings import logging -log=logging.getLogger(__name__) +log = logging.getLogger(__name__) + def get_controller_url(): peer_grading_url = settings.PEER_GRADING_INTERFACE['url'] split_url = peer_grading_url.split("/") controller_url = "http://" + split_url[2] + "/grading_controller" - controller_settings=settings.PEER_GRADING_INTERFACE.copy() + controller_settings = settings.PEER_GRADING_INTERFACE.copy() controller_settings['url'] = controller_url return controller_settings diff --git a/lms/djangoapps/open_ended_grading/staff_grading.py b/lms/djangoapps/open_ended_grading/staff_grading.py index 7a48b25a49..e39b26da56 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading.py +++ b/lms/djangoapps/open_ended_grading/staff_grading.py @@ -22,4 +22,3 @@ class StaffGrading(object): return "Instructor grading!" # context = {} # return render_to_string('courseware/instructor_grading_view.html', context) - diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index d8bee99ac7..dfadacb724 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -21,6 +21,7 @@ from mitxmako.shortcuts import render_to_string log = logging.getLogger(__name__) + class MockStaffGradingService(object): """ A simple mockup of a staff grading service, testing. @@ -28,7 +29,7 @@ class MockStaffGradingService(object): def __init__(self): self.cnt = 0 - def get_next(self,course_id, location, grader_id): + def get_next(self, course_id, location, grader_id): self.cnt += 1 return json.dumps({'success': True, 'submission_id': self.cnt, @@ -61,7 +62,7 @@ class StaffGradingService(GradingService): Interface to staff grading backend. """ def __init__(self, config): - config['system'] = ModuleSystem(None,None,None,render_to_string,None) + config['system'] = ModuleSystem(None, None, None, render_to_string, None) super(StaffGradingService, self).__init__(config) self.get_next_url = self.url + '/get_next_submission/' self.save_grade_url = self.url + '/save_grade/' @@ -85,7 +86,7 @@ class StaffGradingService(GradingService): Raises: GradingServiceError: something went wrong with the connection. """ - params = {'course_id': course_id,'grader_id': grader_id} + params = {'course_id': course_id, 'grader_id': grader_id} return self.get(self.get_problem_list_url, params) @@ -166,6 +167,7 @@ def staff_grading_service(): return _service + def _err_response(msg): """ Return a HttpResponse with a json dump with success=False, and the given error message. @@ -329,4 +331,3 @@ def save_grade(request, course_id): # Ok, save_grade seemed to work. Get the next submission to grade. return HttpResponse(_get_next(course_id, grader_id, location), mimetype="application/json") - diff --git a/lms/djangoapps/open_ended_grading/tests.py b/lms/djangoapps/open_ended_grading/tests.py index 3ee8352c5c..4d220d4baa 100644 --- a/lms/djangoapps/open_ended_grading/tests.py +++ b/lms/djangoapps/open_ended_grading/tests.py @@ -44,7 +44,7 @@ class TestStaffGradingService(ct.PageLoader): self.create_account('u2', self.instructor, self.password) self.activate_user(self.student) self.activate_user(self.instructor) - + self.course_id = "edX/toy/2012_Fall" self.toy = modulestore().get_course(self.course_id) def make_instructor(course): @@ -118,7 +118,7 @@ class TestStaffGradingService(ct.PageLoader): self.assertTrue(d['success'], str(d)) self.assertIsNotNone(d['problem_list']) - + @override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE) class TestPeerGradingService(ct.PageLoader): ''' @@ -137,7 +137,7 @@ class TestPeerGradingService(ct.PageLoader): self.create_account('u2', self.instructor, self.password) self.activate_user(self.student) self.activate_user(self.instructor) - + self.course_id = "edX/toy/2012_Fall" self.toy = modulestore().get_course(self.course_id) location = "i4x://edX/toy/peergrading/init" @@ -146,7 +146,7 @@ class TestPeerGradingService(ct.PageLoader): self.system = ModuleSystem(location, None, None, render_to_string, None) self.descriptor = peer_grading_module.PeerGradingDescriptor(self.system) - self.peer_module = peer_grading_module.PeerGradingModule(self.system,location,"",self.descriptor) + self.peer_module = peer_grading_module.PeerGradingModule(self.system, location, "", self.descriptor) self.peer_module.peer_gs = self.mock_service self.logout() @@ -171,7 +171,7 @@ class TestPeerGradingService(ct.PageLoader): def test_save_grade_success(self): raise SkipTest() data = 'rubric_scores[]=1|rubric_scores[]=2|location=' + self.location + '|submission_id=1|submission_key=fake key|score=2|feedback=feedback|submission_flagged=False' - qdict = QueryDict(data.replace("|","&")) + qdict = QueryDict(data.replace("|", "&")) r = self.peer_module.save_grade(qdict) d = r self.assertTrue(d['success']) @@ -222,7 +222,7 @@ class TestPeerGradingService(ct.PageLoader): def test_save_calibration_essay_success(self): raise SkipTest() data = 'rubric_scores[]=1|rubric_scores[]=2|location=' + self.location + '|submission_id=1|submission_key=fake key|score=2|feedback=feedback|submission_flagged=False' - qdict = QueryDict(data.replace("|","&")) + qdict = QueryDict(data.replace("|", "&")) r = self.peer_module.save_calibration_essay(qdict) d = r self.assertTrue(d['success']) @@ -235,4 +235,3 @@ class TestPeerGradingService(ct.PageLoader): self.assertFalse(d['success']) self.assertTrue(d['error'].find('Missing required keys:') > -1) self.assertFalse('actual_score' in d) - diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index af7f930207..f2e2a4513e 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -10,7 +10,7 @@ from mitxmako.shortcuts import render_to_response from django.core.urlresolvers import reverse from student.models import unique_id_for_user -from courseware.courses import get_course_with_access +from courseware.courses import get_course_with_access from controller_query_service import ControllerQueryService from xmodule.grading_service_module import GradingServiceError @@ -38,12 +38,15 @@ Reverses the URL from the name and the course id, and then adds a trailing slash it does not exist yet """ + + def _reverse_with_slash(url_name, course_id): ajax_url = _reverse_without_slash(url_name, course_id) if not ajax_url.endswith('/'): ajax_url += '/' return ajax_url + def _reverse_without_slash(url_name, course_id): ajax_url = reverse(url_name, kwargs={'course_id': course_id}) return ajax_url @@ -52,14 +55,16 @@ DESCRIPTION_DICT = { 'Peer Grading': "View all problems that require peer assessment in this particular course.", 'Staff Grading': "View ungraded submissions submitted by students for the open ended problems in the course.", 'Problems you have submitted': "View open ended problems that you have previously submitted for grading.", - 'Flagged Submissions' : "View submissions that have been flagged by students as inappropriate." + 'Flagged Submissions': "View submissions that have been flagged by students as inappropriate." } ALERT_DICT = { 'Peer Grading': "New submissions to grade", 'Staff Grading': "New submissions to grade", 'Problems you have submitted': "New grades have been returned", - 'Flagged Submissions' : "Submissions have been flagged for review" + 'Flagged Submissions': "Submissions have been flagged for review" } + + @cache_control(no_cache=True, no_store=True, must_revalidate=True) def staff_grading(request, course_id): """ @@ -68,7 +73,7 @@ def staff_grading(request, course_id): course = get_course_with_access(request.user, course_id, 'staff') ajax_url = _reverse_with_slash('staff_grading', course_id) - + return render_to_response('instructor/staff_grading.html', { 'course': course, 'course_id': course_id, @@ -76,6 +81,7 @@ def staff_grading(request, course_id): # Checked above 'staff_access': True, }) + @cache_control(no_cache=True, no_store=True, must_revalidate=True) def peer_grading(request, course_id): ''' @@ -98,6 +104,7 @@ def peer_grading(request, course_id): log.exception(error_message + "Current course is: {0}".format(course_id)) return HttpResponse(error_message) + def generate_problem_url(problem_url_parts, base_course_url): """ From a list of problem url parts generated by search.path_to_location and a base course url, generates a url to a problem @@ -106,10 +113,10 @@ def generate_problem_url(problem_url_parts, base_course_url): @return: A path to the problem """ problem_url = base_course_url + "/" - for z in xrange(0,len(problem_url_parts)): + for z in xrange(0, len(problem_url_parts)): part = problem_url_parts[z] if part is not None: - if z==1: + if z == 1: problem_url += "courseware/" problem_url += part + "/" return problem_url @@ -139,10 +146,10 @@ def student_problem_list(request, course_id): else: problem_list = problem_list_dict['problem_list'] - for i in xrange(0,len(problem_list)): + for i in xrange(0, len(problem_list)): problem_url_parts = search.path_to_location(modulestore(), course.id, problem_list[i]['location']) problem_url = generate_problem_url(problem_url_parts, base_course_url) - problem_list[i].update({'actual_url' : problem_url}) + problem_list[i].update({'actual_url': problem_url}) """ except GradingServiceError: @@ -166,6 +173,7 @@ def student_problem_list(request, course_id): # Checked above 'staff_access': False, }) + @cache_control(no_cache=True, no_store=True, must_revalidate=True) def flagged_problem_list(request, course_id): ''' @@ -186,7 +194,7 @@ def flagged_problem_list(request, course_id): success = problem_list_dict['success'] if 'error' in problem_list_dict: error_text = problem_list_dict['error'] - problem_list=[] + problem_list = [] else: problem_list = problem_list_dict['flagged_submissions'] @@ -211,6 +219,7 @@ def flagged_problem_list(request, course_id): } return render_to_response('open_ended_problems/open_ended_flagged_problems.html', context) + @cache_control(no_cache=True, no_store=True, must_revalidate=True) def combined_notifications(request, course_id): """ @@ -220,11 +229,11 @@ def combined_notifications(request, course_id): user = request.user notifications = open_ended_notifications.combined_notifications(course, user) response = notifications['response'] - notification_tuples=open_ended_notifications.NOTIFICATION_TYPES + notification_tuples = open_ended_notifications.NOTIFICATION_TYPES notification_list = [] - for response_num in xrange(0,len(notification_tuples)): - tag=notification_tuples[response_num][0] + for response_num in xrange(0, len(notification_tuples)): + tag = notification_tuples[response_num][0] if tag in response: url_name = notification_tuples[response_num][1] human_name = notification_tuples[response_num][2] @@ -241,11 +250,11 @@ def combined_notifications(request, course_id): alert_message = ALERT_DICT[human_name] else: alert_message = "" - + notification_item = { - 'url' : url, - 'name' : human_name, - 'alert' : has_img, + 'url': url, + 'name': human_name, + 'alert': has_img, 'description': description, 'alert_message': alert_message } @@ -253,17 +262,18 @@ def combined_notifications(request, course_id): ajax_url = _reverse_with_slash('open_ended_notifications', course_id) combined_dict = { - 'error_text' : "", - 'notification_list' : notification_list, - 'course' : course, - 'success' : True, - 'ajax_url' : ajax_url, + 'error_text': "", + 'notification_list': notification_list, + 'course': course, + 'success': True, + 'ajax_url': ajax_url, } return render_to_response('open_ended_problems/combined_notifications.html', combined_dict ) + @cache_control(no_cache=True, no_store=True, must_revalidate=True) def take_action_on_flags(request, course_id): """ @@ -293,5 +303,3 @@ def take_action_on_flags(request, course_id): except GradingServiceError: log.exception("Error saving calibration grade, submission_id: {0}, submission_key: {1}, grader_id: {2}".format(submission_id, submission_key, grader_id)) return _err_response('Could not connect to grading service') - - diff --git a/lms/djangoapps/portal/features/common.py b/lms/djangoapps/portal/features/common.py index 20c2ab56b8..8bfb548367 100644 --- a/lms/djangoapps/portal/features/common.py +++ b/lms/djangoapps/portal/features/common.py @@ -1,4 +1,4 @@ -from lettuce import world, step#, before, after +from lettuce import world, step # , before, after from factories import * from django.core.management import call_command from nose.tools import assert_equals, assert_in @@ -11,74 +11,90 @@ import time from logging import getLogger logger = getLogger(__name__) + @step(u'I wait (?:for )?"(\d+)" seconds?$') def wait(step, seconds): time.sleep(float(seconds)) + @step('I (?:visit|access|open) the homepage$') def i_visit_the_homepage(step): world.browser.visit(django_url('/')) assert world.browser.is_element_present_by_css('header.global', 10) + @step(u'I (?:visit|access|open) the dashboard$') def i_visit_the_dashboard(step): world.browser.visit(django_url('/dashboard')) assert world.browser.is_element_present_by_css('section.container.dashboard', 5) + @step(r'click (?:the|a) link (?:called|with the text) "([^"]*)"$') def click_the_link_called(step, text): world.browser.find_link_by_text(text).click() + @step('I should be on the dashboard page$') def i_should_be_on_the_dashboard(step): assert world.browser.is_element_present_by_css('section.container.dashboard', 5) assert world.browser.title == 'Dashboard' + @step(u'I (?:visit|access|open) the courses page$') def i_am_on_the_courses_page(step): world.browser.visit(django_url('/courses')) assert world.browser.is_element_present_by_css('section.courses') + @step('I should see that the path is "([^"]*)"$') def i_should_see_that_the_path_is(step, path): assert world.browser.url == django_url(path) + @step(u'the page title should be "([^"]*)"$') def the_page_title_should_be(step, title): assert world.browser.title == title + @step(r'should see that the url is "([^"]*)"$') def should_have_the_url(step, url): assert_equals(world.browser.url, url) + @step(r'should see (?:the|a) link (?:called|with the text) "([^"]*)"$') def should_see_a_link_called(step, text): assert len(world.browser.find_link_by_text(text)) > 0 + @step(r'should see "(.*)" (?:somewhere|anywhere) in (?:the|this) page') def should_see_in_the_page(step, text): assert_in(text, world.browser.html) + @step('I am logged in$') def i_am_logged_in(step): world.create_user('robot') world.log_in('robot@edx.org', 'test') + @step('I am not logged in$') def i_am_not_logged_in(step): world.browser.cookies.delete() + @step(u'I am registered for a course$') def i_am_registered_for_a_course(step): world.create_user('robot') u = User.objects.get(username='robot') CourseEnrollment.objects.create(user=u, course_id='MITx/6.002x/2012_Fall') world.log_in('robot@edx.org', 'test') - + + @step(u'I am an edX user$') def i_am_an_edx_user(step): world.create_user('robot') + @step(u'User "([^"]*)" is an edX user$') def registered_edx_user(step, uname): world.create_user(uname) diff --git a/lms/djangoapps/portal/features/factories.py b/lms/djangoapps/portal/features/factories.py index 07b615f468..71781ea3d6 100644 --- a/lms/djangoapps/portal/features/factories.py +++ b/lms/djangoapps/portal/features/factories.py @@ -3,6 +3,7 @@ from student.models import User, UserProfile, Registration from datetime import datetime import uuid + class UserProfileFactory(factory.Factory): FACTORY_FOR = UserProfile @@ -13,12 +14,14 @@ class UserProfileFactory(factory.Factory): mailing_address = None goals = 'World domination' + class RegistrationFactory(factory.Factory): FACTORY_FOR = Registration user = None activation_key = uuid.uuid4().hex + class UserFactory(factory.Factory): FACTORY_FOR = User diff --git a/lms/djangoapps/portal/features/homepage.py b/lms/djangoapps/portal/features/homepage.py index 638d65077c..442098c161 100644 --- a/lms/djangoapps/portal/features/homepage.py +++ b/lms/djangoapps/portal/features/homepage.py @@ -1,6 +1,7 @@ from lettuce import world, step from nose.tools import assert_in + @step('I should see "([^"]*)" in the Partners section$') def i_should_see_partner(step, partner): partners = world.browser.find_by_css(".partner .name span") diff --git a/lms/djangoapps/portal/features/login.py b/lms/djangoapps/portal/features/login.py index 5f200eb259..094db078ca 100644 --- a/lms/djangoapps/portal/features/login.py +++ b/lms/djangoapps/portal/features/login.py @@ -1,26 +1,31 @@ from lettuce import step, world from django.contrib.auth.models import User + @step('I am an unactivated user$') def i_am_an_unactivated_user(step): user_is_an_unactivated_user('robot') + @step('I am an activated user$') def i_am_an_activated_user(step): user_is_an_activated_user('robot') + @step('I submit my credentials on the login form') def i_submit_my_credentials_on_the_login_form(step): fill_in_the_login_form('email', 'robot@edx.org') fill_in_the_login_form('password', 'test') login_form = world.browser.find_by_css('form#login_form') login_form.find_by_value('Access My Courses').click() - + + @step(u'I should see the login error message "([^"]*)"$') def i_should_see_the_login_error_message(step, msg): login_error_div = world.browser.find_by_css('form#login_form #login_error') assert (msg in login_error_div.text) + @step(u'click the dropdown arrow$') def click_the_dropdown(step): css = ".dropdown" @@ -29,16 +34,19 @@ def click_the_dropdown(step): #### helper functions + def user_is_an_unactivated_user(uname): u = User.objects.get(username=uname) u.is_active = False u.save() + def user_is_an_activated_user(uname): u = User.objects.get(username=uname) u.is_active = True u.save() + def fill_in_the_login_form(field, value): login_form = world.browser.find_by_css('form#login_form') form_field = login_form.find_by_name(field) diff --git a/lms/djangoapps/portal/features/registration.py b/lms/djangoapps/portal/features/registration.py index 124bed4923..b2b4c4bd8d 100644 --- a/lms/djangoapps/portal/features/registration.py +++ b/lms/djangoapps/portal/features/registration.py @@ -1,5 +1,6 @@ from lettuce import world, step + @step('I register for the course numbered "([^"]*)"$') def i_register_for_the_course(step, course): courses_section = world.browser.find_by_css('section.courses') @@ -13,11 +14,13 @@ def i_register_for_the_course(step, course): assert world.browser.is_element_present_by_css('section.container.dashboard') + @step(u'I should see the course numbered "([^"]*)" in my dashboard$') def i_should_see_that_course_in_my_dashboard(step, course): course_link_css = 'section.my-courses a[href*="%s"]' % course assert world.browser.is_element_present_by_css(course_link_css) + @step(u'I press the "([^"]*)" button in the Unenroll dialog') def i_press_the_button_in_the_unenroll_dialog(step, value): button_css = 'section#unenroll-modal input[value="%s"]' % value diff --git a/lms/djangoapps/portal/features/signup.py b/lms/djangoapps/portal/features/signup.py index afde72b589..3a697a6102 100644 --- a/lms/djangoapps/portal/features/signup.py +++ b/lms/djangoapps/portal/features/signup.py @@ -1,22 +1,25 @@ from lettuce import world, step + @step('I fill in "([^"]*)" on the registration form with "([^"]*)"$') def when_i_fill_in_field_on_the_registration_form_with_value(step, field, value): register_form = world.browser.find_by_css('form#register_form') form_field = register_form.find_by_name(field) form_field.fill(value) + @step('I press the "([^"]*)" button on the registration form$') def i_press_the_button_on_the_registration_form(step, button): register_form = world.browser.find_by_css('form#register_form') register_form.find_by_value(button).click() + @step('I check the checkbox named "([^"]*)"$') def i_check_checkbox(step, checkbox): world.browser.find_by_name(checkbox).check() + @step('I should see "([^"]*)" in the dashboard banner$') def i_should_see_text_in_the_dashboard_banner_section(step, text): css_selector = "section.dashboard-banner h2" assert (text in world.browser.find_by_css(css_selector).text) - \ No newline at end of file diff --git a/lms/djangoapps/psychometrics/management/commands/init_psychometrics.py b/lms/djangoapps/psychometrics/management/commands/init_psychometrics.py index 5e782df595..53f6e17e9d 100644 --- a/lms/djangoapps/psychometrics/management/commands/init_psychometrics.py +++ b/lms/djangoapps/psychometrics/management/commands/init_psychometrics.py @@ -2,7 +2,9 @@ # # generate pyschometrics data from tracking logs and student module data -import os, sys, string +import os +import sys +import string import datetime import json @@ -17,7 +19,7 @@ from django.core.management.base import BaseCommand #db = "ocwtutor" # for debugging #db = "default" -db = getattr(settings,'DATABASE_FOR_PSYCHOMETRICS','default') +db = getattr(settings, 'DATABASE_FOR_PSYCHOMETRICS', 'default') class Command(BaseCommand): @@ -32,39 +34,39 @@ class Command(BaseCommand): #PsychometricData.objects.using(db).all().delete() smset = StudentModule.objects.using(db).exclude(max_grade=None) - + for sm in smset: url = sm.module_state_key location = Location(url) - if not location.category=="problem": + if not location.category == "problem": continue try: state = json.loads(sm.state) done = state['done'] except: - print "Oops, failed to eval state for %s (state=%s)" % (sm,sm.state) + print "Oops, failed to eval state for %s (state=%s)" % (sm, sm.state) continue - + if done: # only keep if problem completed try: pmd = PsychometricData.objects.using(db).get(studentmodule=sm) except PsychometricData.DoesNotExist: pmd = PsychometricData(studentmodule=sm) - + pmd.done = done pmd.attempts = state['attempts'] - + # get attempt times from tracking log uname = sm.student.username - tset = TrackingLog.objects.using(db).filter(username=uname, event_type__contains='save_problem_check') + tset = TrackingLog.objects.using(db).filter(username=uname, event_type__contains='save_problem_check') tset = tset.filter(event_source='server') tset = tset.filter(event__contains="'%s'" % url) checktimes = [x.dtcreated for x in tset] pmd.checktimes = checktimes - if not len(checktimes)==pmd.attempts: + if not len(checktimes) == pmd.attempts: print "Oops, mismatch in number of attempts and check times for %s" % pmd - + #print pmd pmd.save(using=db) - + print "%d PMD entries" % PsychometricData.objects.using(db).all().count() diff --git a/lms/djangoapps/psychometrics/models.py b/lms/djangoapps/psychometrics/models.py index 4ffdf59120..60455f01b8 100644 --- a/lms/djangoapps/psychometrics/models.py +++ b/lms/djangoapps/psychometrics/models.py @@ -7,6 +7,7 @@ from django.db import models from courseware.models import StudentModule + class PsychometricData(models.Model): """ This data is a table linking student, module, and module performance, @@ -25,7 +26,7 @@ class PsychometricData(models.Model): done = models.BooleanField(default=False) attempts = models.IntegerField(default=0) # extracted from studentmodule.state - checktimes = models.TextField(null=True, blank=True) # internally stored as list of datetime objects + checktimes = models.TextField(null=True, blank=True) # internally stored as list of datetime objects # keep in mind # grade = studentmodule.grade @@ -33,7 +34,7 @@ class PsychometricData(models.Model): # student = studentmodule.student # course_id = studentmodule.course_id # location = studentmodule.module_state_key - + def __unicode__(self): sm = self.studentmodule return "[PsychometricData] %s url=%s, grade=%s, max=%s, attempts=%s, ct=%s" % (sm.student, @@ -42,4 +43,3 @@ class PsychometricData(models.Model): sm.max_grade, self.attempts, self.checktimes) - diff --git a/lms/djangoapps/psychometrics/psychoanalyze.py b/lms/djangoapps/psychometrics/psychoanalyze.py index dd7d328278..28a5c4437c 100644 --- a/lms/djangoapps/psychometrics/psychoanalyze.py +++ b/lms/djangoapps/psychometrics/psychoanalyze.py @@ -66,7 +66,7 @@ class StatVar(object): if x > self.max: self.max = x self.sum += x - self.sum2 += x**2 + self.sum2 += x ** 2 self.cnt += 1 def avg(self): @@ -77,11 +77,11 @@ class StatVar(object): def var(self): if self.cnt is None: return 0 - return (self.sum2 / 1.0 / self.cnt / (self.unit**2)) - (self.avg()**2) + return (self.sum2 / 1.0 / self.cnt / (self.unit ** 2)) - (self.avg() ** 2) def sdv(self): v = self.var() - if v>0: + if v > 0: return math.sqrt(v) else: return 0 @@ -112,7 +112,7 @@ def make_histogram(ydata, bins=None): hist = dict(zip(bins, [0] * nbins)) for y in ydata: for b in bins[::-1]: # in reverse order - if y>b: + if y > b: hist[b] += 1 break # hist['bins'] = bins @@ -128,7 +128,7 @@ def problems_with_psychometric_data(course_id): ''' pmdset = PsychometricData.objects.using(db).filter(studentmodule__course_id=course_id) plist = [p['studentmodule__module_state_key'] for p in pmdset.values('studentmodule__module_state_key').distinct()] - problems = dict( (p, pmdset.filter(studentmodule__module_state_key=p).count()) for p in plist ) + problems = dict((p, pmdset.filter(studentmodule__module_state_key=p).count()) for p in plist) return problems @@ -241,7 +241,7 @@ def generate_plots_for_problem(problem): ylast = 0 for x in xdat: y = gset.filter(attempts=x).count() / ngset - ydat.append( y + ylast ) + ydat.append(y + ylast) ylast = y + ylast yset['ydat'] = ydat diff --git a/lms/djangoapps/simplewiki/mdx_mathjax.py b/lms/djangoapps/simplewiki/mdx_mathjax.py index a9148511e3..b14803744b 100644 --- a/lms/djangoapps/simplewiki/mdx_mathjax.py +++ b/lms/djangoapps/simplewiki/mdx_mathjax.py @@ -28,4 +28,3 @@ class MathJaxExtension(markdown.Extension): def makeExtension(configs=None): return MathJaxExtension(configs) - diff --git a/lms/djangoapps/simplewiki/views.py b/lms/djangoapps/simplewiki/views.py index ef0928709f..38c367dec9 100644 --- a/lms/djangoapps/simplewiki/views.py +++ b/lms/djangoapps/simplewiki/views.py @@ -55,6 +55,7 @@ def update_template_dictionary(dictionary, request=None, course=None, article=No else: dictionary['staff_access'] = False + def view(request, article_path, course_id=None): course = get_opt_course_with_access(request.user, course_id, 'load') diff --git a/lms/djangoapps/static_template_view/views.py b/lms/djangoapps/static_template_view/views.py index 8ab6216eda..022f12b148 100644 --- a/lms/djangoapps/static_template_view/views.py +++ b/lms/djangoapps/static_template_view/views.py @@ -46,4 +46,3 @@ def render_404(request): def render_500(request): return HttpResponseServerError(render_to_string('static_templates/server-error.html', {})) - diff --git a/lms/djangoapps/staticbook/views.py b/lms/djangoapps/staticbook/views.py index fabb8b861c..6750d151ce 100644 --- a/lms/djangoapps/staticbook/views.py +++ b/lms/djangoapps/staticbook/views.py @@ -6,6 +6,7 @@ from courseware.access import has_access from courseware.courses import get_course_with_access from lxml import etree + @login_required def index(request, course_id, book_index, page=None): course = get_course_with_access(request.user, course_id, 'load') @@ -22,9 +23,10 @@ def index(request, course_id, book_index, page=None): {'book_index': book_index, 'page': int(page), 'course': course, 'book_url': textbook.book_url, 'table_of_contents': table_of_contents, - 'start_page' : textbook.start_page, - 'end_page' : textbook.end_page, + 'start_page': textbook.start_page, + 'end_page': textbook.end_page, 'staff_access': staff_access}) + def index_shifted(request, course_id, page): return index(request, course_id=course_id, page=int(page) + 24) diff --git a/lms/djangoapps/terrain/__init__.py b/lms/djangoapps/terrain/__init__.py index dd6869e7fd..3445a01d17 100644 --- a/lms/djangoapps/terrain/__init__.py +++ b/lms/djangoapps/terrain/__init__.py @@ -3,4 +3,4 @@ # See https://groups.google.com/forum/?fromgroups=#!msg/lettuce-users/5VyU9B4HcX8/USgbGIJdS5QJ from terrain.browser import * from terrain.steps import * -from terrain.factories import * \ No newline at end of file +from terrain.factories import * diff --git a/lms/djangoapps/terrain/browser.py b/lms/djangoapps/terrain/browser.py index 1c2d401680..e1925bde0b 100644 --- a/lms/djangoapps/terrain/browser.py +++ b/lms/djangoapps/terrain/browser.py @@ -8,20 +8,23 @@ logger.info("Loading the lettuce acceptance testing terrain file...") from django.core.management import call_command + @before.harvest def initial_setup(server): # Launch firefox world.browser = Browser('chrome') + @before.each_scenario def reset_data(scenario): - # Clean out the django test database defined in the + # Clean out the django test database defined in the # envs/acceptance.py file: mitx_all/db/test_mitx.db logger.debug("Flushing the test database...") call_command('flush', interactive=False) + @after.all def teardown_browser(total): # Quit firefox world.browser.quit() - pass \ No newline at end of file + pass diff --git a/lms/djangoapps/terrain/factories.py b/lms/djangoapps/terrain/factories.py index 377ce54d56..896f115df5 100644 --- a/lms/djangoapps/terrain/factories.py +++ b/lms/djangoapps/terrain/factories.py @@ -7,6 +7,7 @@ from time import gmtime from uuid import uuid4 from xmodule.timeparse import stringify_time + class UserProfileFactory(Factory): FACTORY_FOR = UserProfile @@ -17,12 +18,14 @@ class UserProfileFactory(Factory): mailing_address = None goals = 'World domination' + class RegistrationFactory(Factory): FACTORY_FOR = Registration user = None activation_key = uuid4().hex + class UserFactory(Factory): FACTORY_FOR = User @@ -37,12 +40,15 @@ class UserFactory(Factory): last_login = datetime(2012, 1, 1) date_joined = datetime(2011, 1, 1) -def XMODULE_COURSE_CREATION(class_to_create, **kwargs): + +def XMODULE_COURSE_CREATION(class_to_create, **kwargs): return XModuleCourseFactory._create(class_to_create, **kwargs) + def XMODULE_ITEM_CREATION(class_to_create, **kwargs): return XModuleItemFactory._create(class_to_create, **kwargs) + class XModuleCourseFactory(Factory): """ Factory for XModule courses. @@ -58,7 +64,7 @@ class XModuleCourseFactory(Factory): org = kwargs.get('org') number = kwargs.get('number') display_name = kwargs.get('display_name') - location = Location('i4x', org, number, + location = Location('i4x', org, number, 'course', Location.clean(display_name)) store = modulestore('direct') @@ -72,20 +78,22 @@ class XModuleCourseFactory(Factory): new_course.metadata['data_dir'] = uuid4().hex new_course.metadata['start'] = stringify_time(gmtime()) - new_course.tabs = [{"type": "courseware"}, + new_course.tabs = [{"type": "courseware"}, {"type": "course_info", "name": "Course Info"}, {"type": "discussion", "name": "Discussion"}, {"type": "wiki", "name": "Wiki"}, {"type": "progress", "name": "Progress"}] # Update the data in the mongo datastore - store.update_metadata(new_course.location.url(), new_course.own_metadata) + store.update_metadata(new_course.location.url(), new_course.own_metadata) return new_course + class Course: pass + class CourseFactory(XModuleCourseFactory): FACTORY_FOR = Course @@ -94,6 +102,7 @@ class CourseFactory(XModuleCourseFactory): number = '999' display_name = 'Robot Super Course' + class XModuleItemFactory(Factory): """ Factory for XModule items. @@ -110,7 +119,7 @@ class XModuleItemFactory(Factory): """ DETACHED_CATEGORIES = ['about', 'static_tab', 'course_info'] - + parent_location = Location(kwargs.get('parent_location')) template = Location(kwargs.get('template')) display_name = kwargs.get('display_name') @@ -137,12 +146,14 @@ class XModuleItemFactory(Factory): return new_item + class Item: pass + class ItemFactory(XModuleItemFactory): FACTORY_FOR = Item parent_location = 'i4x://MITx/999/course/Robot_Super_Course' template = 'i4x://edx/templates/chapter/Empty' - display_name = 'Section One' \ No newline at end of file + display_name = 'Section One' diff --git a/lms/djangoapps/terrain/steps.py b/lms/djangoapps/terrain/steps.py index 6824fa16ce..6b2a813d8d 100644 --- a/lms/djangoapps/terrain/steps.py +++ b/lms/djangoapps/terrain/steps.py @@ -15,79 +15,97 @@ import os.path from logging import getLogger logger = getLogger(__name__) + @step(u'I wait (?:for )?"(\d+)" seconds?$') def wait(step, seconds): time.sleep(float(seconds)) + @step('I (?:visit|access|open) the homepage$') def i_visit_the_homepage(step): world.browser.visit(django_url('/')) assert world.browser.is_element_present_by_css('header.global', 10) + @step(u'I (?:visit|access|open) the dashboard$') def i_visit_the_dashboard(step): world.browser.visit(django_url('/dashboard')) assert world.browser.is_element_present_by_css('section.container.dashboard', 5) + @step('I should be on the dashboard page$') def i_should_be_on_the_dashboard(step): assert world.browser.is_element_present_by_css('section.container.dashboard', 5) assert world.browser.title == 'Dashboard' + @step(u'I (?:visit|access|open) the courses page$') def i_am_on_the_courses_page(step): world.browser.visit(django_url('/courses')) assert world.browser.is_element_present_by_css('section.courses') + @step(u'I press the "([^"]*)" button$') def and_i_press_the_button(step, value): button_css = 'input[value="%s"]' % value world.browser.find_by_css(button_css).first.click() + @step(u'I click the link with the text "([^"]*)"$') def click_the_link_with_the_text_group1(step, linktext): world.browser.find_link_by_text(linktext).first.click() + @step('I should see that the path is "([^"]*)"$') def i_should_see_that_the_path_is(step, path): assert world.browser.url == django_url(path) + @step(u'the page title should be "([^"]*)"$') def the_page_title_should_be(step, title): assert_equals(world.browser.title, title) + @step('I am a logged in user$') def i_am_logged_in_user(step): create_user('robot') - log_in('robot@edx.org','test') + log_in('robot@edx.org', 'test') + @step('I am not logged in$') def i_am_not_logged_in(step): world.browser.cookies.delete() + @step('I am registered for a course$') def i_am_registered_for_a_course(step): create_user('robot') u = User.objects.get(username='robot') CourseEnrollment.objects.get_or_create(user=u, course_id='MITx/6.002x/2012_Fall') + @step('I am registered for course "([^"]*)"$') def i_am_registered_for_course_by_id(step, course_id): register_by_course_id(course_id) + @step('I am staff for course "([^"]*)"$') def i_am_staff_for_course_by_id(step, course_id): register_by_course_id(course_id, True) + @step('I log in$') def i_log_in(step): - log_in('robot@edx.org','test') + log_in('robot@edx.org', 'test') + @step(u'I am an edX user$') def i_am_an_edx_user(step): create_user('robot') #### helper functions + + @world.absorb def create_user(uname): portal_user = UserFactory.build(username=uname, email=uname + '@edx.org') @@ -100,11 +118,12 @@ def create_user(uname): user_profile = UserProfileFactory(user=portal_user) + @world.absorb -def log_in(email, password): +def log_in(email, password): world.browser.cookies.delete() world.browser.visit(django_url('/')) - world.browser.is_element_present_by_css('header.global', 10) + world.browser.is_element_present_by_css('header.global', 10) world.browser.click_link_by_href('#login-modal') login_form = world.browser.find_by_css('form#login_form') login_form.find_by_name('email').fill(email) @@ -114,15 +133,17 @@ def log_in(email, password): # wait for the page to redraw assert world.browser.is_element_present_by_css('.content-wrapper', 10) + @world.absorb def register_by_course_id(course_id, is_staff=False): create_user('robot') u = User.objects.get(username='robot') if is_staff: - u.is_staff=True - u.save() + u.is_staff = True + u.save() CourseEnrollment.objects.get_or_create(user=u, course_id=course_id) + @world.absorb def save_the_html(path='/tmp'): u = world.browser.url @@ -132,6 +153,7 @@ def save_the_html(path='/tmp'): f.write(html) f.close + @world.absorb def save_the_course_content(path='/tmp'): html = world.browser.html.encode('ascii', 'ignore') @@ -140,12 +162,12 @@ def save_the_course_content(path='/tmp'): # get rid of the header, we only want to compare the body soup.head.decompose() - # for now, remove the data-id attributes, because they are + # for now, remove the data-id attributes, because they are # causing mismatches between cms-master and master for item in soup.find_all(attrs={'data-id': re.compile('.*')}): del item['data-id'] - # we also need to remove them from unrendered problems, + # we also need to remove them from unrendered problems, # where they are contained in the text of divs instead of # in attributes of tags # Be careful of whether or not it was the last attribute @@ -164,7 +186,7 @@ def save_the_course_content(path='/tmp'): # use string slicing to grab everything after 'courseware/' in the URL u = world.browser.url - section_url = u[u.find('courseware/')+11:] + section_url = u[u.find('courseware/') + 11:] if not os.path.exists(path): os.makedirs(path) diff --git a/lms/envs/acceptance.py b/lms/envs/acceptance.py index e0857a4392..412815a402 100644 --- a/lms/envs/acceptance.py +++ b/lms/envs/acceptance.py @@ -1,5 +1,5 @@ """ -This config file extends the test environment configuration +This config file extends the test environment configuration so that we can run the lettuce acceptance tests. """ from .test import * @@ -21,14 +21,14 @@ MODULESTORE = { } } -# Set this up so that rake lms[acceptance] and running the +# Set this up so that rake lms[acceptance] and running the # harvest command both use the same (test) database # which they can flush without messing up your dev db DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ENV_ROOT / "db" / "test_mitx.db", - 'TEST_NAME': ENV_ROOT / "db" / "test_mitx.db", + 'TEST_NAME': ENV_ROOT / "db" / "test_mitx.db", } } diff --git a/lms/envs/common.py b/lms/envs/common.py index 614c68b361..10947a9735 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -40,11 +40,11 @@ DISCUSSION_SETTINGS = { # Features MITX_FEATURES = { - 'SAMPLE' : False, - 'USE_DJANGO_PIPELINE' : True, - 'DISPLAY_HISTOGRAMS_TO_STAFF' : True, - 'REROUTE_ACTIVATION_EMAIL' : False, # nonempty string = address for all activation emails - 'DEBUG_LEVEL' : 0, # 0 = lowest level, least verbose, 255 = max level, most verbose + 'SAMPLE': False, + 'USE_DJANGO_PIPELINE': True, + 'DISPLAY_HISTOGRAMS_TO_STAFF': True, + 'REROUTE_ACTIVATION_EMAIL': False, # nonempty string = address for all activation emails + 'DEBUG_LEVEL': 0, # 0 = lowest level, least verbose, 255 = max level, most verbose ## DO NOT SET TO True IN THIS FILE ## Doing so will cause all courses to be released on production @@ -53,20 +53,20 @@ MITX_FEATURES = { # When True, will only publicly list courses by the subdomain. Expects you # to define COURSE_LISTINGS, a dictionary mapping subdomains to lists of # course_ids (see dev_int.py for an example) - 'SUBDOMAIN_COURSE_LISTINGS' : False, + 'SUBDOMAIN_COURSE_LISTINGS': False, # When True, will override certain branding with university specific values # Expects a SUBDOMAIN_BRANDING dictionary that maps the subdomain to the # university to use for branding purposes 'SUBDOMAIN_BRANDING': False, - 'FORCE_UNIVERSITY_DOMAIN': False, # set this to the university domain to use, as an override to HTTP_HOST + 'FORCE_UNIVERSITY_DOMAIN': False, # set this to the university domain to use, as an override to HTTP_HOST # set to None to do no university selection - 'ENABLE_TEXTBOOK' : True, + 'ENABLE_TEXTBOOK': True, 'ENABLE_DISCUSSION_SERVICE': True, - 'ENABLE_PSYCHOMETRICS': False, # real-time psychometrics (eg item response theory analysis in instructor dashboard) + 'ENABLE_PSYCHOMETRICS': False, # real-time psychometrics (eg item response theory analysis in instructor dashboard) 'ENABLE_SQL_TRACKING_LOGS': False, 'ENABLE_LMS_MIGRATION': False, @@ -74,12 +74,12 @@ MITX_FEATURES = { 'DISABLE_LOGIN_BUTTON': False, # used in systems where login is automatic, eg MIT SSL - 'STUB_VIDEO_FOR_TESTING': False, # do not display video when running automated acceptance tests + 'STUB_VIDEO_FOR_TESTING': False, # do not display video when running automated acceptance tests # extrernal access methods 'ACCESS_REQUIRE_STAFF_FOR_COURSE': False, 'AUTH_USE_OPENID': False, - 'AUTH_USE_MIT_CERTIFICATES' : False, + 'AUTH_USE_MIT_CERTIFICATES': False, 'AUTH_USE_OPENID_PROVIDER': False, } @@ -90,7 +90,7 @@ DEFAULT_GROUPS = [] GENERATE_PROFILE_SCORES = False # Used with XQueue -XQUEUE_WAITTIME_BETWEEN_REQUESTS = 5 # seconds +XQUEUE_WAITTIME_BETWEEN_REQUESTS = 5 # seconds ############################# SET PATH INFORMATION ############################# @@ -151,8 +151,8 @@ TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.static', 'django.contrib.messages.context_processors.messages', #'django.core.context_processors.i18n', - 'django.contrib.auth.context_processors.auth', #this is required for admin - 'django.core.context_processors.csrf', #necessary for csrf protection + 'django.contrib.auth.context_processors.auth', # this is required for admin + 'django.core.context_processors.csrf', # necessary for csrf protection # Added for django-wiki 'django.core.context_processors.media', @@ -162,7 +162,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( 'course_wiki.course_nav.context_processor', ) -STUDENT_FILEUPLOAD_MAX_SIZE = 4*1000*1000 # 4 MB +STUDENT_FILEUPLOAD_MAX_SIZE = 4 * 1000 * 1000 # 4 MB MAX_FILEUPLOADS_PER_INPUT = 20 # FIXME: @@ -172,7 +172,7 @@ LIB_URL = '/static/js/' # Dev machines shouldn't need the book # BOOK_URL = '/static/book/' -BOOK_URL = 'https://mitxstatic.s3.amazonaws.com/book_images/' # For AWS deploys +BOOK_URL = 'https://mitxstatic.s3.amazonaws.com/book_images/' # For AWS deploys # RSS_URL = r'lms/templates/feed.rss' # PRESS_URL = r'' RSS_TIMEOUT = 600 @@ -268,8 +268,8 @@ STATICFILES_DIRS = [ ] # Locale/Internationalization -TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html +TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html USE_I18N = True USE_L10N = True @@ -290,7 +290,7 @@ ALLOWED_GITRELOAD_IPS = ['207.97.227.253', '50.57.128.197', '108.171.174.178'] # setting is, I'm just bumping the expiration time to something absurd (100 # years). This is only used if DEFAULT_FILE_STORAGE is overriden to use S3 # in the global settings.py -AWS_QUERYSTRING_EXPIRE = 10 * 365 * 24 * 60 * 60 # 10 years +AWS_QUERYSTRING_EXPIRE = 10 * 365 * 24 * 60 * 60 # 10 years ################################# SIMPLEWIKI ################################### SIMPLE_WIKI_REQUIRE_LOGIN_EDIT = True @@ -299,8 +299,8 @@ SIMPLE_WIKI_REQUIRE_LOGIN_VIEW = False ################################# WIKI ################################### WIKI_ACCOUNT_HANDLING = False WIKI_EDITOR = 'course_wiki.editors.CodeMirror' -WIKI_SHOW_MAX_CHILDREN = 0 # We don't use the little menu that shows children of an article in the breadcrumb -WIKI_ANONYMOUS = False # Don't allow anonymous access until the styling is figured out +WIKI_SHOW_MAX_CHILDREN = 0 # We don't use the little menu that shows children of an article in the breadcrumb +WIKI_ANONYMOUS = False # Don't allow anonymous access until the styling is figured out WIKI_CAN_CHANGE_PERMISSIONS = lambda article, user: user.is_staff or user.is_superuser WIKI_CAN_ASSIGN = lambda article, user: user.is_staff or user.is_superuser @@ -419,7 +419,7 @@ main_vendor_js = [ discussion_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/discussion/**/*.coffee')) staff_grading_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/staff_grading/**/*.coffee')) -open_ended_js = sorted(rooted_glob(PROJECT_ROOT / 'static','coffee/src/open_ended/**/*.coffee')) +open_ended_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/open_ended/**/*.coffee')) PIPELINE_CSS = { 'application': { @@ -476,11 +476,11 @@ PIPELINE_JS = { 'source_filenames': discussion_js, 'output_filename': 'js/discussion.js' }, - 'staff_grading' : { + 'staff_grading': { 'source_filenames': staff_grading_js, 'output_filename': 'js/staff_grading.js' }, - 'open_ended' : { + 'open_ended': { 'source_filenames': open_ended_js, 'output_filename': 'js/open_ended.js' } @@ -563,9 +563,9 @@ INSTALLED_APPS = ( 'course_groups', #For the wiki - 'wiki', # The new django-wiki from benjaoming + 'wiki', # The new django-wiki from benjaoming 'django_notify', - 'course_wiki', # Our customizations + 'course_wiki', # Our customizations 'mptt', 'sekizai', #'wiki.plugins.attachments', diff --git a/lms/envs/content.py b/lms/envs/content.py index 2584dca969..f699153895 100644 --- a/lms/envs/content.py +++ b/lms/envs/content.py @@ -10,7 +10,7 @@ TEMPLATE_DEBUG = True EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' ################################ DEBUG TOOLBAR ################################# -INSTALLED_APPS += ('debug_toolbar',) +INSTALLED_APPS += ('debug_toolbar',) MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',) DEBUG_TOOLBAR_PANELS = ( @@ -24,8 +24,8 @@ DEBUG_TOOLBAR_PANELS = ( 'debug_toolbar.panels.logger.LoggingPanel', # Enabling the profiler has a weird bug as of django-debug-toolbar==0.9.4 and -# Django=1.3.1/1.4 where requests to views get duplicated (your method gets -# hit twice). So you can uncomment when you need to diagnose performance +# Django=1.3.1/1.4 where requests to views get duplicated (your method gets +# hit twice). So you can uncomment when you need to diagnose performance # problems, but you shouldn't leave it on. # 'debug_toolbar.panels.profiling.ProfilingDebugPanel', ) diff --git a/lms/envs/dev.py b/lms/envs/dev.py index 338a31f641..47bcee1b7e 100644 --- a/lms/envs/dev.py +++ b/lms/envs/dev.py @@ -165,7 +165,7 @@ INSTALLED_APPS += ('django_openid_auth',) OPENID_CREATE_USERS = False OPENID_UPDATE_DETAILS_FROM_SREG = True -OPENID_SSO_SERVER_URL = 'https://www.google.com/accounts/o8/id' # TODO: accept more endpoints +OPENID_SSO_SERVER_URL = 'https://www.google.com/accounts/o8/id' # TODO: accept more endpoints OPENID_USE_AS_ADMIN_LOGIN = False OPENID_PROVIDER_TRUSTED_ROOTS = ['*'] diff --git a/lms/envs/dev_edx4edx.py b/lms/envs/dev_edx4edx.py index 0212d8b550..c138ed81ae 100644 --- a/lms/envs/dev_edx4edx.py +++ b/lms/envs/dev_edx4edx.py @@ -36,7 +36,7 @@ DEBUG = True ENABLE_MULTICOURSE = True # set to False to disable multicourse display (see lib.util.views.mitxhome) QUICKEDIT = True -MAKO_TEMPLATES['course'] = [DATA_DIR, EDX4EDX_ROOT ] +MAKO_TEMPLATES['course'] = [DATA_DIR, EDX4EDX_ROOT] #MITX_FEATURES['USE_DJANGO_PIPELINE'] = False MITX_FEATURES['DISPLAY_HISTOGRAMS_TO_STAFF'] = False @@ -49,12 +49,12 @@ COURSE_TITLE = "edx4edx: edX Author Course" SITE_NAME = "ichuang.mitx.mit.edu" COURSE_SETTINGS = {'edx4edx': {'number' : 'edX.01', - 'title' : 'edx4edx: edX Author Course', + 'title': 'edx4edx: edX Author Course', 'xmlpath': '/edx4edx/', 'github_url': 'https://github.com/MITx/edx4edx', - 'active' : True, - 'default_chapter' : 'Introduction', - 'default_section' : 'edx4edx_Course', + 'active': True, + 'default_chapter': 'Introduction', + 'default_section': 'edx4edx_Course', }, } diff --git a/lms/envs/dev_ike.py b/lms/envs/dev_ike.py index a17622a81a..639d186989 100644 --- a/lms/envs/dev_ike.py +++ b/lms/envs/dev_ike.py @@ -24,25 +24,25 @@ MITX_FEATURES['DISABLE_START_DATES'] = True myhost = socket.gethostname() if ('edxvm' in myhost) or ('ocw' in myhost): - MITX_FEATURES['DISABLE_LOGIN_BUTTON'] = True # auto-login with MIT certificate - MITX_FEATURES['USE_XQA_SERVER'] = 'https://qisx.mit.edu/xqa' # needs to be ssl or browser blocks it - MITX_FEATURES['USE_DJANGO_PIPELINE']=False # don't recompile scss + MITX_FEATURES['DISABLE_LOGIN_BUTTON'] = True # auto-login with MIT certificate + MITX_FEATURES['USE_XQA_SERVER'] = 'https://qisx.mit.edu/xqa' # needs to be ssl or browser blocks it + MITX_FEATURES['USE_DJANGO_PIPELINE'] = False # don't recompile scss if ('ocw' in myhost): MITX_FEATURES['ACCESS_REQUIRE_STAFF_FOR_COURSE'] = False if ('domU' in myhost): EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' - MITX_FEATURES['REROUTE_ACTIVATION_EMAIL'] = 'ichuang@mitx.mit.edu' # nonempty string = address for all activation emails - MITX_FEATURES['USE_DJANGO_PIPELINE']=False # don't recompile scss + MITX_FEATURES['REROUTE_ACTIVATION_EMAIL'] = 'ichuang@mitx.mit.edu' # nonempty string = address for all activation emails + MITX_FEATURES['USE_DJANGO_PIPELINE'] = False # don't recompile scss -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') # django 1.4 for nginx ssl proxy +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') # django 1.4 for nginx ssl proxy #----------------------------------------------------------------------------- # disable django debug toolbars -INSTALLED_APPS = tuple([ app for app in INSTALLED_APPS if not app.startswith('debug_toolbar') ]) -MIDDLEWARE_CLASSES = tuple([ mcl for mcl in MIDDLEWARE_CLASSES if not mcl.startswith('debug_toolbar') ]) +INSTALLED_APPS = tuple([app for app in INSTALLED_APPS if not app.startswith('debug_toolbar')]) +MIDDLEWARE_CLASSES = tuple([mcl for mcl in MIDDLEWARE_CLASSES if not mcl.startswith('debug_toolbar')]) #TEMPLATE_LOADERS = tuple([ app for app in TEMPLATE_LOADERS if not app.startswith('mitxmako') ]) TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', diff --git a/lms/envs/dev_int.py b/lms/envs/dev_int.py index 12123e12d4..21c52c8abc 100644 --- a/lms/envs/dev_int.py +++ b/lms/envs/dev_int.py @@ -14,7 +14,7 @@ from .dev import * MITX_FEATURES['SUBDOMAIN_COURSE_LISTINGS'] = True COURSE_LISTINGS = { - 'default' : ['BerkeleyX/CS169.1x/2012_Fall', + 'default': ['BerkeleyX/CS169.1x/2012_Fall', 'BerkeleyX/CS188.1x/2012_Fall', 'HarvardX/CS50x/2012', 'HarvardX/PH207x/2012_Fall', @@ -25,8 +25,8 @@ COURSE_LISTINGS = { 'berkeley': ['BerkeleyX/CS169.1x/2012_Fall', 'BerkeleyX/CS188.1x/2012_Fall'], - 'harvard' : ['HarvardX/CS50x/2012'], + 'harvard': ['HarvardX/CS50x/2012'], - 'mit' : ['MITx/3.091x/2012_Fall', + 'mit': ['MITx/3.091x/2012_Fall', 'MITx/6.00x/2012_Fall'] } diff --git a/lms/envs/devgroups/courses.py b/lms/envs/devgroups/courses.py index e9ed28a09d..c44717c451 100644 --- a/lms/envs/devgroups/courses.py +++ b/lms/envs/devgroups/courses.py @@ -1,13 +1,13 @@ from ..dev import * CLASSES_TO_DBS = { - 'BerkeleyX/CS169.1x/2012_Fall' : "cs169.db", - 'BerkeleyX/CS188.1x/2012_Fall' : "cs188_1.db", - 'HarvardX/CS50x/2012' : "cs50.db", - 'HarvardX/PH207x/2012_Fall' : "ph207.db", - 'MITx/3.091x/2012_Fall' : "3091.db", - 'MITx/6.002x/2012_Fall' : "6002.db", - 'MITx/6.00x/2012_Fall' : "600.db", + 'BerkeleyX/CS169.1x/2012_Fall': "cs169.db", + 'BerkeleyX/CS188.1x/2012_Fall': "cs188_1.db", + 'HarvardX/CS50x/2012': "cs50.db", + 'HarvardX/PH207x/2012_Fall': "ph207.db", + 'MITx/3.091x/2012_Fall': "3091.db", + 'MITx/6.002x/2012_Fall': "6002.db", + 'MITx/6.00x/2012_Fall': "600.db", } @@ -20,8 +20,8 @@ CACHES = { 'general': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', - 'KEY_PREFIX' : 'general', - 'VERSION' : 5, + 'KEY_PREFIX': 'general', + 'VERSION': 5, 'KEY_FUNCTION': 'util.memcache.safe_key', } } @@ -32,11 +32,12 @@ SESSION_ENGINE = 'django.contrib.sessions.backends.cache' def path_for_db(db_name): return ENV_ROOT / "db" / db_name + def course_db_for(course_id): db_name = CLASSES_TO_DBS[course_id] return { - 'default' : { - 'ENGINE' : 'django.db.backends.sqlite3', - 'NAME' : path_for_db(db_name) + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': path_for_db(db_name) } } diff --git a/lms/envs/devgroups/portal.py b/lms/envs/devgroups/portal.py index b674218571..35808d56fa 100644 --- a/lms/envs/devgroups/portal.py +++ b/lms/envs/devgroups/portal.py @@ -10,4 +10,3 @@ for class_id, db_name in CLASSES_TO_DBS.items(): 'ENGINE': 'django.db.backends.sqlite3', 'NAME': path_for_db(db_name) } - diff --git a/lms/envs/devplus.py b/lms/envs/devplus.py index 5c79304c0a..ea6590291c 100644 --- a/lms/envs/devplus.py +++ b/lms/envs/devplus.py @@ -37,8 +37,8 @@ CACHES = { 'general': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', - 'KEY_PREFIX' : 'general', - 'VERSION' : 5, + 'KEY_PREFIX': 'general', + 'VERSION': 5, 'KEY_FUNCTION': 'util.memcache.safe_key', } } @@ -47,7 +47,7 @@ SESSION_ENGINE = 'django.contrib.sessions.backends.cache' ################################ DEBUG TOOLBAR ################################# -INSTALLED_APPS += ('debug_toolbar',) +INSTALLED_APPS += ('debug_toolbar',) MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',) INTERNAL_IPS = ('127.0.0.1',) @@ -62,8 +62,8 @@ DEBUG_TOOLBAR_PANELS = ( 'debug_toolbar.panels.logger.LoggingPanel', # Enabling the profiler has a weird bug as of django-debug-toolbar==0.9.4 and -# Django=1.3.1/1.4 where requests to views get duplicated (your method gets -# hit twice). So you can uncomment when you need to diagnose performance +# Django=1.3.1/1.4 where requests to views get duplicated (your method gets +# hit twice). So you can uncomment when you need to diagnose performance # problems, but you shouldn't leave it on. 'debug_toolbar.panels.profiling.ProfilingDebugPanel', ) diff --git a/lms/envs/edx4edx_aws.py b/lms/envs/edx4edx_aws.py index adc2c6e1ce..de377c0b57 100644 --- a/lms/envs/edx4edx_aws.py +++ b/lms/envs/edx4edx_aws.py @@ -5,21 +5,21 @@ COURSE_NUMBER = "edX.01" COURSE_TITLE = "edx4edx: edX Author Course" EDX4EDX_ROOT = ENV_ROOT / "data/edx4edx" -### Dark code. Should be enabled in local settings for devel. +### Dark code. Should be enabled in local settings for devel. QUICKEDIT = True -ENABLE_MULTICOURSE = True # set to False to disable multicourse display (see lib.util.views.mitxhome) +ENABLE_MULTICOURSE = True # set to False to disable multicourse display (see lib.util.views.mitxhome) ### PIPELINE_CSS_COMPRESSOR = None PIPELINE_JS_COMPRESSOR = None COURSE_DEFAULT = 'edx4edx' COURSE_SETTINGS = {'edx4edx': {'number' : 'edX.01', - 'title' : 'edx4edx: edX Author Course', + 'title': 'edx4edx: edX Author Course', 'xmlpath': '/edx4edx/', 'github_url': 'https://github.com/MITx/edx4edx', - 'active' : True, - 'default_chapter' : 'Introduction', - 'default_section' : 'edx4edx_Course', + 'active': True, + 'default_chapter': 'Introduction', + 'default_section': 'edx4edx_Course', }, } @@ -34,4 +34,4 @@ STATICFILES_DIRS = [ # ("book", ENV_ROOT / "book_images") ] -MAKO_TEMPLATES['course'] = [DATA_DIR, EDX4EDX_ROOT ] +MAKO_TEMPLATES['course'] = [DATA_DIR, EDX4EDX_ROOT] diff --git a/lms/envs/static.py b/lms/envs/static.py index f233571a9e..23e735c747 100644 --- a/lms/envs/static.py +++ b/lms/envs/static.py @@ -12,7 +12,7 @@ from logsettings import get_logger_config STATIC_GRAB = True -LOGGING = get_logger_config(ENV_ROOT / "log", +LOGGING = get_logger_config(ENV_ROOT / "log", logging_env="dev", tracking_filename="tracking.log", debug=False) @@ -25,7 +25,7 @@ DATABASES = { } CACHES = { - # This is the cache used for most things. + # This is the cache used for most things. # In staging/prod envs, the sessions also live here. 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', diff --git a/lms/envs/test.py b/lms/envs/test.py index 8b546549eb..6cad6416d0 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -23,7 +23,7 @@ MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = False WIKI_ENABLED = True # Makes the tests run much faster... -SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead +SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead # Nose Test Runner INSTALLED_APPS += ('django_nose',) @@ -57,7 +57,7 @@ XQUEUE_INTERFACE = { }, "basic_auth": ('anant', 'agarwal'), } -XQUEUE_WAITTIME_BETWEEN_REQUESTS = 5 # seconds +XQUEUE_WAITTIME_BETWEEN_REQUESTS = 5 # seconds # Don't rely on a real staff grading backend diff --git a/lms/envs/test_ike.py b/lms/envs/test_ike.py index b162d9e2bb..907b7eeadf 100644 --- a/lms/envs/test_ike.py +++ b/lms/envs/test_ike.py @@ -34,11 +34,11 @@ DATA_DIR = COURSES_ROOT MAKO_TEMPLATES['course'] = [DATA_DIR] MAKO_TEMPLATES['sections'] = [DATA_DIR / 'sections'] MAKO_TEMPLATES['custom_tags'] = [DATA_DIR / 'custom_tags'] -MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates', +MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates', DATA_DIR / 'info', DATA_DIR / 'problems'] -LOGGING = get_logger_config(TEST_ROOT / "log", +LOGGING = get_logger_config(TEST_ROOT / "log", logging_env="dev", tracking_filename="tracking.log", debug=True) @@ -51,7 +51,7 @@ DATABASES = { } CACHES = { - # This is the cache used for most things. + # This is the cache used for most things. # In staging/prod envs, the sessions also live here. 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', diff --git a/lms/lib/comment_client/comment.py b/lms/lib/comment_client/comment.py index 6d0bafee02..0d81761512 100644 --- a/lms/lib/comment_client/comment.py +++ b/lms/lib/comment_client/comment.py @@ -4,6 +4,7 @@ from thread import Thread import models import settings + class Comment(models.Model): accessible_fields = [ @@ -41,8 +42,10 @@ class Comment(models.Model): else: return super(Comment, cls).url(action, params) + def _url_for_thread_comments(thread_id): return "{prefix}/threads/{thread_id}/comments".format(prefix=settings.PREFIX, thread_id=thread_id) + def _url_for_comment(comment_id): return "{prefix}/comments/{comment_id}".format(prefix=settings.PREFIX, comment_id=comment_id) diff --git a/lms/lib/comment_client/comment_client.py b/lms/lib/comment_client/comment_client.py index fe485433d6..d7c8f05485 100644 --- a/lms/lib/comment_client/comment_client.py +++ b/lms/lib/comment_client/comment_client.py @@ -7,32 +7,40 @@ from utils import * import settings + def search_similar_threads(course_id, recursive=False, query_params={}, *args, **kwargs): default_params = {'course_id': course_id, 'recursive': recursive} attributes = dict(default_params.items() + query_params.items()) return perform_request('get', _url_for_search_similar_threads(), attributes, *args, **kwargs) + def search_recent_active_threads(course_id, recursive=False, query_params={}, *args, **kwargs): default_params = {'course_id': course_id, 'recursive': recursive} attributes = dict(default_params.items() + query_params.items()) return perform_request('get', _url_for_search_recent_active_threads(), attributes, *args, **kwargs) + def search_trending_tags(course_id, query_params={}, *args, **kwargs): default_params = {'course_id': course_id} attributes = dict(default_params.items() + query_params.items()) return perform_request('get', _url_for_search_trending_tags(), attributes, *args, **kwargs) + def tags_autocomplete(value, *args, **kwargs): return perform_request('get', _url_for_threads_tags_autocomplete(), {'value': value}, *args, **kwargs) + def _url_for_search_similar_threads(): return "{prefix}/search/threads/more_like_this".format(prefix=settings.PREFIX) + def _url_for_search_recent_active_threads(): return "{prefix}/search/threads/recent_active".format(prefix=settings.PREFIX) + def _url_for_search_trending_tags(): return "{prefix}/search/tags/trending".format(prefix=settings.PREFIX) + def _url_for_threads_tags_autocomplete(): return "{prefix}/threads/tags/autocomplete".format(prefix=settings.PREFIX) diff --git a/lms/lib/comment_client/commentable.py b/lms/lib/comment_client/commentable.py index 8f91bfc93d..85c357ef81 100644 --- a/lms/lib/comment_client/commentable.py +++ b/lms/lib/comment_client/commentable.py @@ -3,6 +3,7 @@ from utils import * import models import settings + class Commentable(models.Model): base_url = "{prefix}/commentables".format(prefix=settings.PREFIX) diff --git a/lms/lib/comment_client/legacy.py b/lms/lib/comment_client/legacy.py index fc87bcaf4f..fbf66a09fd 100644 --- a/lms/lib/comment_client/legacy.py +++ b/lms/lib/comment_client/legacy.py @@ -1,6 +1,7 @@ def delete_threads(commentable_id, *args, **kwargs): return _perform_request('delete', _url_for_commentable_threads(commentable_id), *args, **kwargs) + def get_threads(commentable_id, recursive=False, query_params={}, *args, **kwargs): default_params = {'page': 1, 'per_page': 20, 'recursive': recursive} attributes = dict(default_params.items() + query_params.items()) @@ -8,6 +9,7 @@ def get_threads(commentable_id, recursive=False, query_params={}, *args, **kwarg attributes, *args, **kwargs) return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1) + def search_threads(course_id, recursive=False, query_params={}, *args, **kwargs): default_params = {'page': 1, 'per_page': 20, 'course_id': course_id, 'recursive': recursive} attributes = dict(default_params.items() + query_params.items()) @@ -15,106 +17,137 @@ def search_threads(course_id, recursive=False, query_params={}, *args, **kwargs) attributes, *args, **kwargs) return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1) + def search_similar_threads(course_id, recursive=False, query_params={}, *args, **kwargs): default_params = {'course_id': course_id, 'recursive': recursive} attributes = dict(default_params.items() + query_params.items()) return _perform_request('get', _url_for_search_similar_threads(), attributes, *args, **kwargs) + def search_recent_active_threads(course_id, recursive=False, query_params={}, *args, **kwargs): default_params = {'course_id': course_id, 'recursive': recursive} attributes = dict(default_params.items() + query_params.items()) return _perform_request('get', _url_for_search_recent_active_threads(), attributes, *args, **kwargs) + def search_trending_tags(course_id, query_params={}, *args, **kwargs): default_params = {'course_id': course_id} attributes = dict(default_params.items() + query_params.items()) return _perform_request('get', _url_for_search_trending_tags(), attributes, *args, **kwargs) + def create_user(attributes, *args, **kwargs): return _perform_request('post', _url_for_users(), attributes, *args, **kwargs) + def update_user(user_id, attributes, *args, **kwargs): return _perform_request('put', _url_for_user(user_id), attributes, *args, **kwargs) + def get_threads_tags(*args, **kwargs): return _perform_request('get', _url_for_threads_tags(), {}, *args, **kwargs) + def tags_autocomplete(value, *args, **kwargs): return _perform_request('get', _url_for_threads_tags_autocomplete(), {'value': value}, *args, **kwargs) + def create_thread(commentable_id, attributes, *args, **kwargs): return _perform_request('post', _url_for_threads(commentable_id), attributes, *args, **kwargs) - + + def get_thread(thread_id, recursive=False, *args, **kwargs): return _perform_request('get', _url_for_thread(thread_id), {'recursive': recursive}, *args, **kwargs) + def update_thread(thread_id, attributes, *args, **kwargs): return _perform_request('put', _url_for_thread(thread_id), attributes, *args, **kwargs) + def create_comment(thread_id, attributes, *args, **kwargs): return _perform_request('post', _url_for_thread_comments(thread_id), attributes, *args, **kwargs) + def delete_thread(thread_id, *args, **kwargs): return _perform_request('delete', _url_for_thread(thread_id), *args, **kwargs) + def get_comment(comment_id, recursive=False, *args, **kwargs): return _perform_request('get', _url_for_comment(comment_id), {'recursive': recursive}, *args, **kwargs) + def update_comment(comment_id, attributes, *args, **kwargs): return _perform_request('put', _url_for_comment(comment_id), attributes, *args, **kwargs) + def create_sub_comment(comment_id, attributes, *args, **kwargs): return _perform_request('post', _url_for_comment(comment_id), attributes, *args, **kwargs) + def delete_comment(comment_id, *args, **kwargs): return _perform_request('delete', _url_for_comment(comment_id), *args, **kwargs) + def vote_for_comment(comment_id, user_id, value, *args, **kwargs): return _perform_request('put', _url_for_vote_comment(comment_id), {'user_id': user_id, 'value': value}, *args, **kwargs) + def undo_vote_for_comment(comment_id, user_id, *args, **kwargs): return _perform_request('delete', _url_for_vote_comment(comment_id), {'user_id': user_id}, *args, **kwargs) + def vote_for_thread(thread_id, user_id, value, *args, **kwargs): return _perform_request('put', _url_for_vote_thread(thread_id), {'user_id': user_id, 'value': value}, *args, **kwargs) + def undo_vote_for_thread(thread_id, user_id, *args, **kwargs): return _perform_request('delete', _url_for_vote_thread(thread_id), {'user_id': user_id}, *args, **kwargs) + def get_notifications(user_id, *args, **kwargs): return _perform_request('get', _url_for_notifications(user_id), *args, **kwargs) + def get_user_info(user_id, complete=True, *args, **kwargs): return _perform_request('get', _url_for_user(user_id), {'complete': complete}, *args, **kwargs) + def subscribe(user_id, subscription_detail, *args, **kwargs): return _perform_request('post', _url_for_subscription(user_id), subscription_detail, *args, **kwargs) + def subscribe_user(user_id, followed_user_id, *args, **kwargs): return subscribe(user_id, {'source_type': 'user', 'source_id': followed_user_id}) follow = subscribe_user + def subscribe_thread(user_id, thread_id, *args, **kwargs): return subscribe(user_id, {'source_type': 'thread', 'source_id': thread_id}) + def subscribe_commentable(user_id, commentable_id, *args, **kwargs): return subscribe(user_id, {'source_type': 'other', 'source_id': commentable_id}) + def unsubscribe(user_id, subscription_detail, *args, **kwargs): return _perform_request('delete', _url_for_subscription(user_id), subscription_detail, *args, **kwargs) + def unsubscribe_user(user_id, followed_user_id, *args, **kwargs): return unsubscribe(user_id, {'source_type': 'user', 'source_id': followed_user_id}) unfollow = unsubscribe_user + def unsubscribe_thread(user_id, thread_id, *args, **kwargs): return unsubscribe(user_id, {'source_type': 'thread', 'source_id': thread_id}) + def unsubscribe_commentable(user_id, commentable_id, *args, **kwargs): return unsubscribe(user_id, {'source_type': 'other', 'source_id': commentable_id}) + def _perform_request(method, url, data_or_params=None, *args, **kwargs): if method in ['post', 'put', 'patch']: response = requests.request(method, url, data=data_or_params) @@ -130,51 +163,66 @@ def _perform_request(method, url, data_or_params=None, *args, **kwargs): else: return json.loads(response.text) + def _url_for_threads(commentable_id): return "{prefix}/{commentable_id}/threads".format(prefix=PREFIX, commentable_id=commentable_id) + def _url_for_thread(thread_id): return "{prefix}/threads/{thread_id}".format(prefix=PREFIX, thread_id=thread_id) + def _url_for_thread_comments(thread_id): return "{prefix}/threads/{thread_id}/comments".format(prefix=PREFIX, thread_id=thread_id) + def _url_for_comment(comment_id): return "{prefix}/comments/{comment_id}".format(prefix=PREFIX, comment_id=comment_id) + def _url_for_vote_comment(comment_id): return "{prefix}/comments/{comment_id}/votes".format(prefix=PREFIX, comment_id=comment_id) + def _url_for_vote_thread(thread_id): return "{prefix}/threads/{thread_id}/votes".format(prefix=PREFIX, thread_id=thread_id) + def _url_for_notifications(user_id): return "{prefix}/users/{user_id}/notifications".format(prefix=PREFIX, user_id=user_id) + def _url_for_subscription(user_id): return "{prefix}/users/{user_id}/subscriptions".format(prefix=PREFIX, user_id=user_id) + def _url_for_user(user_id): return "{prefix}/users/{user_id}".format(prefix=PREFIX, user_id=user_id) + def _url_for_search_threads(): return "{prefix}/search/threads".format(prefix=PREFIX) + def _url_for_search_similar_threads(): return "{prefix}/search/threads/more_like_this".format(prefix=PREFIX) + def _url_for_search_recent_active_threads(): return "{prefix}/search/threads/recent_active".format(prefix=PREFIX) + def _url_for_search_trending_tags(): return "{prefix}/search/tags/trending".format(prefix=PREFIX) + def _url_for_threads_tags(): return "{prefix}/threads/tags".format(prefix=PREFIX) + def _url_for_threads_tags_autocomplete(): return "{prefix}/threads/tags/autocomplete".format(prefix=PREFIX) + def _url_for_users(): return "{prefix}/users".format(prefix=PREFIX) - diff --git a/lms/lib/comment_client/models.py b/lms/lib/comment_client/models.py index 3ce3858d2d..8676d3af33 100644 --- a/lms/lib/comment_client/models.py +++ b/lms/lib/comment_client/models.py @@ -1,5 +1,6 @@ from utils import * + class Model(object): accessible_fields = ['id'] @@ -26,7 +27,7 @@ class Model(object): raise AttributeError("Field {0} does not exist".format(name)) self.retrieve() return self.__getattr__(name) - + def __setattr__(self, name, value): if name == 'attributes' or name not in self.accessible_fields: super(Model, self).__setattr__(name, value) @@ -80,7 +81,7 @@ class Model(object): def initializable_attributes(self): return extract(self.attributes, self.initializable_fields) - + @classmethod def before_save(cls, instance): pass @@ -91,10 +92,10 @@ class Model(object): def save(self): self.__class__.before_save(self) - if self.id: # if we have id already, treat this as an update + if self.id: # if we have id already, treat this as an update url = self.url(action='put', params=self.attributes) response = perform_request('put', url, self.updatable_attributes()) - else: # otherwise, treat this as an insert + else: # otherwise, treat this as an insert url = self.url(action='post', params=self.attributes) response = perform_request('post', url, self.initializable_attributes()) self.retrieved = True @@ -126,5 +127,5 @@ class Model(object): return cls.url_with_id(params) except KeyError: raise CommentClientError("Cannot perform action {0} without id".format(action)) - else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now + else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now return cls.url_without_id() diff --git a/lms/lib/comment_client/thread.py b/lms/lib/comment_client/thread.py index 6fd31b0823..912ae1af18 100644 --- a/lms/lib/comment_client/thread.py +++ b/lms/lib/comment_client/thread.py @@ -3,6 +3,7 @@ from utils import * import models import settings + class Thread(models.Model): accessible_fields = [ @@ -66,7 +67,7 @@ class Thread(models.Model): def _retrieve(self, *args, **kwargs): url = self.url(action='get', params=self.attributes) - request_params = { + request_params = { 'recursive': kwargs.get('recursive'), 'user_id': kwargs.get('user_id'), 'mark_as_read': kwargs.get('mark_as_read', True), diff --git a/lms/lib/comment_client/user.py b/lms/lib/comment_client/user.py index 546b27556c..c3ba84175e 100644 --- a/lms/lib/comment_client/user.py +++ b/lms/lib/comment_client/user.py @@ -3,6 +3,7 @@ from utils import * import models import settings + class User(models.Model): accessible_fields = ['username', 'email', 'follower_ids', 'upvoted_ids', 'downvoted_ids', @@ -82,17 +83,22 @@ class User(models.Model): response = perform_request('get', url, retrieve_params) self.update_attributes(**response) + def _url_for_vote_comment(comment_id): return "{prefix}/comments/{comment_id}/votes".format(prefix=settings.PREFIX, comment_id=comment_id) + def _url_for_vote_thread(thread_id): return "{prefix}/threads/{thread_id}/votes".format(prefix=settings.PREFIX, thread_id=thread_id) + def _url_for_subscription(user_id): return "{prefix}/users/{user_id}/subscriptions".format(prefix=settings.PREFIX, user_id=user_id) + def _url_for_user_active_threads(user_id): return "{prefix}/users/{user_id}/active_threads".format(prefix=settings.PREFIX, user_id=user_id) + def _url_for_user_subscribed_threads(user_id): return "{prefix}/users/{user_id}/subscribed_threads".format(prefix=settings.PREFIX, user_id=user_id) diff --git a/lms/lib/comment_client/utils.py b/lms/lib/comment_client/utils.py index f50797d5e0..e053fea6c0 100644 --- a/lms/lib/comment_client/utils.py +++ b/lms/lib/comment_client/utils.py @@ -5,23 +5,28 @@ import settings log = logging.getLogger('mitx.' + __name__) + def strip_none(dic): return dict([(k, v) for k, v in dic.iteritems() if v is not None]) + def strip_blank(dic): def _is_blank(v): return isinstance(v, str) and len(v.strip()) == 0 return dict([(k, v) for k, v in dic.iteritems() if not _is_blank(v)]) + def extract(dic, keys): if isinstance(keys, str): return strip_none({keys: dic.get(keys)}) else: return strip_none({k: dic.get(k) for k in keys}) + def merge_dict(dic1, dic2): return dict(dic1.items() + dic2.items()) + def perform_request(method, url, data_or_params=None, *args, **kwargs): if data_or_params is None: data_or_params = {} @@ -34,7 +39,7 @@ def perform_request(method, url, data_or_params=None, *args, **kwargs): except Exception as err: log.exception("Trying to call {method} on {url} with params {params}".format( method=method, url=url, params=data_or_params)) - # Reraise with a single exception type + # Reraise with a single exception type raise CommentClientError(str(err)) if 200 < response.status_code < 500: @@ -47,6 +52,7 @@ def perform_request(method, url, data_or_params=None, *args, **kwargs): else: return json.loads(response.text) + class CommentClientError(Exception): def __init__(self, msg): self.message = msg @@ -54,5 +60,6 @@ class CommentClientError(Exception): def __str__(self): return repr(self.message) + class CommentClientUnknownError(CommentClientError): pass diff --git a/lms/lib/dogfood/check.py b/lms/lib/dogfood/check.py index 0a1da38529..070d3f9262 100644 --- a/lms/lib/dogfood/check.py +++ b/lms/lib/dogfood/check.py @@ -59,5 +59,3 @@ def check_problem_code(ans, the_lcp, correct_answers, false_answers): 'msg': msg + endmsg, } return ret - - diff --git a/lms/lib/loncapa/loncapa_check.py b/lms/lib/loncapa/loncapa_check.py index 0fd998e00e..2cd591520e 100644 --- a/lms/lib/loncapa/loncapa_check.py +++ b/lms/lib/loncapa/loncapa_check.py @@ -33,5 +33,3 @@ def lc_choose(index, *args): deg2rad = math.pi / 180.0 rad2deg = 180.0 / math.pi - - diff --git a/lms/lib/symmath/symmath_check.py b/lms/lib/symmath/symmath_check.py index 3cc4fd7d3c..a3dec4aae5 100644 --- a/lms/lib/symmath/symmath_check.py +++ b/lms/lib/symmath/symmath_check.py @@ -143,6 +143,7 @@ def check(expect, given, numerical=False, matrix=False, normphase=False, abcsym= #----------------------------------------------------------------------------- # helper function to convert all

            to + def make_error_message(msg): # msg = msg.replace('

            ','

            ').replace('

            ','

            ') msg = '
            %s
            ' % msg @@ -153,6 +154,7 @@ def make_error_message(msg): # # This is one of the main entry points to call. + def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None): ''' Check a symbolic mathematical expression using sympy. @@ -183,12 +185,12 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None # msg += '

            abname=%s' % abname # msg += '

            adict=%s' % (repr(adict).replace('<','<')) - threshold = 1.0e-3 # for numerical comparison (also with matrices) + threshold = 1.0e-3 # for numerical comparison (also with matrices) DEBUG = debug if xml is not None: - DEBUG = xml.get('debug',False) # override debug flag using attribute in symbolicmath xml - if DEBUG in ['0','False']: + DEBUG = xml.get('debug', False) # override debug flag using attribute in symbolicmath xml + if DEBUG in ['0', 'False']: DEBUG = False # options diff --git a/lms/static/admin/js/compress.py b/lms/static/admin/js/compress.py index 8d2caa28ea..a23b431750 100644 --- a/lms/static/admin/js/compress.py +++ b/lms/static/admin/js/compress.py @@ -6,6 +6,7 @@ import sys here = os.path.dirname(__file__) + def main(): usage = "usage: %prog [file1..fileN]" description = """With no file paths given this script will automatically diff --git a/lms/urls.py b/lms/urls.py index e9746c2338..b25c4d259e 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -13,7 +13,7 @@ urlpatterns = ('', # certificate view url(r'^update_certificate$', 'certificates.views.update_certificate'), - url(r'^$', 'branding.views.index', name="root"), # Main marketing page, or redirect to courseware + url(r'^$', 'branding.views.index', name="root"), # Main marketing page, or redirect to courseware url(r'^dashboard$', 'student.views.dashboard', name="dashboard"), url(r'^admin_dashboard$', 'dashboard.views.dashboard'), @@ -35,7 +35,7 @@ urlpatterns = ('', # url(r'^testcenter/logout$', 'student.test_center_views.logout'), url(r'^event$', 'track.views.user_track'), - url(r'^t/(?P