From ee1ba1aad93d674d44ca34209761ef09d43c5de1 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 20 Jun 2019 01:20:18 +0530 Subject: [PATCH 01/59] add sections field --- readthedocs/search/documents.py | 5 +++++ readthedocs/search/parse_json.py | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index 5e9d950f272..38d50d4164b 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -122,6 +122,11 @@ class PageDocument(RTDDocTypeMixin, DocType): title = fields.TextField(attr='processed_json.title') headers = fields.TextField(attr='processed_json.headers') content = fields.TextField(attr='processed_json.content') + sections = fields.ObjectField(attr='processed_json.sections', properties={ + 'id': fields.KeywordField(), + 'title': fields.TextField(), + 'content': fields.TextField() + }) modified_model_field = 'modified_date' diff --git a/readthedocs/search/parse_json.py b/readthedocs/search/parse_json.py index a3593056204..524a14f25c1 100644 --- a/readthedocs/search/parse_json.py +++ b/readthedocs/search/parse_json.py @@ -35,7 +35,10 @@ def generate_sections_from_pyquery(body): if next_p[0].tag == 'div' and 'class' in next_p[0].attrib: if 'section' in next_p[0].attrib['class']: break - h1_content += '\n%s\n' % next_p.html() + h1_content += '\n%s\n' % next_p.text().replace('¶', '').strip() + h1_content = h1_content.split('\n')[1:] # to remove the redundant text + h1_content = '\n'.join(h1_content) + next_p = next_p.next() if h1_content: yield { @@ -51,7 +54,11 @@ def generate_sections_from_pyquery(body): header = section_list.eq(num) title = header.text().replace('¶', '').strip() section_id = div.attr('id') - content = div.html() + + content = div.text().replace('¶', '').strip() + content = content.split('\n')[1:] # to remove the redundant text + content = '\n'.join(content) + yield { 'id': section_id, 'title': title, From 4b05f8a66b4f38547818966af3d1048bcb9f242b Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 21 Jun 2019 20:03:16 +0530 Subject: [PATCH 02/59] index each section as separate document in ES --- readthedocs/projects/models.py | 6 +++--- readthedocs/search/api.py | 3 +++ readthedocs/search/documents.py | 10 +++------- readthedocs/search/faceted_search.py | 7 +++++-- readthedocs/search/parse_json.py | 15 ++++++++------- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py index e4c90e1e72d..535d2760dcb 100644 --- a/readthedocs/projects/models.py +++ b/readthedocs/projects/models.py @@ -1252,11 +1252,11 @@ def get_processed_json(self): file_path, ) return { - 'headers': [], - 'content': '', 'path': file_path, 'title': '', - 'sections': [], + 'section_title': '', + 'section_id': '', + 'section_content': '', } @cached_property diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index 57c8efb9186..5189d5303a9 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -23,6 +23,9 @@ class PageSearchSerializer(serializers.Serializer): version = serializers.CharField() title = serializers.CharField() path = serializers.CharField() + section_id = serializers.CharField() + section_title = serializers.CharField() + section_content = serializers.CharField() link = serializers.SerializerMethodField() highlight = serializers.SerializerMethodField() diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index 38d50d4164b..ede3660f406 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -120,13 +120,9 @@ class PageDocument(RTDDocTypeMixin, DocType): # Searchable content title = fields.TextField(attr='processed_json.title') - headers = fields.TextField(attr='processed_json.headers') - content = fields.TextField(attr='processed_json.content') - sections = fields.ObjectField(attr='processed_json.sections', properties={ - 'id': fields.KeywordField(), - 'title': fields.TextField(), - 'content': fields.TextField() - }) + section_id = fields.KeywordField(attr='processed_json.section_id') + section_title = fields.TextField(attr='processed_json.section_title') + section_content = fields.TextField(attr='processed_json.section_content') modified_model_field = 'modified_date' diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 9fed27de679..7cab3698be4 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -61,7 +61,6 @@ def query(self, search, query): * Adds HTML encoding of results to avoid XSS issues. """ search = search.highlight_options(encoder='html', number_of_fragments=3) - search = search.source(exclude=['content', 'headers']) all_queries = [] @@ -96,7 +95,11 @@ class PageSearchBase(RTDFacetedSearch): } doc_types = [PageDocument] index = PageDocument._doc_type.index - fields = ['title^10', 'headers^5', 'content'] + fields = [ + 'title^10', + 'section_title^5', + 'section_content', + ] operators = ['and', 'or'] diff --git a/readthedocs/search/parse_json.py b/readthedocs/search/parse_json.py index 524a14f25c1..71a0eb20660 100644 --- a/readthedocs/search/parse_json.py +++ b/readthedocs/search/parse_json.py @@ -99,13 +99,14 @@ def process_file(fjson_filename): else: log.info('Unable to index title for: %s', fjson_filename) - return { - 'headers': process_headers(data, fjson_filename), - 'content': body_content, - 'path': path, - 'title': title, - 'sections': sections, - } + for section in sections: + return { + 'path': path, + 'title': title, + 'section_id': section['id'], + 'section_title': section['title'], + 'section_content': section['content'], + } def recurse_while_none(element): From 54ceb5c839d1e56272f4368028d95d927e0393c9 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 21 Jun 2019 21:54:41 +0530 Subject: [PATCH 03/59] few refactoring --- readthedocs/projects/models.py | 4 ++-- readthedocs/search/parse_json.py | 30 +----------------------------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py index 535d2760dcb..425129c5427 100644 --- a/readthedocs/projects/models.py +++ b/readthedocs/projects/models.py @@ -1252,10 +1252,10 @@ def get_processed_json(self): file_path, ) return { - 'path': file_path, 'title': '', - 'section_title': '', + 'path': file_path, 'section_id': '', + 'section_title': '', 'section_content': '', } diff --git a/readthedocs/search/parse_json.py b/readthedocs/search/parse_json.py index 71a0eb20660..ed6f45b0b31 100644 --- a/readthedocs/search/parse_json.py +++ b/readthedocs/search/parse_json.py @@ -10,17 +10,6 @@ log = logging.getLogger(__name__) -def process_headers(data, filename): - """Read headers from toc data.""" - headers = [] - if data.get('toc', False): - for element in PyQuery(data['toc'])('a'): - headers.append(recurse_while_none(element)) - if None in headers: - log.info('Unable to index file headers for: %s', filename) - return headers - - def generate_sections_from_pyquery(body): """Given a pyquery object, generate section dicts for each section.""" # Capture text inside h1 before the first h2 @@ -78,7 +67,6 @@ def process_file(fjson_filename): sections = [] path = '' title = '' - body_content = '' if 'current_page_name' in data: path = data['current_page_name'] @@ -87,8 +75,7 @@ def process_file(fjson_filename): if data.get('body'): body = PyQuery(data['body']) - body_content = body.text().replace('¶', '') - sections.extend(generate_sections_from_pyquery(body)) + sections = generate_sections_from_pyquery(body) else: log.info('Unable to index content for: %s', fjson_filename) @@ -107,18 +94,3 @@ def process_file(fjson_filename): 'section_title': section['title'], 'section_content': section['content'], } - - -def recurse_while_none(element): - """ - Traverse the ``element`` until a non-None text is found. - - :param element: element to traverse until get a non-None text. - :type element: pyquery.PyQuery - - :returns: the first non-None value found - :rtype: str - """ - if element.text is None: - return recurse_while_none(element.getchildren()[0]) - return element.text From b11e3577f6d511001e2fc1fe506ef79747529f18 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Mon, 24 Jun 2019 23:14:05 +0530 Subject: [PATCH 04/59] revert all --- readthedocs/projects/models.py | 8 ++-- readthedocs/search/api.py | 3 -- readthedocs/search/documents.py | 5 +-- readthedocs/search/faceted_search.py | 7 +--- readthedocs/search/parse_json.py | 56 +++++++++++++++++++--------- 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py index 425129c5427..e4c90e1e72d 100644 --- a/readthedocs/projects/models.py +++ b/readthedocs/projects/models.py @@ -1252,11 +1252,11 @@ def get_processed_json(self): file_path, ) return { - 'title': '', + 'headers': [], + 'content': '', 'path': file_path, - 'section_id': '', - 'section_title': '', - 'section_content': '', + 'title': '', + 'sections': [], } @cached_property diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index 5189d5303a9..57c8efb9186 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -23,9 +23,6 @@ class PageSearchSerializer(serializers.Serializer): version = serializers.CharField() title = serializers.CharField() path = serializers.CharField() - section_id = serializers.CharField() - section_title = serializers.CharField() - section_content = serializers.CharField() link = serializers.SerializerMethodField() highlight = serializers.SerializerMethodField() diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index ede3660f406..5e9d950f272 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -120,9 +120,8 @@ class PageDocument(RTDDocTypeMixin, DocType): # Searchable content title = fields.TextField(attr='processed_json.title') - section_id = fields.KeywordField(attr='processed_json.section_id') - section_title = fields.TextField(attr='processed_json.section_title') - section_content = fields.TextField(attr='processed_json.section_content') + headers = fields.TextField(attr='processed_json.headers') + content = fields.TextField(attr='processed_json.content') modified_model_field = 'modified_date' diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 7cab3698be4..9fed27de679 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -61,6 +61,7 @@ def query(self, search, query): * Adds HTML encoding of results to avoid XSS issues. """ search = search.highlight_options(encoder='html', number_of_fragments=3) + search = search.source(exclude=['content', 'headers']) all_queries = [] @@ -95,11 +96,7 @@ class PageSearchBase(RTDFacetedSearch): } doc_types = [PageDocument] index = PageDocument._doc_type.index - fields = [ - 'title^10', - 'section_title^5', - 'section_content', - ] + fields = ['title^10', 'headers^5', 'content'] operators = ['and', 'or'] diff --git a/readthedocs/search/parse_json.py b/readthedocs/search/parse_json.py index ed6f45b0b31..a3593056204 100644 --- a/readthedocs/search/parse_json.py +++ b/readthedocs/search/parse_json.py @@ -10,6 +10,17 @@ log = logging.getLogger(__name__) +def process_headers(data, filename): + """Read headers from toc data.""" + headers = [] + if data.get('toc', False): + for element in PyQuery(data['toc'])('a'): + headers.append(recurse_while_none(element)) + if None in headers: + log.info('Unable to index file headers for: %s', filename) + return headers + + def generate_sections_from_pyquery(body): """Given a pyquery object, generate section dicts for each section.""" # Capture text inside h1 before the first h2 @@ -24,10 +35,7 @@ def generate_sections_from_pyquery(body): if next_p[0].tag == 'div' and 'class' in next_p[0].attrib: if 'section' in next_p[0].attrib['class']: break - h1_content += '\n%s\n' % next_p.text().replace('¶', '').strip() - h1_content = h1_content.split('\n')[1:] # to remove the redundant text - h1_content = '\n'.join(h1_content) - + h1_content += '\n%s\n' % next_p.html() next_p = next_p.next() if h1_content: yield { @@ -43,11 +51,7 @@ def generate_sections_from_pyquery(body): header = section_list.eq(num) title = header.text().replace('¶', '').strip() section_id = div.attr('id') - - content = div.text().replace('¶', '').strip() - content = content.split('\n')[1:] # to remove the redundant text - content = '\n'.join(content) - + content = div.html() yield { 'id': section_id, 'title': title, @@ -67,6 +71,7 @@ def process_file(fjson_filename): sections = [] path = '' title = '' + body_content = '' if 'current_page_name' in data: path = data['current_page_name'] @@ -75,7 +80,8 @@ def process_file(fjson_filename): if data.get('body'): body = PyQuery(data['body']) - sections = generate_sections_from_pyquery(body) + body_content = body.text().replace('¶', '') + sections.extend(generate_sections_from_pyquery(body)) else: log.info('Unable to index content for: %s', fjson_filename) @@ -86,11 +92,25 @@ def process_file(fjson_filename): else: log.info('Unable to index title for: %s', fjson_filename) - for section in sections: - return { - 'path': path, - 'title': title, - 'section_id': section['id'], - 'section_title': section['title'], - 'section_content': section['content'], - } + return { + 'headers': process_headers(data, fjson_filename), + 'content': body_content, + 'path': path, + 'title': title, + 'sections': sections, + } + + +def recurse_while_none(element): + """ + Traverse the ``element`` until a non-None text is found. + + :param element: element to traverse until get a non-None text. + :type element: pyquery.PyQuery + + :returns: the first non-None value found + :rtype: str + """ + if element.text is None: + return recurse_while_none(element.getchildren()[0]) + return element.text From 762a79da59421b6ced5035d9bcb8e687670c7371 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 25 Jun 2019 01:44:23 +0530 Subject: [PATCH 05/59] update document mapping (nested fields) --- readthedocs/projects/models.py | 2 -- readthedocs/search/documents.py | 10 ++++++++-- readthedocs/search/parse_json.py | 34 ++------------------------------ readthedocs/settings/base.py | 3 --- 4 files changed, 10 insertions(+), 39 deletions(-) diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py index e4c90e1e72d..4b99371a7d8 100644 --- a/readthedocs/projects/models.py +++ b/readthedocs/projects/models.py @@ -1252,8 +1252,6 @@ def get_processed_json(self): file_path, ) return { - 'headers': [], - 'content': '', 'path': file_path, 'title': '', 'sections': [], diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index 5e9d950f272..62553c461c2 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -120,8 +120,14 @@ class PageDocument(RTDDocTypeMixin, DocType): # Searchable content title = fields.TextField(attr='processed_json.title') - headers = fields.TextField(attr='processed_json.headers') - content = fields.TextField(attr='processed_json.content') + sections = fields.NestedField( + attr='processed_json.sections', + properties={ + 'id': fields.KeywordField(), + 'title': fields.TextField(), + 'content': fields.TextField(), + } + ) modified_model_field = 'modified_date' diff --git a/readthedocs/search/parse_json.py b/readthedocs/search/parse_json.py index a3593056204..0a08925bf56 100644 --- a/readthedocs/search/parse_json.py +++ b/readthedocs/search/parse_json.py @@ -10,17 +10,6 @@ log = logging.getLogger(__name__) -def process_headers(data, filename): - """Read headers from toc data.""" - headers = [] - if data.get('toc', False): - for element in PyQuery(data['toc'])('a'): - headers.append(recurse_while_none(element)) - if None in headers: - log.info('Unable to index file headers for: %s', filename) - return headers - - def generate_sections_from_pyquery(body): """Given a pyquery object, generate section dicts for each section.""" # Capture text inside h1 before the first h2 @@ -35,7 +24,7 @@ def generate_sections_from_pyquery(body): if next_p[0].tag == 'div' and 'class' in next_p[0].attrib: if 'section' in next_p[0].attrib['class']: break - h1_content += '\n%s\n' % next_p.html() + h1_content += '\n%s\n' % next_p.text() next_p = next_p.next() if h1_content: yield { @@ -51,7 +40,7 @@ def generate_sections_from_pyquery(body): header = section_list.eq(num) title = header.text().replace('¶', '').strip() section_id = div.attr('id') - content = div.html() + content = div.text() yield { 'id': section_id, 'title': title, @@ -71,7 +60,6 @@ def process_file(fjson_filename): sections = [] path = '' title = '' - body_content = '' if 'current_page_name' in data: path = data['current_page_name'] @@ -80,7 +68,6 @@ def process_file(fjson_filename): if data.get('body'): body = PyQuery(data['body']) - body_content = body.text().replace('¶', '') sections.extend(generate_sections_from_pyquery(body)) else: log.info('Unable to index content for: %s', fjson_filename) @@ -93,24 +80,7 @@ def process_file(fjson_filename): log.info('Unable to index title for: %s', fjson_filename) return { - 'headers': process_headers(data, fjson_filename), - 'content': body_content, 'path': path, 'title': title, 'sections': sections, } - - -def recurse_while_none(element): - """ - Traverse the ``element`` until a non-None text is found. - - :param element: element to traverse until get a non-None text. - :type element: pyquery.PyQuery - - :returns: the first non-None value found - :rtype: str - """ - if element.text is None: - return recurse_while_none(element.getchildren()[0]) - return element.text diff --git a/readthedocs/settings/base.py b/readthedocs/settings/base.py index 7c4ae9ececa..cb0782840d6 100644 --- a/readthedocs/settings/base.py +++ b/readthedocs/settings/base.py @@ -446,9 +446,6 @@ def USE_PROMOS(self): # noqa 'settings': { 'number_of_shards': 2, 'number_of_replicas': 0, - "index": { - "sort.field": ["project", "version"] - } } }, } From 7a61dbd01b2b908be8b5c25be3b19ed4843b0c67 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 25 Jun 2019 02:01:50 +0530 Subject: [PATCH 06/59] format text --- readthedocs/search/parse_json.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/readthedocs/search/parse_json.py b/readthedocs/search/parse_json.py index 0a08925bf56..20deaabe054 100644 --- a/readthedocs/search/parse_json.py +++ b/readthedocs/search/parse_json.py @@ -24,7 +24,11 @@ def generate_sections_from_pyquery(body): if next_p[0].tag == 'div' and 'class' in next_p[0].attrib: if 'section' in next_p[0].attrib['class']: break - h1_content += '\n%s\n' % next_p.text() + + h1_content += '\n%s\n' % next_p.text().replace('¶', '').strip() + h1_content = h1_content.split('\n')[1:] # to remove the redundant text + h1_content = '\n'.join(h1_content) + next_p = next_p.next() if h1_content: yield { @@ -40,7 +44,11 @@ def generate_sections_from_pyquery(body): header = section_list.eq(num) title = header.text().replace('¶', '').strip() section_id = div.attr('id') - content = div.text() + + content = div.text().replace('¶', '').strip() + content = content.split('\n')[1:] # to remove the redundant text + content = '\n'.join(content) + yield { 'id': section_id, 'title': title, From 644565be775e7d9bbfff28861955d8bb5f3acd23 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 25 Jun 2019 20:08:26 +0530 Subject: [PATCH 07/59] get results from inner_hits --- readthedocs/search/api.py | 14 ++++++++++ readthedocs/search/faceted_search.py | 39 +++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index 57c8efb9186..abbf4261cdb 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -25,6 +25,7 @@ class PageSearchSerializer(serializers.Serializer): path = serializers.CharField() link = serializers.SerializerMethodField() highlight = serializers.SerializerMethodField() + inner_hits = serializers.SerializerMethodField() def get_link(self, obj): projects_url = self.context.get('projects_url') @@ -43,6 +44,19 @@ def get_highlight(self, obj): log.debug('API Search highlight: %s', pformat(ret)) return ret + def get_inner_hits(self, obj): + inner_hits = getattr(obj.meta, 'inner_hits', None) + if inner_hits: + sections = getattr(inner_hits, 'sections', 'None') + res = [] + for hit in sections.hits: + info = { + '_source': hit._source.to_dict(), + 'highlight': hit.highlight.to_dict(), + } + res.append(info) + return res + class PageSearchAPIView(generics.ListAPIView): diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 9fed27de679..94e1bb0fb24 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -96,9 +96,46 @@ class PageSearchBase(RTDFacetedSearch): } doc_types = [PageDocument] index = PageDocument._doc_type.index - fields = ['title^10', 'headers^5', 'content'] + outer_fields = ['title^10'] + nested_fields = ['sections.title^5', 'sections.content'] + fields = outer_fields operators = ['and', 'or'] + def query(self, search, query): + """Manipulates query to support nested query.""" + search = search.highlight_options(encoder='html', number_of_fragments=3) + + all_queries = [] + + # need to search for both 'and' and 'or' operations + # the score of and should be higher as it satisfies both or and and + + for operator in self.operators: + query_string = SimpleQueryString( + query=query, + fields=self.outer_fields + self.nested_fields, + default_operator=operator + ) + all_queries.append(query_string) + + # run bool query with should, so it returns result where either of the query matches + bool_query = Bool(should=all_queries) + + search = search.query( + 'nested', + path='sections', + inner_hits={ + 'highlight': { + 'fields': { + 'sections.title': {}, + 'sections.content': {}, + } + } + }, + query=bool_query + ) + return search + class DomainSearchBase(RTDFacetedSearch): facets = { From 0bc6be57467e50814ad7e9011cd2b113506c81e0 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 25 Jun 2019 22:14:39 +0530 Subject: [PATCH 08/59] correct the none --- readthedocs/search/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index abbf4261cdb..111c01f4647 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -47,7 +47,7 @@ def get_highlight(self, obj): def get_inner_hits(self, obj): inner_hits = getattr(obj.meta, 'inner_hits', None) if inner_hits: - sections = getattr(inner_hits, 'sections', 'None') + sections = getattr(inner_hits, 'sections', None) res = [] for hit in sections.hits: info = { From 013999333709f2a7060d86f25314e8a5058bb030 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 26 Jun 2019 19:50:55 +0530 Subject: [PATCH 09/59] add field for PageDocument. This will work after merging of #5848 --- readthedocs/search/documents.py | 77 +++++++++++++++------------------ 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index 62553c461c2..e9a6ac2c8dd 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -6,7 +6,6 @@ from elasticsearch import Elasticsearch from readthedocs.projects.models import HTMLFile, Project -from readthedocs.sphinx_domains.models import SphinxDomain project_conf = settings.ES_INDEXES['project'] @@ -35,46 +34,6 @@ def update(self, *args, **kwargs): super().update(*args, **kwargs) -@domain_index.doc_type -class SphinxDomainDocument(RTDDocTypeMixin, DocType): - project = fields.KeywordField(attr='project.slug') - version = fields.KeywordField(attr='version.slug') - role_name = fields.KeywordField(attr='role_name') - - # For linking to the URL - doc_name = fields.KeywordField(attr='doc_name') - anchor = fields.KeywordField(attr='anchor') - - # For showing in the search result - type_display = fields.TextField(attr='type_display') - doc_display = fields.TextField(attr='doc_display') - - # Simple analyzer breaks on `.`, - # otherwise search results are too strict for this use case - name = fields.TextField(attr='name', analyzer='simple') - display_name = fields.TextField(attr='display_name', analyzer='simple') - - modified_model_field = 'modified' - - class Meta: - model = SphinxDomain - fields = ('commit', 'build') - ignore_signals = True - - def get_queryset(self): - """Overwrite default queryset to filter certain files to index.""" - queryset = super().get_queryset() - - excluded_types = [ - {'domain': 'std', 'type': 'doc'}, - {'domain': 'std', 'type': 'label'}, - ] - - for exclude in excluded_types: - queryset = queryset.exclude(**exclude) - return queryset - - @project_index.doc_type class ProjectDocument(RTDDocTypeMixin, DocType): @@ -128,6 +87,24 @@ class PageDocument(RTDDocTypeMixin, DocType): 'content': fields.TextField(), } ) + domains = fields.NestedField( + properties={ + 'role_name': fields.KeywordField(), + + # For linking to the URL + 'doc_name': fields.KeywordField(), + 'anchor': fields.KeywordField(), + + # For showing in the search result + 'type_display': fields.TextField(), + 'doc_display': fields.TextField(), + + # Simple analyzer breaks on `.`, + # otherwise search results are too strict for this use case + 'name': fields.TextField(analyzer='simple'), + 'display_name': fields.TextField(analyzer='simple'), + } + ) modified_model_field = 'modified_date' @@ -136,6 +113,24 @@ class Meta: fields = ('commit', 'build') ignore_signals = True + def prepare_domains(self, html_file): + """Prepares and returns the values for domains field.""" + domains_qs = html_file.sphinx_domains.all() + domains_qs = domains_qs.exclude(domain='std', type__in=['doc', 'label']) + + all_domains = [{ + 'role_name': domain.role_name, + 'doc_name': domain.doc_name, + 'anchor': domain.anchor, + 'type_display': domain.type_display, + 'doc_display': domain.doc_display, + 'name': domain.name, + 'display_name': domain.display_name, + } for domain in domains_qs] + + return all_domains + + @classmethod def faceted_search( cls, query, user, projects_list=None, versions_list=None, From 53a02e873949d3957641a201010389c78c592e8c Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 26 Jun 2019 20:33:25 +0530 Subject: [PATCH 10/59] remove domain_index settings --- readthedocs/search/documents.py | 4 ---- readthedocs/settings/base.py | 6 ------ 2 files changed, 10 deletions(-) diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index e9a6ac2c8dd..ac5cb7bba49 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -16,10 +16,6 @@ page_index = Index(page_conf['name']) page_index.settings(**page_conf['settings']) -domain_conf = settings.ES_INDEXES['domain'] -domain_index = Index(domain_conf['name']) -domain_index.settings(**domain_conf['settings']) - log = logging.getLogger(__name__) diff --git a/readthedocs/settings/base.py b/readthedocs/settings/base.py index cb0782840d6..dc54b0ba4e7 100644 --- a/readthedocs/settings/base.py +++ b/readthedocs/settings/base.py @@ -429,12 +429,6 @@ def USE_PROMOS(self): # noqa ES_TASK_CHUNK_SIZE = 100 ES_INDEXES = { - 'domain': { - 'name': 'domain_index', - 'settings': {'number_of_shards': 2, - 'number_of_replicas': 0 - } - }, 'project': { 'name': 'project_index', 'settings': {'number_of_shards': 2, From 6207f4ee7caea42aabc8d14fc179c4c62696d591 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 26 Jun 2019 21:34:25 +0530 Subject: [PATCH 11/59] remove SphinxDomainDocument and DomainSearch --- readthedocs/search/faceted_search.py | 40 ++++++++-------------------- readthedocs/search/views.py | 2 -- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 94e1bb0fb24..45ce99b37f0 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -10,7 +10,6 @@ from readthedocs.search.documents import ( PageDocument, ProjectDocument, - SphinxDomainDocument, ) @@ -137,18 +136,6 @@ def query(self, search, query): return search -class DomainSearchBase(RTDFacetedSearch): - facets = { - 'project': TermsFacet(field='project'), - 'version': TermsFacet(field='version'), - 'role_name': TermsFacet(field='role_name'), - } - doc_types = [SphinxDomainDocument] - index = SphinxDomainDocument._doc_type.index - fields = ('display_name^5', 'name^3', 'project^3', 'type_display') - operators = ['and'] - - class PageSearch(SettingsOverrideObject): """ @@ -171,17 +158,6 @@ class ProjectSearch(SettingsOverrideObject): _default_class = ProjectSearchBase -class DomainSearch(SettingsOverrideObject): - - """ - Allow this class to be overridden based on CLASS_OVERRIDES setting. - - This is primary used on the .com to adjust how we filter our search queries - """ - - _default_class = DomainSearchBase - - class AllSearch(RTDFacetedSearch): """ @@ -189,7 +165,9 @@ class AllSearch(RTDFacetedSearch): It has some UI/UX problems that need to be addressed. """ - + # TODO: This will not work currently and will break + # wherever this is used. + # Fix This. facets = { 'project': TermsFacet(field='project'), 'version': TermsFacet(field='version'), @@ -198,10 +176,14 @@ class AllSearch(RTDFacetedSearch): # Need to improve UX here for exposing to users # 'index': TermsFacet(field='_index'), } - doc_types = [SphinxDomainDocument, PageDocument, ProjectDocument] - index = [SphinxDomainDocument._doc_type.index, - PageDocument._doc_type.index, - ProjectDocument._doc_type.index] + doc_types = [ + PageDocument, + ProjectDocument + ] + index = [ + PageDocument._doc_type.index, + ProjectDocument._doc_type.index + ] fields = ('title^10', 'headers^5', 'content', 'name^20', 'slug^5', 'description', 'display_name^5') operators = ['and'] diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index 5a207bdd9bd..c296680eff9 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -10,7 +10,6 @@ from readthedocs.search.faceted_search import ( ALL_FACETS, AllSearch, - DomainSearch, PageSearch, ProjectSearch, ) @@ -63,7 +62,6 @@ def elastic_search(request, project_slug=None): lambda: ProjectSearch, { 'project': ProjectSearch, - 'domain': DomainSearch, 'file': PageSearch, 'all': AllSearch, } From a251a9844a23b7fda93bf48884c17bed0fc4f574 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 27 Jun 2019 00:32:15 +0530 Subject: [PATCH 12/59] generate correct query --- readthedocs/search/api.py | 20 ++++++- readthedocs/search/faceted_search.py | 87 +++++++++++++++++++++------- 2 files changed, 83 insertions(+), 24 deletions(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index 111c01f4647..4a33a45b1af 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -1,4 +1,5 @@ import logging +from collections import defaultdict from pprint import pformat from rest_framework import generics, serializers @@ -34,6 +35,7 @@ def get_link(self, obj): return docs_url + obj.path def get_highlight(self, obj): + # TODO: make this work for inner_hits.sections and inner_hits.domains also. highlight = getattr(obj.meta, 'highlight', None) if highlight: if hasattr(highlight, 'content'): @@ -47,14 +49,26 @@ def get_highlight(self, obj): def get_inner_hits(self, obj): inner_hits = getattr(obj.meta, 'inner_hits', None) if inner_hits: + res = defaultdict(list) + + # add sections data to the search results sections = getattr(inner_hits, 'sections', None) - res = [] for hit in sections.hits: - info = { + section_info = { + '_source': hit._source.to_dict(), + 'highlight': hit.highlight.to_dict(), + } + res['sections'].append(section_info) + + # add sphinx domain data to the search results + domains = getattr(inner_hits, 'domains', None) + for hit in domains: + domain_info = { '_source': hit._source.to_dict(), 'highlight': hit.highlight.to_dict(), } - res.append(info) + res['domains'].append(domain_info) + return res diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 45ce99b37f0..d0b25b2d4ce 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -2,7 +2,7 @@ from elasticsearch import Elasticsearch from elasticsearch_dsl import FacetedSearch, TermsFacet -from elasticsearch_dsl.query import Bool, SimpleQueryString +from elasticsearch_dsl.query import Bool, SimpleQueryString, Nested, Match from django.conf import settings @@ -95,34 +95,33 @@ class PageSearchBase(RTDFacetedSearch): } doc_types = [PageDocument] index = PageDocument._doc_type.index + outer_fields = ['title^10'] - nested_fields = ['sections.title^5', 'sections.content'] + section_fields = ['sections.title^5', 'sections.content'] + domain_fields = [ + 'domains.type_display', + 'domains.doc_display', + 'domains.name', + 'domains.display_name', + ] fields = outer_fields + + # need to search for both 'and' and 'or' operations + # the score of and should be higher as it satisfies both or and and operators = ['and', 'or'] def query(self, search, query): """Manipulates query to support nested query.""" search = search.highlight_options(encoder='html', number_of_fragments=3) - all_queries = [] - - # need to search for both 'and' and 'or' operations - # the score of and should be higher as it satisfies both or and and - - for operator in self.operators: - query_string = SimpleQueryString( - query=query, - fields=self.outer_fields + self.nested_fields, - default_operator=operator - ) - all_queries.append(query_string) - - # run bool query with should, so it returns result where either of the query matches - bool_query = Bool(should=all_queries) + # match query for the title (of the page) field. + match_title_query = Match(title=query) - search = search.query( - 'nested', + # nested query for search in sections + sections_nested_query = self.generate_nested_query( + query=query, path='sections', + fields=self.section_fields, inner_hits={ 'highlight': { 'fields': { @@ -130,12 +129,58 @@ def query(self, search, query): 'sections.content': {}, } } - }, - query=bool_query + } ) + + # nested query for search in domains + domains_nested_query = self.generate_nested_query( + query=query, + path='domains', + fields=self.domain_fields, + inner_hits={ + 'highlight': { + 'fields': { + 'domains.type_display': {}, + 'domains.doc_display': {}, + 'domains.name': {}, + 'domains.display_name': {}, + } + } + } + ) + + final_query = Bool(should=[ + match_title_query, + sections_nested_query, + domains_nested_query, + ]) + + search = search.query(final_query) return search + def generate_nested_query(self, query, path, fields, inner_hits): + """Generate a nested query with passed parameters.""" + queries = [] + + for operator in self.operators: + query_string = SimpleQueryString( + query=query, + fields=fields, + default_operator=operator + ) + queries.append(query_string) + + bool_query = Bool(should=queries) + + nested_query = Nested( + path=path, + inner_hits=inner_hits, + query=bool_query + ) + return nested_query + + class PageSearch(SettingsOverrideObject): """ From b6847b9c53fbd81c030af8b4c4371e4eb70c27bf Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 27 Jun 2019 01:56:33 +0530 Subject: [PATCH 13/59] remove boosting and allsearch --- readthedocs/search/faceted_search.py | 35 ++-------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index d0b25b2d4ce..0ec593d460f 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -96,8 +96,8 @@ class PageSearchBase(RTDFacetedSearch): doc_types = [PageDocument] index = PageDocument._doc_type.index - outer_fields = ['title^10'] - section_fields = ['sections.title^5', 'sections.content'] + outer_fields = ['title'] + section_fields = ['sections.title', 'sections.content'] domain_fields = [ 'domains.type_display', 'domains.doc_display', @@ -201,34 +201,3 @@ class ProjectSearch(SettingsOverrideObject): """ _default_class = ProjectSearchBase - - -class AllSearch(RTDFacetedSearch): - - """ - Simplfy for testing. - - It has some UI/UX problems that need to be addressed. - """ - # TODO: This will not work currently and will break - # wherever this is used. - # Fix This. - facets = { - 'project': TermsFacet(field='project'), - 'version': TermsFacet(field='version'), - 'language': TermsFacet(field='language'), - 'role_name': TermsFacet(field='role_name'), - # Need to improve UX here for exposing to users - # 'index': TermsFacet(field='_index'), - } - doc_types = [ - PageDocument, - ProjectDocument - ] - index = [ - PageDocument._doc_type.index, - ProjectDocument._doc_type.index - ] - fields = ('title^10', 'headers^5', 'content', 'name^20', - 'slug^5', 'description', 'display_name^5') - operators = ['and'] From af2d69f85a746bee365b65222951a183999e6c50 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 27 Jun 2019 02:02:54 +0530 Subject: [PATCH 14/59] remove allsearch import --- readthedocs/search/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index c296680eff9..dd2afddc18c 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -9,7 +9,6 @@ from readthedocs.projects.models import Project from readthedocs.search.faceted_search import ( ALL_FACETS, - AllSearch, PageSearch, ProjectSearch, ) @@ -63,7 +62,6 @@ def elastic_search(request, project_slug=None): { 'project': ProjectSearch, 'file': PageSearch, - 'all': AllSearch, } ) From 32d0bedfc0abef912043fe7390566a561f189e41 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 27 Jun 2019 02:45:02 +0530 Subject: [PATCH 15/59] recursively remove newline characters from highlight dict --- readthedocs/search/api.py | 49 ++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index 4a33a45b1af..7ec6e0b4d5e 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -35,15 +35,10 @@ def get_link(self, obj): return docs_url + obj.path def get_highlight(self, obj): - # TODO: make this work for inner_hits.sections and inner_hits.domains also. highlight = getattr(obj.meta, 'highlight', None) if highlight: - if hasattr(highlight, 'content'): - # Change results to turn newlines in highlight into periods - # https://github.com/rtfd/readthedocs.org/issues/5168 - highlight.content = [result.replace('\n', '. ') for result in highlight.content] - ret = highlight.to_dict() - log.debug('API Search highlight: %s', pformat(ret)) + ret = self._get_clean_highlight_dict(highlight.to_dict()) + log.debug('API Search highlight [Page title]: %s', pformat(ret)) return ret def get_inner_hits(self, obj): @@ -54,23 +49,59 @@ def get_inner_hits(self, obj): # add sections data to the search results sections = getattr(inner_hits, 'sections', None) for hit in sections.hits: + section_highlight = self._get_clean_highlight_dict( + hit.highlight.to_dict() + ) + + log.debug('API Search highlight [Page sections]: %s', pformat(section_highlight)) + section_info = { '_source': hit._source.to_dict(), - 'highlight': hit.highlight.to_dict(), + 'highlight': section_highlight, } + res['sections'].append(section_info) # add sphinx domain data to the search results domains = getattr(inner_hits, 'domains', None) for hit in domains: + domain_highlight = self._get_clean_highlight_dict( + hit.highlight.to_dict() + ) + + log.debug('API Search highlight [Page domains]: %s', pformat(domain_highlight)) + domain_info = { '_source': hit._source.to_dict(), - 'highlight': hit.highlight.to_dict(), + 'highlight': domain_highlight, } + res['domains'].append(domain_info) return res + def _get_clean_highlight_dict(self, highlight): + """ + Recursively change results to turn newlines in highlight into periods + See: https://github.com/rtfd/readthedocs.org/issues/5168 + + :param highlight: highlight dict whose contents are to be edited. + :type highlight: dict + :returns: dict with all the newlines changed to periods. + :rtype: dict + """ + for k, v in highlight.items(): + if isinstance(v, dict): + highlight[k] = self.get_clean_highlight_dict(v) + else: + # elastic returns the contents of the + # highlighted field in a list. + if isinstance(v, list): + v_new_list = [res.replace('\n', '. ') for res in v] + highlight[k] = v_new_list + + return highlight + class PageSearchAPIView(generics.ListAPIView): From 878343d70ad400caa2e893445d1173ffc3341acf Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 27 Jun 2019 08:31:01 +0530 Subject: [PATCH 16/59] lint fix --- readthedocs/search/api.py | 14 +++++++------- readthedocs/search/documents.py | 1 - readthedocs/search/faceted_search.py | 1 - 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index 7ec6e0b4d5e..c79e1bda7d3 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -37,7 +37,7 @@ def get_link(self, obj): def get_highlight(self, obj): highlight = getattr(obj.meta, 'highlight', None) if highlight: - ret = self._get_clean_highlight_dict(highlight.to_dict()) + ret = self._remove_newlines_from_dict(highlight.to_dict()) log.debug('API Search highlight [Page title]: %s', pformat(ret)) return ret @@ -49,7 +49,7 @@ def get_inner_hits(self, obj): # add sections data to the search results sections = getattr(inner_hits, 'sections', None) for hit in sections.hits: - section_highlight = self._get_clean_highlight_dict( + section_highlight = self._remove_newlines_from_dict( hit.highlight.to_dict() ) @@ -65,7 +65,7 @@ def get_inner_hits(self, obj): # add sphinx domain data to the search results domains = getattr(inner_hits, 'domains', None) for hit in domains: - domain_highlight = self._get_clean_highlight_dict( + domain_highlight = self._remove_newlines_from_dict( hit.highlight.to_dict() ) @@ -80,11 +80,11 @@ def get_inner_hits(self, obj): return res - def _get_clean_highlight_dict(self, highlight): + def _remove_newlines_from_dict(self, highlight): """ - Recursively change results to turn newlines in highlight into periods + Recursively change results to turn newlines in highlight into periods. + See: https://github.com/rtfd/readthedocs.org/issues/5168 - :param highlight: highlight dict whose contents are to be edited. :type highlight: dict :returns: dict with all the newlines changed to periods. @@ -92,7 +92,7 @@ def _get_clean_highlight_dict(self, highlight): """ for k, v in highlight.items(): if isinstance(v, dict): - highlight[k] = self.get_clean_highlight_dict(v) + highlight[k] = self._remove_newlines_from_dict(v) else: # elastic returns the contents of the # highlighted field in a list. diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index ac5cb7bba49..b9cae424b0d 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -126,7 +126,6 @@ def prepare_domains(self, html_file): return all_domains - @classmethod def faceted_search( cls, query, user, projects_list=None, versions_list=None, diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 0ec593d460f..2b04a4318ff 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -158,7 +158,6 @@ def query(self, search, query): search = search.query(final_query) return search - def generate_nested_query(self, query, path, fields, inner_hits): """Generate a nested query with passed parameters.""" queries = [] From 7c1c641adc6c038b23016cf45aab565f6c4305cd Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 28 Jun 2019 12:27:14 +0530 Subject: [PATCH 17/59] set number_of_fragments to 1 --- readthedocs/search/faceted_search.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 2b04a4318ff..3bfb6e209ff 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -112,7 +112,7 @@ class PageSearchBase(RTDFacetedSearch): def query(self, search, query): """Manipulates query to support nested query.""" - search = search.highlight_options(encoder='html', number_of_fragments=3) + search = search.highlight_options(encoder='html', number_of_fragments=1) # match query for the title (of the page) field. match_title_query = Match(title=query) @@ -124,6 +124,7 @@ def query(self, search, query): fields=self.section_fields, inner_hits={ 'highlight': { + 'number_of_fragments': 1, 'fields': { 'sections.title': {}, 'sections.content': {}, @@ -139,6 +140,7 @@ def query(self, search, query): fields=self.domain_fields, inner_hits={ 'highlight': { + 'number_of_fragments': 1, 'fields': { 'domains.type_display': {}, 'domains.doc_display': {}, From fd8e8f76cab1df977222b5c825f6864a2c6e8344 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 28 Jun 2019 23:21:48 +0530 Subject: [PATCH 18/59] use nested facet --- readthedocs/search/faceted_search.py | 7 ++++++- readthedocs/search/views.py | 8 -------- requirements/pip.txt | 4 +++- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 3bfb6e209ff..c9d693275e0 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -2,6 +2,7 @@ from elasticsearch import Elasticsearch from elasticsearch_dsl import FacetedSearch, TermsFacet +from elasticsearch_dsl.faceted_search import NestedFacet from elasticsearch_dsl.query import Bool, SimpleQueryString, Nested, Match from django.conf import settings @@ -91,7 +92,11 @@ class ProjectSearchBase(RTDFacetedSearch): class PageSearchBase(RTDFacetedSearch): facets = { 'project': TermsFacet(field='project'), - 'version': TermsFacet(field='version') + 'version': TermsFacet(field='version'), + 'role_name': NestedFacet( + 'domains', + TermsFacet(field='domains.role_name') + ), } doc_types = [PageDocument] index = PageDocument._doc_type.index diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index dd2afddc18c..e58ffc048fb 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -103,14 +103,6 @@ def elastic_search(request, project_slug=None): facets[avail_facet].insert(0, (value, 0, True)) if results: - if user_input.type == 'file': - # Change results to turn newlines in highlight into periods - # https://github.com/rtfd/readthedocs.org/issues/5168 - for result in results: - if hasattr(result.meta.highlight, 'content'): - result.meta.highlight.content = [result.replace( - '\n', '. ') for result in result.meta.highlight.content] - log.debug('Search results: %s', pformat(results.to_dict())) log.debug('Search facets: %s', pformat(results.facets.to_dict())) diff --git a/requirements/pip.txt b/requirements/pip.txt index 294a64802f5..10de1924557 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -60,7 +60,9 @@ elasticsearch==6.4.0 # pyup: <7.0.0 # File "/home/travis/build/rtfd/readthedocs.org/.tox/py36/lib/python3.6/site-packages/django_elasticsearch_dsl/documents.py", line 8, in # from elasticsearch_dsl.document import DocTypeMeta as DSLDocTypeMeta # ImportError: cannot import name 'DocTypeMeta' -elasticsearch-dsl==6.1.0 # pyup: ignore +# +# Commit 97e3f75 adds the NestedFacet +git+https://github.com/elastic/elasticsearch-dsl-py@97e3f756a8cacd1c863d3ced3d17abcafbb0f85e#egg=elasticsearch-dsl==6.1.0 django-elasticsearch-dsl==0.5.1 pyquery==1.4.0 From f6221ecc617e0ddc60940b613d860706f67f22b8 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 2 Jul 2019 20:48:44 +0530 Subject: [PATCH 19/59] get sorted results --- readthedocs/search/api.py | 46 +++++++++++++-------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index c79e1bda7d3..214d79521e9 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -1,3 +1,4 @@ +import itertools import logging from collections import defaultdict from pprint import pformat @@ -44,41 +45,24 @@ def get_highlight(self, obj): def get_inner_hits(self, obj): inner_hits = getattr(obj.meta, 'inner_hits', None) if inner_hits: - res = defaultdict(list) - - # add sections data to the search results - sections = getattr(inner_hits, 'sections', None) - for hit in sections.hits: - section_highlight = self._remove_newlines_from_dict( - hit.highlight.to_dict() - ) - - log.debug('API Search highlight [Page sections]: %s', pformat(section_highlight)) - - section_info = { - '_source': hit._source.to_dict(), - 'highlight': section_highlight, - } - - res['sections'].append(section_info) - - # add sphinx domain data to the search results - domains = getattr(inner_hits, 'domains', None) - for hit in domains: - domain_highlight = self._remove_newlines_from_dict( - hit.highlight.to_dict() - ) - - log.debug('API Search highlight [Page domains]: %s', pformat(domain_highlight)) - - domain_info = { + sections = inner_hits.sections + domains = inner_hits.domains + all_results = list(sections) + list(domains) + sorted_results = [ + { + 'type': hit._nested.field, '_source': hit._source.to_dict(), - 'highlight': domain_highlight, + 'highlight': self._remove_newlines_from_dict( + hit.highlight.to_dict() + ), } + for hit in sorted(all_results, key=self._get_score, reverse=True) + ] - res['domains'].append(domain_info) + return sorted_results - return res + def _get_score(self, res): + return res._score def _remove_newlines_from_dict(self, highlight): """ From 60e229c5307944960a30911d342c6ae76922732a Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 2 Jul 2019 23:31:19 +0530 Subject: [PATCH 20/59] fix search.html --- .../static-src/core/js/doc-embed/search.js | 98 ++++++++++++++++--- .../static/core/js/readthedocs-doc-embed.js | 2 +- .../projects/static/projects/js/tools.js | 2 +- 3 files changed, 87 insertions(+), 15 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index 79ef3c01c77..ec6191935ef 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -35,14 +35,25 @@ function attach_elastic_search_query(data) { for (var i = 0; i < hit_list.length; i += 1) { var doc = hit_list[i]; var highlight = doc.highlight; + var inner_hits = doc.inner_hits || []; var list_item = $('
  • '); + var title = doc.title; + // if highlighted title is present, + // use that. + if (highlight) { + if (highlight.title) { + title = highlight.title[0]; + } + } + // Creating the result from elements var link = doc.link + DOCUMENTATION_OPTIONS.FILE_SUFFIX + '?highlight=' + $.urlencode(query); var item = $('', {'href': link}); - item.html(doc.title); + item.html(title); + item.find('em').addClass('highlighted') list_item.append(item); // If the document is from subproject, add extra information @@ -53,20 +64,81 @@ function attach_elastic_search_query(data) { list_item.append(extra); } - // Show highlighted texts - if (highlight.content) { - for (var index = 0; index < highlight.content.length; index += 1) { - if (index < 3) { - // Show up to 3 results for search - var content = highlight.content[index]; - var content_text = xss(content); - var contents = $('
    '); - - contents.html("..." + content_text + "..."); - contents.find('em').addClass('highlighted'); - list_item.append(contents); + for (var j = 0; j < inner_hits.length; j += 1) { + + var contents = $('
    '); + + // if the result is page section + if(inner_hits[j].type === "sections") { + + var section = inner_hits[j]; + var subtitle = $('
    '); + var subtitle_link = $(''); + var section_content = $('') + + if (section.highlight) { + if (section.highlight["sections.title"]) { + subtitle_link.html( + section.highlight["sections.title"] + ); + } else { + subtitle_link.html( + section._source.title + ) + } + + if (section.highlight["sections.content"]) { + section_content.html( + "... " + + section.highlight["sections.content"]) + + " ..." + } else { + section_content.html( + section._source.content.substring(0, 80) + + " ..." + ) + } } + + subtitle.html(subtitle_link); + contents.append(subtitle); + contents.append(section_content) + contents.find('em').addClass('highlighted') } + + // if the result is a sphinx domain object + if (inner_hits[j].type === "domains") { + + var domain = inner_hits[j]; + var subtitle = $('"),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return r.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var r=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+r.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,c=/"/g,p=/"/g,f=/&#([a-zA-Z0-9]*);?/gim,h=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(c,""")}function y(e){return e.replace(p,'"')}function _(e){return e.replace(f,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(h,":").replace(g," ")}function k(e){for(var t="",i=0,r=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,r){if(i=T(i),"href"===t||"src"===t){if("#"===(i=u.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==r&&(i=(r=r||a).process(i))}return i=E(i)},i.escapeHtml=s,i.escapeQuote=b,i.unescapeQuote=y,i.escapeHtmlEntities=_,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(a,s){"function"!=typeof s&&(s=function(){});var l=!Array.isArray(a),d=[],c=!1;return{onIgnoreTag:function(e,t,i){if(o=e,l||-1!==u.indexOf(a,o)){if(i.isClosing){var r="[/removed]",n=i.position+r.length;return d.push([!1!==c?c:i.position,n]),c=!1,r}return c||(c=i.position),"[removed]"}return s(e,t,i);var o},remove:function(t){var i="",r=0;return u.forEach(d,function(e){i+=t.slice(r,e[0]),r=e[1]}),i+=t.slice(r)}}},i.stripCommentTag=function(e){return e.replace(S,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=a,i.getDefaultCSSWhiteList=n},{"./util":5,cssfilter:10}],3:[function(e,t,i){var r=e("./default"),n=e("./parser"),o=e("./xss");for(var a in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,r)i[a]=r[a];for(var a in n)i[a]=n[a];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function f(e,t){for(;t"===u){r+=i(e.slice(n,o)),c=p(d=e.slice(o,s+1)),r+=t(o,r.length,c,d,"";var s=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[n],d=w(s.html,function(e,t){var i,r=-1!==b.indexOf(l,e);return y(i=f(n,e,t,r))?r?(t=g(n,e,t,v))?e+'="'+t+'"':e:y(i=h(n,e,t,r))?void 0:i:i});i="<"+n;return d&&(i+=" "+d),s.closing&&(i+=" /"),i+=">"}return y(o=p(n,i,a))?m(i):o},m);return i&&(r=i.remove(r)),r},t.exports=s},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var r,n;r=this,n=function(){var T=!0;function a(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var r=s;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(r=a(i));var n=""+r.version;for(var o in e)if(e.hasOwnProperty(o)&&r[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return l([n,e[o]])<0}return t}return s.test=function(e){for(var t=0;t'),a=r.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX+"?highlight="+$.urlencode(h),s=$("
    ",{href:a});if(s.html(r.title),o.append(s),r.project!==g){var l=" (from project "+r.project+")",d=$("",{text:l});o.append(d)}if(n.content)for(var c=0;c');f.html("..."+p+"..."),f.find("em").addClass("highlighted"),o.append(f)}Search.output.append(o),o.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(h),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(h)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?r.reject():r.resolve(e.responseJSON)}}).fail(function(e,t,i){return r.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(r.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(n,e,t){var o=n("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=n("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),r=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(r),r.prependTo(i),t.navBar=r}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var u,p=e("./constants"),f=e("./rtd-data"),r=e("bowser"),h="#ethical-ad-placement";function g(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),r=p.PROMO_TYPES.LEFTNAV,n=p.DEFAULT_PROMO_PRIORITY,o=null;return u.is_mkdocs_builder()&&u.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):u.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):u.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(n=p.LOW_PROMO_PRIORITY),{div_id:i,display_type:r,priority:n}):null}function m(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),r=p.PROMO_TYPES.FOOTER,n=p.DEFAULT_PROMO_PRIORITY,o=null;return u.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):u.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(n=p.LOW_PROMO_PRIORITY),{div_id:i,display_type:r,priority:n}):null}function v(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=p.PROMO_TYPES.FIXED_FOOTER,i=p.DEFAULT_PROMO_PRIORITY;return r&&r.mobile&&(i=p.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function w(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}w.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);var i=function(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))};$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},w.prototype.disable=function(){$("#"+this.div_id).hide()},w.prototype.post_promo_display=function(){this.display_type===p.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:w,init:function(){var e,t,i,r,n,o={format:"jsonp"},a=[],s=[],l=[],d=[m,g,v];if(u=f.get(),r="rtd-"+(Math.random()+1).toString(36).substring(4),n=p.PROMO_TYPES.LEFTNAV,i=u.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",t=0<$(h).length?($("
    ").attr("id",r).addClass(i).appendTo(h),{div_id:r,display_type:n}):null)a.push(t.div_id),s.push(t.display_type),l.push(t.priority||p.DEFAULT_PROMO_PRIORITY);else{if(!u.show_promo())return;for(var c=0;c").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(i=!0),$("#rtd-detection").remove(),i)&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),e=g(),t=null,e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t)))}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),r=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');r.find("a").attr("href",i).text(e.slug);var n=$("div.body");n.length||(n=$("div.document")),n.prepend(r)}}}},{"./rtd-data":16}],21:[function(e,t,i){var r=e("./doc-embed/sponsorship"),n=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),a=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){n.init(),o.init(),a.init(),r.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,h=/"/g,p=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function y(e){return e.replace(h,'"')}function _(e){return e.replace(p,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=y,i.escapeHtmlEntities=_,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function h(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function p(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=h(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return y(i=p(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:y(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return y(o=h(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=r.title[0]);var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX+"?highlight="+$.urlencode(y),d=$("",{href:l});if(d.html(a),d.find("em").addClass("highlighted"),s.append(d),n.project!==x){var c=" (from project "+n.project+")",u=$("",{text:c});s.append(u)}for(var h=0;h');if("sections"===o[h].type){var f=o[h],g=$('
    '),m=$(''),v=$("");f.highlight&&(f.highlight["sections.title"]?m.html(f.highlight["sections.title"]):m.html(f._source.title),f.highlight["sections.content"]?v.html("... "+f.highlight["sections.content"]):v.html(f._source.content.substring(0,80)+" ...")),g.html(m),p.append(g),p.append(v),p.find("em").addClass("highlighted")}if("domains"===o[h].type){var w=o[h],b=(g=$('
    '),m=$(''),$(""));m.html(w._source.role_name),w.highlight&&(w.highlight["domains.name"]?b.html("... "+w.highlight["domains.name"]+" ..."):b.html(w._source.name+" ...")),g.append(m),p.append(g),p.append(b),p.find("em").addClass("highlighted")}s.append(p),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(y),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(y)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[p,h,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=h(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file diff --git a/readthedocs/projects/static/projects/js/tools.js b/readthedocs/projects/static/projects/js/tools.js index ec4ff8a1f40..5e60509d765 100644 --- a/readthedocs/projects/static/projects/js/tools.js +++ b/readthedocs/projects/static/projects/js/tools.js @@ -1 +1 @@ -require=function o(i,a,l){function c(t,e){if(!a[t]){if(!i[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var r=new Error("Cannot find module '"+t+"'");throw r.code="MODULE_NOT_FOUND",r}var s=a[t]={exports:{}};i[t][0].call(s.exports,function(e){return c(i[t][1][e]||e)},s,s.exports,o,i,a,l)}return a[t].exports}for(var u="function"==typeof require&&require,e=0;e'),i("body").append(t));var n=e.insertContent(t);i(n).show(),t.show(),i(document).click(function(e){i(e.target).closest("#embed-container").length||(i(n).remove(),t.remove())})}function s(e){var s=this;s.config=e||{},void 0===s.config.api_host&&(s.config.api_host="https://readthedocs.org"),s.help=o.observable(null),s.error=o.observable(null),s.project=o.observable(s.config.project),s.file=o.observable(null),s.sections=o.observableArray(),o.computed(function(){var e=s.file();(s.sections.removeAll(),e)&&(s.help("Loading..."),s.error(null),s.section(null),new r.Embed(s.config).page(s.project(),"latest",s.file(),function(e){s.sections.removeAll(),s.help(null),s.error(null);var t,n=[];for(t in e.sections){var r=e.sections[t];i.each(r,function(e,t){n.push({title:e,id:e})})}s.sections(n)},function(e){s.help(null),s.error("There was a problem retrieving data from the API")}))}),s.has_sections=o.computed(function(){return 0'),i("body").append(t));var n=e.insertContent(t);i(n).show(),t.show(),i(document).click(function(e){i(e.target).closest("#embed-container").length||(i(n).remove(),t.remove())})}function s(e){var s=this;s.config=e||{},void 0===s.config.api_host&&(s.config.api_host="https://readthedocs.org"),s.help=o.observable(null),s.error=o.observable(null),s.project=o.observable(s.config.project),s.file=o.observable(null),s.sections=o.observableArray(),o.computed(function(){var e=s.file();(s.sections.removeAll(),e)&&(s.help("Loading..."),s.error(null),s.section(null),new r.Embed(s.config).page(s.project(),"latest",s.file(),function(e){s.sections.removeAll(),s.help(null),s.error(null);var t,n=[];for(t in e.sections){var r=e.sections[t];i.each(r,function(e,t){n.push({title:e,id:e})})}s.sections(n)},function(e){s.help(null),s.error("There was a problem retrieving data from the API")}))}),s.has_sections=o.computed(function(){return 0 Date: Tue, 2 Jul 2019 23:44:59 +0530 Subject: [PATCH 21/59] remove unused imports and add logging --- readthedocs/search/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index 214d79521e9..b4b6e2ddcc9 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -1,6 +1,4 @@ -import itertools import logging -from collections import defaultdict from pprint import pformat from rest_framework import generics, serializers @@ -84,6 +82,8 @@ def _remove_newlines_from_dict(self, highlight): v_new_list = [res.replace('\n', '. ') for res in v] highlight[k] = v_new_list + log.debug('API Search highlight: %s', pformat(highlight)) + return highlight From ae5033cd70a603dd501ff89ab3beca8ceabbf784 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 3 Jul 2019 13:16:16 +0530 Subject: [PATCH 22/59] show more data on domain objects --- .../static-src/core/js/doc-embed/search.js | 45 ++++++++++++------- .../static/core/js/readthedocs-doc-embed.js | 2 +- readthedocs/search/faceted_search.py | 2 - 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index ec6191935ef..4a718d11758 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -43,7 +43,7 @@ function attach_elastic_search_query(data) { // use that. if (highlight) { if (highlight.title) { - title = highlight.title[0]; + title = xss(highlight.title[0]); } } @@ -79,7 +79,7 @@ function attach_elastic_search_query(data) { if (section.highlight) { if (section.highlight["sections.title"]) { subtitle_link.html( - section.highlight["sections.title"] + xss(section.highlight["sections.title"][0]) ); } else { subtitle_link.html( @@ -90,11 +90,12 @@ function attach_elastic_search_query(data) { if (section.highlight["sections.content"]) { section_content.html( "... " + - section.highlight["sections.content"]) + + xss(section.highlight["sections.content"][0]) + " ..." + ) } else { section_content.html( - section._source.content.substring(0, 80) + + section._source.content.substring(0, 100) + " ..." ) } @@ -108,28 +109,38 @@ function attach_elastic_search_query(data) { // if the result is a sphinx domain object if (inner_hits[j].type === "domains") { - + var domain = inner_hits[j]; var subtitle = $('
    '); var subtitle_link = $(''); var domain_content = $('') - - subtitle_link.html(domain._source.role_name); - + + if ( + typeof domain._source.display_name === "string" && + domain._source.display_name.length >= 2 + ) { + subtitle_link.html( + "(" + + domain._source.role_name + + ")" + + domain._source.display_name + ) + } else { + subtitle_link.html(domain._source.role_name) + } + + // preparing domain_content + domain_content.append(domain._source.type_display + " -- "); if (domain.highlight) { if (domain.highlight["domains.name"]) { - domain_content.html( - "... " + - domain.highlight["domains.name"] + - " ..." - ) + domain_content.append( + xss(domain.highlight["domains.name"][0]) + ); } else { - domain_content.html( - domain._source.name + - " ..." - ) + domain_content.append(domain._source.name); } } + domain_content.append(" -- in " + domain._source.doc_display); subtitle.append(subtitle_link); contents.append(subtitle); diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js index 07e75065c35..f7a66c9785b 100644 --- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js +++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js @@ -1 +1 @@ -!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,h=/"/g,p=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function y(e){return e.replace(h,'"')}function _(e){return e.replace(p,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=y,i.escapeHtmlEntities=_,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function h(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function p(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=h(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return y(i=p(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:y(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return y(o=h(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=r.title[0]);var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX+"?highlight="+$.urlencode(y),d=$("
    ",{href:l});if(d.html(a),d.find("em").addClass("highlighted"),s.append(d),n.project!==x){var c=" (from project "+n.project+")",u=$("",{text:c});s.append(u)}for(var h=0;h');if("sections"===o[h].type){var f=o[h],g=$('
    '),m=$(''),v=$("");f.highlight&&(f.highlight["sections.title"]?m.html(f.highlight["sections.title"]):m.html(f._source.title),f.highlight["sections.content"]?v.html("... "+f.highlight["sections.content"]):v.html(f._source.content.substring(0,80)+" ...")),g.html(m),p.append(g),p.append(v),p.find("em").addClass("highlighted")}if("domains"===o[h].type){var w=o[h],b=(g=$('
    '),m=$(''),$(""));m.html(w._source.role_name),w.highlight&&(w.highlight["domains.name"]?b.html("... "+w.highlight["domains.name"]+" ..."):b.html(w._source.name+" ...")),g.append(m),p.append(g),p.append(b),p.find("em").addClass("highlighted")}s.append(p),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(y),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(y)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[p,h,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=h(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=k(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX+"?highlight="+$.urlencode(y),d=$("",{href:l});if(d.html(a),d.find("em").addClass("highlighted"),s.append(d),n.project!==x){var c=" (from project "+n.project+")",u=$("",{text:c});s.append(u)}for(var p=0;p');if("sections"===o[p].type){var f=o[p],g=$('
    '),m=$(''),v=$("");f.highlight&&(f.highlight["sections.title"]?m.html(k(f.highlight["sections.title"][0])):m.html(f._source.title),f.highlight["sections.content"]?v.html("... "+k(f.highlight["sections.content"][0])+" ..."):v.html(f._source.content.substring(0,100)+" ...")),g.html(m),h.append(g),h.append(v),h.find("em").addClass("highlighted")}if("domains"===o[p].type){var w=o[p],b=(g=$('
    '),m=$(''),$(""));"string"==typeof w._source.display_name&&2<=w._source.display_name.length?m.html("("+w._source.role_name+")"+w._source.display_name):m.html(w._source.role_name),b.append(w._source.type_display+" -- "),w.highlight&&(w.highlight["domains.name"]?b.append(k(w.highlight["domains.name"][0])):b.append(w._source.name)),b.append(" -- in "+w._source.doc_display),g.append(m),h.append(g),h.append(b),h.find("em").addClass("highlighted")}s.append(h),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(y),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(y)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index c9d693275e0..220db94f956 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -105,7 +105,6 @@ class PageSearchBase(RTDFacetedSearch): section_fields = ['sections.title', 'sections.content'] domain_fields = [ 'domains.type_display', - 'domains.doc_display', 'domains.name', 'domains.display_name', ] @@ -148,7 +147,6 @@ def query(self, search, query): 'number_of_fragments': 1, 'fields': { 'domains.type_display': {}, - 'domains.doc_display': {}, 'domains.name': {}, 'domains.display_name': {}, } From 28e7cbfb79852b772eb135e10f173addd4b16d50 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 3 Jul 2019 18:32:37 +0530 Subject: [PATCH 23/59] fix main site search --- readthedocs/core/templatetags/core_tags.py | 8 + readthedocs/search/api.py | 45 +- readthedocs/search/utils.py | 28 ++ readthedocs/search/views.py | 32 ++ .../templates/search/elastic_search.html | 412 +++++++++--------- 5 files changed, 293 insertions(+), 232 deletions(-) diff --git a/readthedocs/core/templatetags/core_tags.py b/readthedocs/core/templatetags/core_tags.py index 14e0afdc483..db6f7600e16 100644 --- a/readthedocs/core/templatetags/core_tags.py +++ b/readthedocs/core/templatetags/core_tags.py @@ -109,6 +109,14 @@ def key(d, key_name): return d[key_name] +@register.filter +def get_key_or_none(d, key_name): + try: + return d[key_name] + except KeyError: + return None + + @register.simple_tag def readthedocs_version(): return __version__ diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index b4b6e2ddcc9..adf028b4133 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -6,7 +6,7 @@ from rest_framework.pagination import PageNumberPagination from readthedocs.search.faceted_search import PageSearch -from readthedocs.search.utils import get_project_list_or_404 +from readthedocs.search import utils log = logging.getLogger(__name__) @@ -36,7 +36,7 @@ def get_link(self, obj): def get_highlight(self, obj): highlight = getattr(obj.meta, 'highlight', None) if highlight: - ret = self._remove_newlines_from_dict(highlight.to_dict()) + ret = utils._remove_newlines_from_dict(highlight.to_dict()) log.debug('API Search highlight [Page title]: %s', pformat(ret)) return ret @@ -46,45 +46,26 @@ def get_inner_hits(self, obj): sections = inner_hits.sections domains = inner_hits.domains all_results = list(sections) + list(domains) + sorted_results = [ { 'type': hit._nested.field, '_source': hit._source.to_dict(), - 'highlight': self._remove_newlines_from_dict( - hit.highlight.to_dict() - ), + 'highlight': self._get_inner_hits_highlights(hit), } - for hit in sorted(all_results, key=self._get_score, reverse=True) + for hit in sorted(all_results, key=utils._get_hit_score, reverse=True) ] return sorted_results - def _get_score(self, res): - return res._score - - def _remove_newlines_from_dict(self, highlight): - """ - Recursively change results to turn newlines in highlight into periods. - - See: https://github.com/rtfd/readthedocs.org/issues/5168 - :param highlight: highlight dict whose contents are to be edited. - :type highlight: dict - :returns: dict with all the newlines changed to periods. - :rtype: dict - """ - for k, v in highlight.items(): - if isinstance(v, dict): - highlight[k] = self._remove_newlines_from_dict(v) - else: - # elastic returns the contents of the - # highlighted field in a list. - if isinstance(v, list): - v_new_list = [res.replace('\n', '. ') for res in v] - highlight[k] = v_new_list - - log.debug('API Search highlight: %s', pformat(highlight)) + def _get_inner_hits_highlights(self, hit): + """Removes new lines from highlight and log it.""" + highlight_dict = utils._remove_newlines_from_dict( + hit.highlight.to_dict() + ) - return highlight + log.debug('API Search highlight: %s', pformat(highlight_dict)) + return highlight_dict class PageSearchAPIView(generics.ListAPIView): @@ -155,7 +136,7 @@ def get_all_projects(self): """ project_slug = self.request.query_params.get('project') version_slug = self.request.query_params.get('version') - all_projects = get_project_list_or_404( + all_projects = utils.get_project_list_or_404( project_slug=project_slug, user=self.request.user, version_slug=version_slug, ) return all_projects diff --git a/readthedocs/search/utils.py b/readthedocs/search/utils.py index 7eca59dbb45..3f562384ac4 100644 --- a/readthedocs/search/utils.py +++ b/readthedocs/search/utils.py @@ -159,3 +159,31 @@ def _indexing_helper(html_objs_qs, wipe=False): index_objects_to_es.delay(**kwargs) else: delete_objects_in_es.delay(**kwargs) + + +def _get_hit_score(res): + """Returns the _score of a single ES search result hits.""" + return res._score + + +def _remove_newlines_from_dict(highlight): + """ + Recursively change results to turn newlines into periods. + + See: https://github.com/rtfd/readthedocs.org/issues/5168 + :param highlight: highlight dict whose contents are to be edited. + :type highlight: dict + :returns: dict with all the newlines changed to periods. + :rtype: dict + """ + for k, v in highlight.items(): + if isinstance(v, dict): + highlight[k] = self._remove_newlines_from_dict(v) + else: + # elastic returns the contents of the + # highlighted field in a list. + if isinstance(v, list): + v_new_list = [res.replace('\n', '. ') for res in v] + highlight[k] = v_new_list + + return highlight diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index e58ffc048fb..e91c79a9068 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -12,6 +12,7 @@ PageSearch, ProjectSearch, ) +from readthedocs.search import utils log = logging.getLogger(__name__) @@ -103,6 +104,37 @@ def elastic_search(request, project_slug=None): facets[avail_facet].insert(0, (value, 0, True)) if results: + + # sorting inner_hits (if present) + try: + for hit in results.hits.hits: + sections = hit['inner_hits'].get('sections', []) + domains = hit['inner_hits'].get('domains', []) + all_results = list(sections) + list(domains) + + sorted_results = [ + { + 'type': hit._nested.field, + + # here _source term is not used because + # django gives error if the names of the + # variables start with underscore + 'source': hit._source.to_dict(), + + 'highlight': utils._remove_newlines_from_dict( + hit.highlight.to_dict() + ), + } + for hit in sorted(all_results, key=utils._get_hit_score, reverse=True) + ] + + hit['inner_hits'].pop('sections', None) + hit['inner_hits'].pop('domains', None) + hit['inner_hits'] = sorted_results + + except Exception as e: + log.error('Error occurred while sorting inner_hits', e) + log.debug('Search results: %s', pformat(results.to_dict())) log.debug('Search facets: %s', pformat(results.facets.to_dict())) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index a7e33862a30..8667e5cafd1 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -2,15 +2,17 @@ {% load core_tags i18n static %} -{% block title %}{% blocktrans with query=query|default:"" %}Search: {{ query }} {% endblocktrans %}{% endblock %} +{% block title %} + {% blocktrans with query=query|default:"" %} + Search: {{ query }} + {% endblocktrans %} +{% endblock %} {% block extra_links %} -{{ super }} - - - + {{ super }} + {% endblock %} {% block project_editing %} @@ -25,218 +27,228 @@ {% endblock %} From 1e2a40b1e7cf074f9ee70f0e2ed9e5cf482622ad Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 3 Jul 2019 22:11:37 +0530 Subject: [PATCH 24/59] mark as safe and change log to debug --- readthedocs/search/views.py | 2 +- readthedocs/templates/search/elastic_search.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index e91c79a9068..e2ee3ac866c 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -133,7 +133,7 @@ def elastic_search(request, project_slug=None): hit['inner_hits'] = sorted_results except Exception as e: - log.error('Error occurred while sorting inner_hits', e) + log.debug('Error occurred while sorting inner_hits', e) log.debug('Search results: %s', pformat(results.to_dict())) log.debug('Search facets: %s', pformat(results.facets.to_dict())) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index 8667e5cafd1..31afa3bc9a5 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -208,7 +208,7 @@

    {% if inner_hit.highlight|get_key_or_none:"domains.name" %} {% with l=inner_hit.highlight|get_key_or_none:"domains.name" %} - {{ inner_hit.source.type_display }} -- {{ l.0 }} -- {{ inner_hit.source.doc_display }} + {{ inner_hit.source.type_display }} -- {{ l.0|safe }} -- {{ inner_hit.source.doc_display }} {% endwith %} {% else %} {{ inner_hit.source.type_display }} -- {{ inner_hit.source.name }} -- {{ inner_hit.source.doc_display }} From 7b7a3c9b561dbbd2f5748b5e749d91a69843dacb Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 3 Jul 2019 23:47:31 +0530 Subject: [PATCH 25/59] add transpiled files -- js --- .../static-src/core/js/doc-embed/search.js | 54 +++++++++---------- .../static/core/js/readthedocs-doc-embed.js | 2 +- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index 4a718d11758..b6af1d57658 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -53,7 +53,7 @@ function attach_elastic_search_query(data) { var item = $('', {'href': link}); item.html(title); - item.find('em').addClass('highlighted') + item.find('em').addClass('highlighted'); list_item.append(item); // If the document is from subproject, add extra information @@ -70,63 +70,63 @@ function attach_elastic_search_query(data) { // if the result is page section if(inner_hits[j].type === "sections") { - + var section = inner_hits[j]; - var subtitle = $('

    '); - var subtitle_link = $(''); - var section_content = $('') - + var section_subtitle = $('
    '); + var section_subtitle_link = $(''); + var section_content = $(''); + if (section.highlight) { if (section.highlight["sections.title"]) { - subtitle_link.html( + section_subtitle_link.html( xss(section.highlight["sections.title"][0]) ); } else { - subtitle_link.html( + section_subtitle_link.html( section._source.title - ) + ); } - + if (section.highlight["sections.content"]) { section_content.html( "... " + xss(section.highlight["sections.content"][0]) + " ..." - ) + ); } else { section_content.html( section._source.content.substring(0, 100) + " ..." - ) + ); } } - - subtitle.html(subtitle_link); - contents.append(subtitle); - contents.append(section_content) - contents.find('em').addClass('highlighted') + + section_subtitle.html(section_subtitle_link); + contents.append(section_subtitle); + contents.append(section_content); + contents.find('em').addClass('highlighted'); } // if the result is a sphinx domain object if (inner_hits[j].type === "domains") { var domain = inner_hits[j]; - var subtitle = $('
    '); - var subtitle_link = $(''); - var domain_content = $('') + var domain_subtitle = $('
    '); + var domain_subtitle_link = $(''); + var domain_content = $(''); if ( typeof domain._source.display_name === "string" && domain._source.display_name.length >= 2 ) { - subtitle_link.html( + domain_subtitle_link.html( "(" + domain._source.role_name + ")" + domain._source.display_name - ) + ); } else { - subtitle_link.html(domain._source.role_name) + domain_subtitle_link.html(domain._source.role_name); } // preparing domain_content @@ -141,11 +141,11 @@ function attach_elastic_search_query(data) { } } domain_content.append(" -- in " + domain._source.doc_display); - - subtitle.append(subtitle_link); - contents.append(subtitle); + + domain_subtitle.append(domain_subtitle_link); + contents.append(domain_subtitle); contents.append(domain_content); - contents.find('em').addClass('highlighted') + contents.find('em').addClass('highlighted'); } list_item.append(contents); diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js index f7a66c9785b..0acce36fe0b 100644 --- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js +++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js @@ -1 +1 @@ -!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=k(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX+"?highlight="+$.urlencode(y),d=$("
    ",{href:l});if(d.html(a),d.find("em").addClass("highlighted"),s.append(d),n.project!==x){var c=" (from project "+n.project+")",u=$("",{text:c});s.append(u)}for(var p=0;p');if("sections"===o[p].type){var f=o[p],g=$('
    '),m=$(''),v=$("");f.highlight&&(f.highlight["sections.title"]?m.html(k(f.highlight["sections.title"][0])):m.html(f._source.title),f.highlight["sections.content"]?v.html("... "+k(f.highlight["sections.content"][0])+" ..."):v.html(f._source.content.substring(0,100)+" ...")),g.html(m),h.append(g),h.append(v),h.find("em").addClass("highlighted")}if("domains"===o[p].type){var w=o[p],b=(g=$('
    '),m=$(''),$(""));"string"==typeof w._source.display_name&&2<=w._source.display_name.length?m.html("("+w._source.role_name+")"+w._source.display_name):m.html(w._source.role_name),b.append(w._source.type_display+" -- "),w.highlight&&(w.highlight["domains.name"]?b.append(k(w.highlight["domains.name"][0])):b.append(w._source.name)),b.append(" -- in "+w._source.doc_display),g.append(m),h.append(g),h.append(b),h.find("em").addClass("highlighted")}s.append(h),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(y),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(y)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=E(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX+"?highlight="+$.urlencode(k),d=$("",{href:l});if(d.html(a),d.find("em").addClass("highlighted"),s.append(d),n.project!==T){var c=" (from project "+n.project+")",u=$("",{text:c});s.append(u)}for(var p=0;p');if("sections"===o[p].type){var f=o[p],g=$('
    '),m=$(''),v=$("");f.highlight&&(f.highlight["sections.title"]?m.html(E(f.highlight["sections.title"][0])):m.html(f._source.title),f.highlight["sections.content"]?v.html("... "+E(f.highlight["sections.content"][0])+" ..."):v.html(f._source.content.substring(0,100)+" ...")),g.html(m),h.append(g),h.append(v),h.find("em").addClass("highlighted")}if("domains"===o[p].type){var w=o[p],b=$('
    '),y=$(''),x=$("");"string"==typeof w._source.display_name&&2<=w._source.display_name.length?y.html("("+w._source.role_name+")"+w._source.display_name):y.html(w._source.role_name),x.append(w._source.type_display+" -- "),w.highlight&&(w.highlight["domains.name"]?x.append(E(w.highlight["domains.name"][0])):x.append(w._source.name)),x.append(" -- in "+w._source.doc_display),b.append(y),h.append(b),h.append(x),h.find("em").addClass("highlighted")}s.append(h),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(k),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(k)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file From 3931bc087609c41d9814d7cc4c8ff4defa3f73b0 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 3 Jul 2019 23:58:20 +0530 Subject: [PATCH 26/59] remove log --- readthedocs/search/views.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index e2ee3ac866c..5f086a78c1f 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -132,8 +132,10 @@ def elastic_search(request, project_slug=None): hit['inner_hits'].pop('domains', None) hit['inner_hits'] = sorted_results - except Exception as e: - log.debug('Error occurred while sorting inner_hits', e) + except: + # if the control comes in this block, + # that implies that there was PageSearch + pass log.debug('Search results: %s', pformat(results.to_dict())) log.debug('Search facets: %s', pformat(results.facets.to_dict())) From 84a2494e190acac24ae7582b9e3e947383c02b26 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 4 Jul 2019 00:46:00 +0530 Subject: [PATCH 27/59] small improvements in template --- readthedocs/templates/search/elastic_search.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index 31afa3bc9a5..ab6eb959b8e 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -190,7 +190,7 @@

    {% if 'page' in hit|key:"_index" %}
  • - + {{ hit|key:'_source'|key:'project' }} - {{ hit|key:'_source'|key:'title' }} @@ -208,7 +208,7 @@

    {% if inner_hit.highlight|get_key_or_none:"domains.name" %} {% with l=inner_hit.highlight|get_key_or_none:"domains.name" %} - {{ inner_hit.source.type_display }} -- {{ l.0|safe }} -- {{ inner_hit.source.doc_display }} + {{ inner_hit.source.type_display }} -- {{ l.0|safe }} -- in {{ inner_hit.source.doc_display }} {% endwith %} {% else %} {{ inner_hit.source.type_display }} -- {{ inner_hit.source.name }} -- {{ inner_hit.source.doc_display }} From 5cae508c7d9b58420a3b3383b4ac3eac59fb2e15 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 4 Jul 2019 01:32:29 +0530 Subject: [PATCH 28/59] change variable name --- readthedocs/templates/search/elastic_search.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index ab6eb959b8e..d403867c849 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -207,8 +207,8 @@

    {% if inner_hit.highlight|get_key_or_none:"domains.name" %} - {% with l=inner_hit.highlight|get_key_or_none:"domains.name" %} - {{ inner_hit.source.type_display }} -- {{ l.0|safe }} -- in {{ inner_hit.source.doc_display }} + {% with domain_name=inner_hit.highlight|get_key_or_none:"domains.name" %} + {{ inner_hit.source.type_display }} -- {{ domain_name.0|safe }} -- in {{ inner_hit.source.doc_display }} {% endwith %} {% else %} {{ inner_hit.source.type_display }} -- {{ inner_hit.source.name }} -- {{ inner_hit.source.doc_display }} @@ -219,8 +219,8 @@

    {% if inner_hit.highlight|get_key_or_none:"sections.title" %} - {% with l=inner_hit.highlight|get_key_or_none:"sections.title" %} - {{ l.0|safe }} + {% with section_title=inner_hit.highlight|get_key_or_none:"sections.title" %} + {{ section_title.0|safe }} {% endwith %} {% else %} {{ inner_hit.source.title }} From adb74ed083b5cdb2f5b788a5cbb72e4380a36b5e Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 4 Jul 2019 12:44:51 +0530 Subject: [PATCH 29/59] fix template --- readthedocs/search/views.py | 14 +++---- .../templates/search/elastic_search.html | 37 +++++++------------ 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index 5f086a78c1f..1c131b0b980 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -107,9 +107,11 @@ def elastic_search(request, project_slug=None): # sorting inner_hits (if present) try: - for hit in results.hits.hits: - sections = hit['inner_hits'].get('sections', []) - domains = hit['inner_hits'].get('domains', []) + for result in results: + + inner_hits = result.meta.inner_hits + sections = inner_hits.sections or [] + domains = inner_hits.domains or [] all_results = list(sections) + list(domains) sorted_results = [ @@ -128,13 +130,11 @@ def elastic_search(request, project_slug=None): for hit in sorted(all_results, key=utils._get_hit_score, reverse=True) ] - hit['inner_hits'].pop('sections', None) - hit['inner_hits'].pop('domains', None) - hit['inner_hits'] = sorted_results + result.meta.inner_hits = sorted_results except: # if the control comes in this block, - # that implies that there was PageSearch + # that implies that there was a PageSearch pass log.debug('Search results: %s', pformat(results.to_dict())) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index d403867c849..7532a795f8b 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -164,9 +164,9 @@

    {% for result in results %} - {% if 'project' in result.meta.index %} -
  • -

    +

  • +

    + {% if 'project' in result.meta.index %} {{ result.name }} ({{ result.slug }}) @@ -177,27 +177,16 @@

    {% empty %}

    No description for project.

    {% endfor %} -

    -

  • - {% elif 'page' in result.meta.index %} - {% endif %} - {% empty %} -
  • {% trans "No results found." %}
  • - {% endfor %} - - {% for hit in results.hits.hits %} - {% if 'page' in hit|key:"_index" %} -
  • -

    - - {{ hit|key:'_source'|key:'project' }} - {{ hit|key:'_source'|key:'title' }} + {% elif 'page' in result.meta.index %} + + {{ result.project }} - {% if result.meta.highlight.title %} {{ result.meta.highlight.title.0|safe }} {% else %} {{ result.title }} {% endif %} - {% for inner_hit in hit.inner_hits %} + {% for inner_hit in result.meta.inner_hits %} {% if inner_hit.type == 'domains' %}

    - + {% if inner_hit.source.display_name|length >= 2 %} ({{ inner_hit.source.role_name }}) {{ inner_hit.source.display_name}} {% else %} @@ -217,7 +206,7 @@

    {% elif inner_hit.type == 'sections' %}

    - + {% if inner_hit.highlight|get_key_or_none:"sections.title" %} {% with section_title=inner_hit.highlight|get_key_or_none:"sections.title" %} {{ section_title.0|safe }} @@ -238,9 +227,11 @@

    {% endif %} {% endfor %} -

    -

  • - {% endif %} + {% endif %} +

    +

  • + {% empty %} +
  • {% trans "No results found." %}
  • {% endfor %}

    From d500d98d57505e14f678f965e255cc5a786d4f39 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 4 Jul 2019 12:56:21 +0530 Subject: [PATCH 30/59] fix lint --- readthedocs/search/utils.py | 2 +- readthedocs/search/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/readthedocs/search/utils.py b/readthedocs/search/utils.py index 3f562384ac4..5d9a6fe248b 100644 --- a/readthedocs/search/utils.py +++ b/readthedocs/search/utils.py @@ -178,7 +178,7 @@ def _remove_newlines_from_dict(highlight): """ for k, v in highlight.items(): if isinstance(v, dict): - highlight[k] = self._remove_newlines_from_dict(v) + highlight[k] = _remove_newlines_from_dict(v) else: # elastic returns the contents of the # highlighted field in a list. diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index 1c131b0b980..0fb61da5efc 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -132,7 +132,7 @@ def elastic_search(request, project_slug=None): result.meta.inner_hits = sorted_results - except: + except Exception as e: # if the control comes in this block, # that implies that there was a PageSearch pass From 9461d4f45d55f3c965301e249291bca7bc7fa61e Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 4 Jul 2019 13:32:52 +0530 Subject: [PATCH 31/59] use python datatypes --- readthedocs/search/api.py | 11 ++++++----- readthedocs/search/views.py | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/readthedocs/search/api.py b/readthedocs/search/api.py index adf028b4133..4c6bd4c8d47 100644 --- a/readthedocs/search/api.py +++ b/readthedocs/search/api.py @@ -1,3 +1,4 @@ +import itertools import logging from pprint import pformat @@ -43,18 +44,18 @@ def get_highlight(self, obj): def get_inner_hits(self, obj): inner_hits = getattr(obj.meta, 'inner_hits', None) if inner_hits: - sections = inner_hits.sections - domains = inner_hits.domains - all_results = list(sections) + list(domains) + sections = inner_hits.sections or [] + domains = inner_hits.domains or [] + all_results = itertools.chain(sections, domains) - sorted_results = [ + sorted_results = ( { 'type': hit._nested.field, '_source': hit._source.to_dict(), 'highlight': self._get_inner_hits_highlights(hit), } for hit in sorted(all_results, key=utils._get_hit_score, reverse=True) - ] + ) return sorted_results diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index 0fb61da5efc..a8b0b346594 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -1,5 +1,6 @@ """Search views.""" import collections +import itertools import logging from pprint import pformat @@ -112,9 +113,9 @@ def elastic_search(request, project_slug=None): inner_hits = result.meta.inner_hits sections = inner_hits.sections or [] domains = inner_hits.domains or [] - all_results = list(sections) + list(domains) + all_results = itertools.chain(sections, domains) - sorted_results = [ + sorted_results = ( { 'type': hit._nested.field, @@ -128,7 +129,7 @@ def elastic_search(request, project_slug=None): ), } for hit in sorted(all_results, key=utils._get_hit_score, reverse=True) - ] + ) result.meta.inner_hits = sorted_results From 75dcc2ff5c0b1680efc64851d65bce6186142bf9 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 4 Jul 2019 14:04:57 +0530 Subject: [PATCH 32/59] remove highlight url param from sections and domains --- readthedocs/templates/search/elastic_search.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index 7532a795f8b..21023bc53cc 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -186,7 +186,7 @@

    {% for inner_hit in result.meta.inner_hits %} {% if inner_hit.type == 'domains' %}

    - + {% if inner_hit.source.display_name|length >= 2 %} ({{ inner_hit.source.role_name }}) {{ inner_hit.source.display_name}} {% else %} @@ -206,7 +206,7 @@

    {% elif inner_hit.type == 'sections' %}

    - + {% if inner_hit.highlight|get_key_or_none:"sections.title" %} {% with section_title=inner_hit.highlight|get_key_or_none:"sections.title" %} {{ section_title.0|safe }} From ea36138b30537ffd8a89a936b6526a5658c9d515 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Thu, 4 Jul 2019 16:01:02 +0530 Subject: [PATCH 33/59] fix clashing css classes --- .../core/static-src/core/js/doc-embed/search.js | 10 +++++----- .../core/static/core/js/readthedocs-doc-embed.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index b6af1d57658..33e3034b5a4 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -48,10 +48,10 @@ function attach_elastic_search_query(data) { } // Creating the result from elements - var link = doc.link + DOCUMENTATION_OPTIONS.FILE_SUFFIX + - '?highlight=' + $.urlencode(query); + var link = doc.link + DOCUMENTATION_OPTIONS.FILE_SUFFIX; + var highlight_link = link + "?highlight=" + $.urlencode(query) - var item = $('', {'href': link}); + var item = $('', {'href': highlight_link}); item.html(title); item.find('em').addClass('highlighted'); list_item.append(item); @@ -72,7 +72,7 @@ function attach_elastic_search_query(data) { if(inner_hits[j].type === "sections") { var section = inner_hits[j]; - var section_subtitle = $('

    '); + var section_subtitle = $('
    '); var section_subtitle_link = $(''); var section_content = $(''); @@ -111,7 +111,7 @@ function attach_elastic_search_query(data) { if (inner_hits[j].type === "domains") { var domain = inner_hits[j]; - var domain_subtitle = $('
    '); + var domain_subtitle = $('"),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=E(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX+"?highlight="+$.urlencode(k),d=$("
    ",{href:l});if(d.html(a),d.find("em").addClass("highlighted"),s.append(d),n.project!==T){var c=" (from project "+n.project+")",u=$("",{text:c});s.append(u)}for(var p=0;p');if("sections"===o[p].type){var f=o[p],g=$('
    '),m=$(''),v=$("");f.highlight&&(f.highlight["sections.title"]?m.html(E(f.highlight["sections.title"][0])):m.html(f._source.title),f.highlight["sections.content"]?v.html("... "+E(f.highlight["sections.content"][0])+" ..."):v.html(f._source.content.substring(0,100)+" ...")),g.html(m),h.append(g),h.append(v),h.find("em").addClass("highlighted")}if("domains"===o[p].type){var w=o[p],b=$('
    '),y=$(''),x=$("");"string"==typeof w._source.display_name&&2<=w._source.display_name.length?y.html("("+w._source.role_name+")"+w._source.display_name):y.html(w._source.role_name),x.append(w._source.type_display+" -- "),w.highlight&&(w.highlight["domains.name"]?x.append(E(w.highlight["domains.name"][0])):x.append(w._source.name)),x.append(" -- in "+w._source.doc_display),b.append(y),h.append(b),h.append(x),h.find("em").addClass("highlighted")}s.append(h),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(k),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(k)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function y(e){return e.replace(p,'"')}function _(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=y,i.escapeHtmlEntities=_,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return y(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:y(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return y(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=A(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(T),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==E){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=$("
    "),v=$(''),w=$("");g.highlight&&(g.highlight["sections.title"]?v.html(A(g.highlight["sections.title"][0])):v.html(g._source.title),g.highlight["sections.content"]?w.html("... "+A(g.highlight["sections.content"][0])+" ..."):w.html(g._source.content.substring(0,100)+" ...")),m.html(v),f.append(m),f.append(w),f.find("em").addClass("highlighted")}if("domains"===o[h].type){var b=o[h],y=$("
    "),x=$(''),k=$("");"string"==typeof b._source.display_name&&2<=b._source.display_name.length?x.html("("+b._source.role_name+")"+b._source.display_name):x.html(b._source.role_name),k.append(b._source.type_display+" -- "),b.highlight&&(b.highlight["domains.name"]?k.append(A(b.highlight["domains.name"][0])):k.append(b._source.name)),k.append(" -- in "+b._source.doc_display),y.append(x),f.append(y),f.append(k),f.find("em").addClass("highlighted")}s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(T),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(T)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file From 0817d43edf4f32d42d69ea95a79fe7b01ec7c1a7 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 01:29:23 +0530 Subject: [PATCH 34/59] use underscore.js template --- .../static-src/core/js/doc-embed/search.js | 112 ++++++++++-------- .../static/core/js/readthedocs-doc-embed.js | 2 +- 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index 33e3034b5a4..3660739e37d 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -68,86 +68,102 @@ function attach_elastic_search_query(data) { var contents = $('
    '); + var section_template = + ' \ + \ + <%= section_content %> \ + '; + + var domain_template = + ' \ + \ + <%= domain_content %> \ + '; + // if the result is page section if(inner_hits[j].type === "sections") { var section = inner_hits[j]; - var section_subtitle = $('
    '); - var section_subtitle_link = $(''); - var section_content = $(''); + var section_subtitle = section._source.title; + var section_subtitle_link = link + "#" + section._source.id; + var section_content = section._source.content.substring(0, 100) + " ..."; if (section.highlight) { if (section.highlight["sections.title"]) { - section_subtitle_link.html( - xss(section.highlight["sections.title"][0]) - ); - } else { - section_subtitle_link.html( - section._source.title - ); + section_subtitle = xss(section.highlight["sections.title"][0]); } if (section.highlight["sections.content"]) { - section_content.html( - "... " + - xss(section.highlight["sections.content"][0]) + - " ..." - ); - } else { - section_content.html( - section._source.content.substring(0, 100) + - " ..." - ); + section_content = "... " + xss(section.highlight["sections.content"][0]) +" ..."; } } - section_subtitle.html(section_subtitle_link); - contents.append(section_subtitle); - contents.append(section_content); - contents.find('em').addClass('highlighted'); + contents.append( + $u.template( + section_template, + { + section_subtitle_link: section_subtitle_link, + section_subtitle: section_subtitle, + section_content: section_content + } + ) + ); } // if the result is a sphinx domain object if (inner_hits[j].type === "domains") { var domain = inner_hits[j]; - var domain_subtitle = $('
    '); - var domain_subtitle_link = $(''); - var domain_content = $(''); + var domain_subtitle = domain._source.role_name; + var domain_subtitle_link = link + "#" + domain._source.anchor; + var domain_content = ""; if ( typeof domain._source.display_name === "string" && - domain._source.display_name.length >= 2 + domain._source.display_name.length >= 2 // "2" because some domain display_name are "-" ) { - domain_subtitle_link.html( - "(" + - domain._source.role_name + - ")" + - domain._source.display_name - ); - } else { - domain_subtitle_link.html(domain._source.role_name); + domain_subtitle = "(" + domain._source.role_name + ")" + domain._source.display_name; } // preparing domain_content - domain_content.append(domain._source.type_display + " -- "); + // domain_content = type_display -- + domain_content = domain._source.type_display + " -- "; if (domain.highlight) { if (domain.highlight["domains.name"]) { - domain_content.append( - xss(domain.highlight["domains.name"][0]) - ); + // domain_content = type_display -- name + domain_content += xss(domain.highlight["domains.name"][0]); } else { - domain_content.append(domain._source.name); + // domain_content = type_display -- name + domain_content += domain._source.name; } + } else { + // domain_content = type_display -- name + domain_content += domain._source.name; } - domain_content.append(" -- in " + domain._source.doc_display); - - domain_subtitle.append(domain_subtitle_link); - contents.append(domain_subtitle); - contents.append(domain_content); - contents.find('em').addClass('highlighted'); + // domain_content = type_display -- name -- in doc_display + domain_content += " -- in " + domain._source.doc_display; + + contents.append( + $u.template( + domain_template, + { + domain_subtitle_link: domain_subtitle_link, + domain_subtitle: domain_subtitle, + domain_content: domain_content + } + ) + ); } - + + contents.find('em').addClass('highlighted'); list_item.append(contents); list_item.append($("
    ")); } diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js index c7e2c0c5fa8..69cdc80ed5f 100644 --- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js +++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js @@ -1 +1 @@ -!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function y(e){return e.replace(p,'"')}function _(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=y,i.escapeHtmlEntities=_,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return y(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:y(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return y(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=A(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(T),c=$("
    ",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==E){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=$("
    "),v=$(''),w=$("");g.highlight&&(g.highlight["sections.title"]?v.html(A(g.highlight["sections.title"][0])):v.html(g._source.title),g.highlight["sections.content"]?w.html("... "+A(g.highlight["sections.content"][0])+" ..."):w.html(g._source.content.substring(0,100)+" ...")),m.html(v),f.append(m),f.append(w),f.find("em").addClass("highlighted")}if("domains"===o[h].type){var b=o[h],y=$("
    "),x=$(''),k=$("");"string"==typeof b._source.display_name&&2<=b._source.display_name.length?x.html("("+b._source.role_name+")"+b._source.display_name):x.html(b._source.role_name),k.append(b._source.type_display+" -- "),b.highlight&&(b.highlight["domains.name"]?k.append(A(b.highlight["domains.name"][0])):k.append(b._source.name)),k.append(" -- in "+b._source.doc_display),y.append(x),f.append(y),f.append(k),f.find("em").addClass("highlighted")}s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(T),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(T)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=A(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(T),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==E){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=g._source.content.substring(0,100)+" ...";g.highlight&&(g.highlight["sections.title"]&&(m=A(g.highlight["sections.title"][0])),g.highlight["sections.content"]&&(w="... "+A(g.highlight["sections.content"][0])+" ...")),f.append($u.template(' <%= section_content %> ',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var b=o[h],y=b._source.role_name,x=l+"#"+b._source.anchor,k="";"string"==typeof b._source.display_name&&2<=b._source.display_name.length&&(y="("+b._source.role_name+")"+b._source.display_name),k=b._source.type_display+" -- ",b.highlight&&b.highlight["domains.name"]?k+=A(b.highlight["domains.name"][0]):k+=b._source.name,k+=" -- in "+b._source.doc_display,f.append($u.template(' <%= domain_content %> ',{domain_subtitle_link:x,domain_subtitle:y,domain_content:k}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(T),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(T)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file From 530545803402e57521a478bde9aa8ea62a339fdb Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 01:32:48 +0530 Subject: [PATCH 35/59] add _ with variables --- readthedocs/search/faceted_search.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 220db94f956..a5c44198800 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -101,14 +101,14 @@ class PageSearchBase(RTDFacetedSearch): doc_types = [PageDocument] index = PageDocument._doc_type.index - outer_fields = ['title'] - section_fields = ['sections.title', 'sections.content'] - domain_fields = [ + _outer_fields = ['title'] + _section_fields = ['sections.title', 'sections.content'] + _domain_fields = [ 'domains.type_display', 'domains.name', 'domains.display_name', ] - fields = outer_fields + fields = _outer_fields # need to search for both 'and' and 'or' operations # the score of and should be higher as it satisfies both or and and @@ -125,7 +125,7 @@ def query(self, search, query): sections_nested_query = self.generate_nested_query( query=query, path='sections', - fields=self.section_fields, + fields=self._section_fields, inner_hits={ 'highlight': { 'number_of_fragments': 1, @@ -141,7 +141,7 @@ def query(self, search, query): domains_nested_query = self.generate_nested_query( query=query, path='domains', - fields=self.domain_fields, + fields=self._domain_fields, inner_hits={ 'highlight': { 'number_of_fragments': 1, From 68cb7afa0a20caa5ac1f4e5886b5ed840ae35aa2 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 01:35:52 +0530 Subject: [PATCH 36/59] add comment in template --- readthedocs/templates/search/elastic_search.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index 21023bc53cc..cbeb84209e7 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -187,6 +187,8 @@

    {% if inner_hit.type == 'domains' %}

    + + {% comment %} ">= 2" because some display_name are just "-" {% endcomment %} {% if inner_hit.source.display_name|length >= 2 %} ({{ inner_hit.source.role_name }}) {{ inner_hit.source.display_name}} {% else %} From d62bf3eb0e14b57e86ec158ee9f858063da8af37 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 01:36:14 +0530 Subject: [PATCH 37/59] use .iterator() --- readthedocs/search/documents.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index b9cae424b0d..d9fd4490214 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -111,7 +111,7 @@ class Meta: def prepare_domains(self, html_file): """Prepares and returns the values for domains field.""" - domains_qs = html_file.sphinx_domains.all() + domains_qs = html_file.sphinx_domains.all().iterator() domains_qs = domains_qs.exclude(domain='std', type__in=['doc', 'label']) all_domains = [{ From ed16e5663bcc1c11a3387c2f284c7c22335f87f8 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 15:02:32 +0530 Subject: [PATCH 38/59] show multiple results per section, if present --- .../static-src/core/js/doc-embed/search.js | 21 +++++++++++------ .../static/core/js/readthedocs-doc-embed.js | 2 +- .../templates/search/elastic_search.html | 23 ++++++++++--------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index 3660739e37d..490e440ca05 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -4,6 +4,7 @@ var rtddata = require('./rtd-data'); var xss = require('xss/lib/index'); +var MAX_RESULT_PER_SECTION = 3; /* @@ -74,9 +75,11 @@ function attach_elastic_search_query(data) { <%= section_subtitle %> \ \

    \ - \ - <%= section_content %> \ - '; + <% for (var i = 0; i < section_content.length; ++i) { %> \ +
    \ + <%= section_content[i] %> \ +
    \ + <% } %>'; var domain_template = '
    \ @@ -94,7 +97,7 @@ function attach_elastic_search_query(data) { var section = inner_hits[j]; var section_subtitle = section._source.title; var section_subtitle_link = link + "#" + section._source.id; - var section_content = section._source.content.substring(0, 100) + " ..."; + var section_content = [ section._source.content.substring(0, 100) + " ..." ]; if (section.highlight) { if (section.highlight["sections.title"]) { @@ -102,7 +105,11 @@ function attach_elastic_search_query(data) { } if (section.highlight["sections.content"]) { - section_content = "... " + xss(section.highlight["sections.content"][0]) +" ..."; + var content = section.highlight["sections.content"]; + section_content = []; + for (var k = 0; k < content.length && k < MAX_RESULT_PER_SECTION; ++k) { + section_content.push("... " + xss(content[k]) + " ..."); + } } } @@ -128,9 +135,9 @@ function attach_elastic_search_query(data) { if ( typeof domain._source.display_name === "string" && - domain._source.display_name.length >= 2 // "2" because some domain display_name are "-" + domain._source.display_name.length >= 1 ) { - domain_subtitle = "(" + domain._source.role_name + ")" + domain._source.display_name; + domain_subtitle = "(" + domain._source.role_name + ") " + domain._source.display_name; } // preparing domain_content diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js index 69cdc80ed5f..9e865709eee 100644 --- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js +++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js @@ -1 +1 @@ -!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=A(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(T),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==E){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=g._source.content.substring(0,100)+" ...";g.highlight&&(g.highlight["sections.title"]&&(m=A(g.highlight["sections.title"][0])),g.highlight["sections.content"]&&(w="... "+A(g.highlight["sections.content"][0])+" ...")),f.append($u.template(' <%= section_content %> ',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var b=o[h],y=b._source.role_name,x=l+"#"+b._source.anchor,k="";"string"==typeof b._source.display_name&&2<=b._source.display_name.length&&(y="("+b._source.role_name+")"+b._source.display_name),k=b._source.type_display+" -- ",b.highlight&&b.highlight["domains.name"]?k+=A(b.highlight["domains.name"][0]):k+=b._source.name,k+=" -- in "+b._source.doc_display,f.append($u.template(' <%= domain_content %> ',{domain_subtitle_link:x,domain_subtitle:y,domain_content:k}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(T),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(T)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=O(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(A),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==S){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=[g._source.content.substring(0,100)+" ..."];if(g.highlight&&(g.highlight["sections.title"]&&(m=O(g.highlight["sections.title"][0])),g.highlight["sections.content"])){var b=g.highlight["sections.content"];w=[];for(var y=0;y <%= section_subtitle %>
    <% for (var i = 0; i < section_content.length; ++i) { %>
    <%= section_content[i] %>
    <% } %>',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var x=o[h],k=x._source.role_name,T=l+"#"+x._source.anchor,E="";"string"==typeof x._source.display_name&&1<=x._source.display_name.length&&(k="("+x._source.role_name+") "+x._source.display_name),E=x._source.type_display+" -- ",x.highlight&&x.highlight["domains.name"]?E+=O(x.highlight["domains.name"][0]):E+=x._source.name,E+=" -- in "+x._source.doc_display,f.append($u.template(' <%= domain_content %> ',{domain_subtitle_link:T,domain_subtitle:k,domain_content:E}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(A),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(A)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index cbeb84209e7..f07cb201656 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -188,8 +188,7 @@

    - {% comment %} ">= 2" because some display_name are just "-" {% endcomment %} - {% if inner_hit.source.display_name|length >= 2 %} + {% if inner_hit.source.display_name|length >= 1 %} ({{ inner_hit.source.role_name }}) {{ inner_hit.source.display_name}} {% else %} {{ inner_hit.source.role_name }} @@ -218,15 +217,17 @@

    {% endif %}

    -

    - {% if inner_hit.highlight|get_key_or_none:"sections.content" %} - {% with l=inner_hit.highlight|get_key_or_none:"sections.content" %} - ... {{ l.0|safe }} ... - {% endwith %} - {% else %} - {{ inner_hit.source.content|slice:"100" }} ... - {% endif %} -

    + {% if inner_hit.highlight|get_key_or_none:"sections.content" %} + {% with section_content=inner_hit.highlight|get_key_or_none:"sections.content" %} + {% for content in section_content %} +

    + ... {{ content|safe }} ... +

    + {% endfor %} + {% endwith %} + {% else %} + {{ inner_hit.source.content|slice:"100" }} ... + {% endif %} {% endif %} {% endfor %} {% endif %} From 0ed64f7b7f60f6d3def5fa49e2f233933dadcc41 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 17:41:26 +0530 Subject: [PATCH 39/59] fix sphinx indexing --- readthedocs/projects/tasks.py | 31 +++++++------------------------ readthedocs/search/documents.py | 6 ++++-- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/readthedocs/projects/tasks.py b/readthedocs/projects/tasks.py index edb8e2a6366..00023795a53 100644 --- a/readthedocs/projects/tasks.py +++ b/readthedocs/projects/tasks.py @@ -1282,13 +1282,8 @@ def fileify(version_pk, commit, build): except Exception: log.exception('Failed during ImportedFile creation') - try: - _update_intersphinx_data(version, path, commit, build) - except Exception: - log.exception('Failed during SphinxDomain creation') - -def _update_intersphinx_data(version, path, commit, build): +def _create_intersphinx_data(version, path, commit, build): """ Update intersphinx data for this version. @@ -1376,24 +1371,6 @@ def warn(self, msg): build=build, ) - # Index new SphinxDomain objects to elasticsearch - index_new_files(model=SphinxDomain, version=version, build=build) - - # Remove old SphinxDomain from elasticsearch - remove_indexed_files( - model=SphinxDomain, - version=version, - build=build, - ) - - # Delete SphinxDomain objects from the previous build of the version. - ( - SphinxDomain.objects - .filter(project=version.project, version=version) - .exclude(build=build) - .delete() - ) - def clean_build(version_pk): """Clean the files used in the build of the given version.""" @@ -1481,6 +1458,12 @@ def _manage_imported_files(version, path, commit, build): build=build, ) + # create SphinxDomain objects + try: + _create_intersphinx_data(version, path, commit, build) + except Exception: + log.exception('Failed during SphinxDomain objects creation') + # Index new HTMLFiles to elasticsearch index_new_files(model=HTMLFile, version=version, build=build) diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index d9fd4490214..7d9a74e8e27 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -111,8 +111,10 @@ class Meta: def prepare_domains(self, html_file): """Prepares and returns the values for domains field.""" - domains_qs = html_file.sphinx_domains.all().iterator() - domains_qs = domains_qs.exclude(domain='std', type__in=['doc', 'label']) + domains_qs = html_file.sphinx_domains.exclude( + domain='std', + type__in=['doc', 'label'] + ).iterator() all_domains = [{ 'role_name': domain.role_name, From f9883021c84f2295679610639346c55e0f706680 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 17:55:22 +0530 Subject: [PATCH 40/59] don't index '-' value of domain.display_name --- readthedocs/search/documents.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/readthedocs/search/documents.py b/readthedocs/search/documents.py index 7d9a74e8e27..a09a78aed80 100644 --- a/readthedocs/search/documents.py +++ b/readthedocs/search/documents.py @@ -116,15 +116,18 @@ def prepare_domains(self, html_file): type__in=['doc', 'label'] ).iterator() - all_domains = [{ - 'role_name': domain.role_name, - 'doc_name': domain.doc_name, - 'anchor': domain.anchor, - 'type_display': domain.type_display, - 'doc_display': domain.doc_display, - 'name': domain.name, - 'display_name': domain.display_name, - } for domain in domains_qs] + all_domains = [ + { + 'role_name': domain.role_name, + 'doc_name': domain.doc_name, + 'anchor': domain.anchor, + 'type_display': domain.type_display, + 'doc_display': domain.doc_display, + 'name': domain.name, + 'display_name': domain.display_name if domain.display_name != '-' else '', + } + for domain in domains_qs + ] return all_domains From 429b3e90d116f266eb076e1a4bb69e05e3831752 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Tue, 9 Jul 2019 18:18:19 +0530 Subject: [PATCH 41/59] fix eslint --- .../static-src/core/js/doc-embed/search.js | 54 ++++++++++--------- .../static/core/js/readthedocs-doc-embed.js | 2 +- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index 490e440ca05..fcdcbe8bd22 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -50,7 +50,7 @@ function attach_elastic_search_query(data) { // Creating the result from elements var link = doc.link + DOCUMENTATION_OPTIONS.FILE_SUFFIX; - var highlight_link = link + "?highlight=" + $.urlencode(query) + var highlight_link = link + "?highlight=" + $.urlencode(query); var item = $('', {'href': highlight_link}); item.html(title); @@ -69,27 +69,27 @@ function attach_elastic_search_query(data) { var contents = $('
    '); - var section_template = - ' \ - <% for (var i = 0; i < section_content.length; ++i) { %> \ -
    \ - <%= section_content[i] %> \ -
    \ - <% } %>'; - - var domain_template = - ' \ - \ - <%= domain_content %> \ - '; + var section_template = '' + + '' + + '<% for (var i = 0; i < section_content.length; ++i) { %>' + + '
    ' + + '<%= section_content[i] %>' + + '
    ' + + '<% } %>'; + + var domain_template = '' + + '' + + '' + + '<%= domain_content %>' + + ''; // if the result is page section if(inner_hits[j].type === "sections") { @@ -97,7 +97,7 @@ function attach_elastic_search_query(data) { var section = inner_hits[j]; var section_subtitle = section._source.title; var section_subtitle_link = link + "#" + section._source.id; - var section_content = [ section._source.content.substring(0, 100) + " ..." ]; + var section_content = [section._source.content.substring(0, 100) + " ..."]; if (section.highlight) { if (section.highlight["sections.title"]) { @@ -107,7 +107,11 @@ function attach_elastic_search_query(data) { if (section.highlight["sections.content"]) { var content = section.highlight["sections.content"]; section_content = []; - for (var k = 0; k < content.length && k < MAX_RESULT_PER_SECTION; ++k) { + for ( + var k = 0; + k < content.length && k < MAX_RESULT_PER_SECTION; + k += 1 + ) { section_content.push("... " + xss(content[k]) + " ..."); } } @@ -169,7 +173,7 @@ function attach_elastic_search_query(data) { ) ); } - + contents.find('em').addClass('highlighted'); list_item.append(contents); list_item.append($("
    ")); diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js index 9e865709eee..6fed0f6843c 100644 --- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js +++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js @@ -1 +1 @@ -!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=O(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(A),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==S){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=[g._source.content.substring(0,100)+" ..."];if(g.highlight&&(g.highlight["sections.title"]&&(m=O(g.highlight["sections.title"][0])),g.highlight["sections.content"])){var b=g.highlight["sections.content"];w=[];for(var y=0;y <%= section_subtitle %>

    <% for (var i = 0; i < section_content.length; ++i) { %>
    <%= section_content[i] %>
    <% } %>',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var x=o[h],k=x._source.role_name,T=l+"#"+x._source.anchor,E="";"string"==typeof x._source.display_name&&1<=x._source.display_name.length&&(k="("+x._source.role_name+") "+x._source.display_name),E=x._source.type_display+" -- ",x.highlight&&x.highlight["domains.name"]?E+=O(x.highlight["domains.name"][0]):E+=x._source.name,E+=" -- in "+x._source.doc_display,f.append($u.template(' <%= domain_content %> ',{domain_subtitle_link:T,domain_subtitle:k,domain_content:E}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(A),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(A)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=O(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(A),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==S){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=[g._source.content.substring(0,100)+" ..."];if(g.highlight&&(g.highlight["sections.title"]&&(m=O(g.highlight["sections.title"][0])),g.highlight["sections.content"])){var b=g.highlight["sections.content"];w=[];for(var y=0;y<%= section_subtitle %>
    <% for (var i = 0; i < section_content.length; ++i) { %>
    <%= section_content[i] %>
    <% } %>',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var x=o[h],k=x._source.role_name,T=l+"#"+x._source.anchor,E="";"string"==typeof x._source.display_name&&1<=x._source.display_name.length&&(k="("+x._source.role_name+") "+x._source.display_name),E=x._source.type_display+" -- ",x.highlight&&x.highlight["domains.name"]?E+=O(x.highlight["domains.name"][0]):E+=x._source.name,E+=" -- in "+x._source.doc_display,f.append($u.template('<%= domain_content %>',{domain_subtitle_link:T,domain_subtitle:k,domain_content:E}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(A),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(A)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file From aeaba6f206b624c082589f199dcb6b9a41a7a3dd Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 10 Jul 2019 14:08:26 +0530 Subject: [PATCH 42/59] reduce complexity in search.js --- .../core/static-src/core/js/doc-embed/search.js | 15 ++++----------- .../core/static/core/js/readthedocs-doc-embed.js | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index fcdcbe8bd22..0c61f51eb29 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -136,6 +136,7 @@ function attach_elastic_search_query(data) { var domain_subtitle = domain._source.role_name; var domain_subtitle_link = link + "#" + domain._source.anchor; var domain_content = ""; + var domain_name = domain._source.name; if ( typeof domain._source.display_name === "string" && @@ -144,23 +145,15 @@ function attach_elastic_search_query(data) { domain_subtitle = "(" + domain._source.role_name + ") " + domain._source.display_name; } - // preparing domain_content - // domain_content = type_display -- - domain_content = domain._source.type_display + " -- "; if (domain.highlight) { if (domain.highlight["domains.name"]) { // domain_content = type_display -- name - domain_content += xss(domain.highlight["domains.name"][0]); - } else { - // domain_content = type_display -- name - domain_content += domain._source.name; + domain_name = xss(domain.highlight["domains.name"][0]); } - } else { - // domain_content = type_display -- name - domain_content += domain._source.name; } + // domain_content = type_display -- name -- in doc_display - domain_content += " -- in " + domain._source.doc_display; + domain_content = domain._source.type_display + " -- " + domain_name + " -- in " + domain._source.doc_display; contents.append( $u.template( diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js index 6fed0f6843c..9b17881ccce 100644 --- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js +++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js @@ -1 +1 @@ -!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=O(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(A),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==S){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=[g._source.content.substring(0,100)+" ..."];if(g.highlight&&(g.highlight["sections.title"]&&(m=O(g.highlight["sections.title"][0])),g.highlight["sections.content"])){var b=g.highlight["sections.content"];w=[];for(var y=0;y<%= section_subtitle %>
    <% for (var i = 0; i < section_content.length; ++i) { %>
    <%= section_content[i] %>
    <% } %>',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var x=o[h],k=x._source.role_name,T=l+"#"+x._source.anchor,E="";"string"==typeof x._source.display_name&&1<=x._source.display_name.length&&(k="("+x._source.role_name+") "+x._source.display_name),E=x._source.type_display+" -- ",x.highlight&&x.highlight["domains.name"]?E+=O(x.highlight["domains.name"][0]):E+=x._source.name,E+=" -- in "+x._source.doc_display,f.append($u.template('<%= domain_content %>',{domain_subtitle_link:T,domain_subtitle:k,domain_content:E}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(A),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(A)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=R(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(S),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==O){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=[g._source.content.substring(0,100)+" ..."];if(g.highlight&&(g.highlight["sections.title"]&&(m=R(g.highlight["sections.title"][0])),g.highlight["sections.content"])){var b=g.highlight["sections.content"];w=[];for(var y=0;y<%= section_subtitle %>
    <% for (var i = 0; i < section_content.length; ++i) { %>
    <%= section_content[i] %>
    <% } %>',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var x,k=o[h],T=k._source.role_name,E=l+"#"+k._source.anchor,A=k._source.name;"string"==typeof k._source.display_name&&1<=k._source.display_name.length&&(T="("+k._source.role_name+") "+k._source.display_name),!k.highlight||k.highlight["domains.name"]&&(A=R(k.highlight["domains.name"][0])),x=k._source.type_display+" -- "+A+" -- in "+k._source.doc_display,f.append($u.template('<%= domain_content %>',{domain_subtitle_link:E,domain_subtitle:T,domain_content:x}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(S),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(S)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file From 6f9b2bccf60017821fa503e7a9b08185e8d50ff7 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 10 Jul 2019 14:52:54 +0530 Subject: [PATCH 43/59] refactor tasks.py file --- readthedocs/projects/tasks.py | 41 +++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/readthedocs/projects/tasks.py b/readthedocs/projects/tasks.py index 4adc5b44a0e..1701cf20295 100644 --- a/readthedocs/projects/tasks.py +++ b/readthedocs/projects/tasks.py @@ -1278,14 +1278,25 @@ def fileify(version_pk, commit, build): } ) try: - _manage_imported_files(version, path, commit, build) + changed_files = _create_imported_files(version, path, commit, build) except Exception: + changed_files = set() log.exception('Failed during ImportedFile creation') + try: + _create_intersphinx_data(version, path, commit, build) + except Exception: + log.exception('Failed during SphinxDomain creation') + + try: + _sync_imported_files(version, build, changed_files) + except Exception: + log.exception('Failed during ImportedFile syncing') + def _create_intersphinx_data(version, path, commit, build): """ - Update intersphinx data for this version. + Create intersphinx data for this version. :param version: Version instance :param path: Path to search @@ -1401,14 +1412,16 @@ def clean_build(version_pk): return True -def _manage_imported_files(version, path, commit, build): +def _create_imported_files(version, path, commit, build): """ - Update imported files for version. + Create imported files for version. :param version: Version instance :param path: Path to search :param commit: Commit that updated path :param build: Build id + :returns: paths of changed files + :rtype: set """ changed_files = set() @@ -1458,16 +1471,22 @@ def _manage_imported_files(version, path, commit, build): build=build, ) - # create SphinxDomain objects - try: - _create_intersphinx_data(version, path, commit, build) - except Exception: - log.exception('Failed during SphinxDomain objects creation') + return changed_files + + +def _sync_imported_files(version, build, changed_files): + """ + Sync/Update/Delete ImportedFiles objects of this version. + + :param version: Version instance + :param build: Build id + :param changed_files: path of changed files + """ - # Index new HTMLFiles to elasticsearch + # Index new HTMLFiles to ElasticSearch index_new_files(model=HTMLFile, version=version, build=build) - # Remove old HTMLFiles from elasticsearch + # Remove old HTMLFiles from ElasticSearch remove_indexed_files( model=HTMLFile, version=version, From 6135cde9547965de0d5719fb4f5226443b98ac7d Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 10 Jul 2019 15:07:48 +0530 Subject: [PATCH 44/59] fix logic in search.views --- readthedocs/search/views.py | 58 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/readthedocs/search/views.py b/readthedocs/search/views.py index 9183d733aee..25a11c699f3 100644 --- a/readthedocs/search/views.py +++ b/readthedocs/search/views.py @@ -107,36 +107,34 @@ def elastic_search(request, project_slug=None): if results: # sorting inner_hits (if present) - try: - for result in results: - - inner_hits = result.meta.inner_hits - sections = inner_hits.sections or [] - domains = inner_hits.domains or [] - all_results = itertools.chain(sections, domains) - - sorted_results = ( - { - 'type': hit._nested.field, - - # here _source term is not used because - # django gives error if the names of the - # variables start with underscore - 'source': hit._source.to_dict(), - - 'highlight': utils._remove_newlines_from_dict( - hit.highlight.to_dict() - ), - } - for hit in sorted(all_results, key=utils._get_hit_score, reverse=True) - ) - - result.meta.inner_hits = sorted_results - - except Exception as e: - # if the control comes in this block, - # that implies that there was a PageSearch - pass + if user_input.type == 'file': + + try: + for result in results: + inner_hits = result.meta.inner_hits + sections = inner_hits.sections or [] + domains = inner_hits.domains or [] + all_results = itertools.chain(sections, domains) + + sorted_results = ( + { + 'type': hit._nested.field, + + # here _source term is not used because + # django gives error if the names of the + # variables start with underscore + 'source': hit._source.to_dict(), + + 'highlight': utils._remove_newlines_from_dict( + hit.highlight.to_dict() + ), + } + for hit in sorted(all_results, key=utils._get_hit_score, reverse=True) + ) + + result.meta.inner_hits = sorted_results + except Exception: + log.exception('Error while sorting the results (inner_hits).') log.debug('Search results: %s', pformat(results.to_dict())) log.debug('Search facets: %s', pformat(results.facets.to_dict())) From d3566ac4a482aa431908fad5ed10f912d4515c68 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Wed, 10 Jul 2019 15:34:29 +0530 Subject: [PATCH 45/59] make 100 a constant --- readthedocs/core/static-src/core/js/doc-embed/search.js | 3 ++- readthedocs/core/static/core/js/readthedocs-doc-embed.js | 2 +- readthedocs/templates/search/elastic_search.html | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/readthedocs/core/static-src/core/js/doc-embed/search.js b/readthedocs/core/static-src/core/js/doc-embed/search.js index 0c61f51eb29..d3aab53d239 100644 --- a/readthedocs/core/static-src/core/js/doc-embed/search.js +++ b/readthedocs/core/static-src/core/js/doc-embed/search.js @@ -5,6 +5,7 @@ var rtddata = require('./rtd-data'); var xss = require('xss/lib/index'); var MAX_RESULT_PER_SECTION = 3; +var MAX_SUBSTRING_LIMIT = 100; /* @@ -97,7 +98,7 @@ function attach_elastic_search_query(data) { var section = inner_hits[j]; var section_subtitle = section._source.title; var section_subtitle_link = link + "#" + section._source.id; - var section_content = [section._source.content.substring(0, 100) + " ..."]; + var section_content = [section._source.content.substring(0, MAX_SUBSTRING_LIMIT) + " ..."]; if (section.highlight) { if (section.highlight["sections.title"]) { diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js index 9b17881ccce..b7e28d8629c 100644 --- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js +++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js @@ -1 +1 @@ -!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=R(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(S),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==O){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=[g._source.content.substring(0,100)+" ..."];if(g.highlight&&(g.highlight["sections.title"]&&(m=R(g.highlight["sections.title"][0])),g.highlight["sections.content"])){var b=g.highlight["sections.content"];w=[];for(var y=0;y<%= section_subtitle %>
    <% for (var i = 0; i < section_content.length; ++i) { %>
    <%= section_content[i] %>
    <% } %>',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var x,k=o[h],T=k._source.role_name,E=l+"#"+k._source.anchor,A=k._source.name;"string"==typeof k._source.display_name&&1<=k._source.display_name.length&&(T="("+k._source.role_name+") "+k._source.display_name),!k.highlight||k.highlight["domains.name"]&&(A=R(k.highlight["domains.name"][0])),x=k._source.type_display+" -- "+A+" -- in "+k._source.doc_display,f.append($u.template('<%= domain_content %>',{domain_subtitle_link:E,domain_subtitle:T,domain_content:x}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(S),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(S)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file +!function o(s,a,l){function d(t,e){if(!a[t]){if(!s[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return d(s[t][1][e]||e)},r,r.exports,o,s,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e
    "),i("table.docutils.footnote").wrap("
    "),i("table.docutils.citation").wrap("
    "),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=i(this);expand=i(''),expand.on("click",function(e){return n.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),i=t.find('[href="'+e+'"]');if(0===i.length){var n=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(i=t.find('[href="#'+n.attr("id")+'"]')).length&&(i=t.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav}),function(){for(var o=0,e=["ms","moz","webkit","o"],t=0;t/g,u=/"/g,p=/"/g,h=/&#([a-zA-Z0-9]*);?/gim,f=/:?/gim,g=/&newline;?/gim,m=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi,v=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,w=/u\s*r\s*l\s*\(.*/gi;function b(e){return e.replace(u,""")}function _(e){return e.replace(p,'"')}function y(e){return e.replace(h,function(e,t){return"x"===t[0]||"X"===t[0]?String.fromCharCode(parseInt(t.substr(1),16)):String.fromCharCode(parseInt(t,10))})}function x(e){return e.replace(f,":").replace(g," ")}function k(e){for(var t="",i=0,n=e.length;i/g;i.whiteList={a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","loop","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height"],ins:["datetime"],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],sup:[],strong:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","loop","preload","src","height","width"]},i.getDefaultWhiteList=o,i.onTag=function(e,t,i){},i.onIgnoreTag=function(e,t,i){},i.onTagAttr=function(e,t,i){},i.onIgnoreTagAttr=function(e,t,i){},i.safeAttrValue=function(e,t,i,n){if(i=T(i),"href"===t||"src"===t){if("#"===(i=c.trim(i)))return"#";if("http://"!==i.substr(0,7)&&"https://"!==i.substr(0,8)&&"mailto:"!==i.substr(0,7)&&"tel:"!==i.substr(0,4)&&"#"!==i[0]&&"/"!==i[0])return""}else if("background"===t){if(m.lastIndex=0,m.test(i))return""}else if("style"===t){if(v.lastIndex=0,v.test(i))return"";if(w.lastIndex=0,w.test(i)&&(m.lastIndex=0,m.test(i)))return"";!1!==n&&(i=(n=n||s).process(i))}return i=E(i)},i.escapeHtml=a,i.escapeQuote=b,i.unescapeQuote=_,i.escapeHtmlEntities=y,i.escapeDangerHtml5Entities=x,i.clearNonPrintableCharacter=k,i.friendlyAttrValue=T,i.escapeAttrValue=E,i.onIgnoreTagStripAll=function(){return""},i.StripTagBody=function(o,s){"function"!=typeof s&&(s=function(){});var a=!Array.isArray(o),l=[],d=!1;return{onIgnoreTag:function(e,t,i){if(function(e){return a||-1!==c.indexOf(o,e)}(e)){if(i.isClosing){var n="[/removed]",r=i.position+n.length;return l.push([!1!==d?d:i.position,r]),d=!1,n}return d||(d=i.position),"[removed]"}return s(e,t,i)},remove:function(t){var i="",n=0;return c.forEach(l,function(e){i+=t.slice(n,e[0]),n=e[1]}),i+=t.slice(n)}}},i.stripCommentTag=function(e){return e.replace(A,"")},i.stripBlankChar=function(e){var t=e.split("");return(t=t.filter(function(e){var t=e.charCodeAt(0);return!(127===t||t<=31&&10!==t&&13!==t)})).join("")},i.cssFilter=s,i.getDefaultCSSWhiteList=r},{"./util":5,cssfilter:10}],3:[function(e,t,i){var n=e("./default"),r=e("./parser"),o=e("./xss");for(var s in(i=t.exports=function(e,t){return new o(t).process(e)}).FilterXSS=o,n)i[s]=n[s];for(var s in r)i[s]=r[s];"undefined"!=typeof window&&(window.filterXSS=t.exports)},{"./default":2,"./parser":4,"./xss":6}],4:[function(e,t,i){var c=e("./util");function p(e){var t=c.spaceIndex(e);if(-1===t)var i=e.slice(1,-1);else i=e.slice(1,t+1);return"/"===(i=c.trim(i).toLowerCase()).slice(0,1)&&(i=i.slice(1)),"/"===i.slice(-1)&&(i=i.slice(0,-1)),i}var u=/[^a-zA-Z0-9_:\.\-]/gim;function h(e,t){for(;t"===u){n+=i(e.slice(r,o)),c=p(d=e.slice(o,a+1)),n+=t(o,n.length,c,d,"";var a=function(e){var t=b.spaceIndex(e);if(-1===t)return{html:"",closing:"/"===e[e.length-2]};var i="/"===(e=b.trim(e.slice(t+1,-1)))[e.length-1];return i&&(e=b.trim(e.slice(0,-1))),{html:e,closing:i}}(i),l=c[r],d=w(a.html,function(e,t){var i,n=-1!==b.indexOf(l,e);return _(i=h(r,e,t,n))?n?(t=g(r,e,t,v))?e+'="'+t+'"':e:_(i=f(r,e,t,n))?void 0:i:i});i="<"+r;return d&&(i+=" "+d),a.closing&&(i+=" /"),i+=">"}return _(o=p(r,i,s))?m(i):o},m);return i&&(n=i.remove(n)),n},t.exports=a},{"./default":2,"./parser":4,"./util":5,cssfilter:10}],7:[function(e,t,i){var n,r;n=this,r=function(){var T=!0;function s(i){function e(e){var t=i.match(e);return t&&1t[1][i])return 1;if(t[0][i]!==t[1][i])return-1;if(0===i)return 0}}function o(e,t,i){var n=a;"string"==typeof t&&(i=t,t=void 0),void 0===t&&(t=!1),i&&(n=s(i));var r=""+n.version;for(var o in e)if(e.hasOwnProperty(o)&&n[o]){if("string"!=typeof e[o])throw new Error("Browser version in the minVersion map should be a string: "+o+": "+String(e));return E([r,e[o]])<0}return t}return a.test=function(e){for(var t=0;t'),a=n.title;!r||r.title&&(a=R(r.title[0]));var l=n.link+DOCUMENTATION_OPTIONS.FILE_SUFFIX,d=l+"?highlight="+$.urlencode(S),c=$("",{href:d});if(c.html(a),c.find("em").addClass("highlighted"),s.append(c),n.project!==O){var u=" (from project "+n.project+")",p=$("",{text:u});s.append(p)}for(var h=0;h');if("sections"===o[h].type){var g=o[h],m=g._source.title,v=l+"#"+g._source.id,w=[g._source.content.substring(0,I)+" ..."];if(g.highlight&&(g.highlight["sections.title"]&&(m=R(g.highlight["sections.title"][0])),g.highlight["sections.content"])){var b=g.highlight["sections.content"];w=[];for(var y=0;y<%= section_subtitle %>
    <% for (var i = 0; i < section_content.length; ++i) { %>
    <%= section_content[i] %>
    <% } %>',{section_subtitle_link:v,section_subtitle:m,section_content:w}))}if("domains"===o[h].type){var x,k=o[h],T=k._source.role_name,E=l+"#"+k._source.anchor,A=k._source.name;"string"==typeof k._source.display_name&&1<=k._source.display_name.length&&(T="("+k._source.role_name+") "+k._source.display_name),!k.highlight||k.highlight["domains.name"]&&(A=R(k.highlight["domains.name"][0])),x=k._source.type_display+" -- "+A+" -- in "+k._source.doc_display,f.append($u.template('<%= domain_content %>',{domain_subtitle_link:E,domain_subtitle:T,domain_content:x}))}f.find("em").addClass("highlighted"),s.append(f),s.append($("
    "))}Search.output.append(s),s.slideDown(5)}t.length?Search.status.text(_("Search finished, found %s page(s) matching the search query.").replace("%s",t.length)):(Search.query_fallback(S),console.log("Read the Docs search failed. Falling back to Sphinx search."))}).fail(function(e){Search.query_fallback(S)}).always(function(){$("#search-progress").empty(),Search.stopPulse(),Search.title.text(_("Search Results")),Search.status.fadeIn(500)}),$.ajax({url:e.href,crossDomain:!0,xhrFields:{withCredentials:!0},complete:function(e,t){return"success"!==t||void 0===e.responseJSON||0===e.responseJSON.count?n.reject():n.resolve(e.responseJSON)}}).fail(function(e,t,i){return n.reject()})}}$(document).ready(function(){"undefined"!=typeof Search&&Search.init()})}(n.get())}}},{"./../../../../../../bower_components/xss/lib/index":3,"./rtd-data":16}],18:[function(r,e,t){var o=r("./rtd-data");e.exports={init:function(){var e=o.get();if($(document).on("click","[data-toggle='rst-current-version']",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e])}),void 0===window.SphinxRtdTheme){var t=r("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav;if($(document).ready(function(){setTimeout(function(){t.navBar||t.enable()},1e3)}),e.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length){console.log("Applying theme sidebar fix...");var i=$("nav.wy-nav-side:first"),n=$("
    ").addClass("wy-side-scroll");i.children().detach().appendTo(n),n.prependTo(i),t.navBar=n}}}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":16}],19:[function(e,t,i){var l,d=e("./constants"),c=e("./rtd-data"),n=e("bowser"),u="#ethical-ad-placement";function p(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.LEFTNAV,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_mkdocs_builder()&&l.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):l.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):l.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top>$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function h(){var e,t,i="rtd-"+(Math.random()+1).toString(36).substring(4),n=d.PROMO_TYPES.FOOTER,r=d.DEFAULT_PROMO_PRIORITY,o=null;return l.is_rtd_like_theme()?(o=$("
    ").insertAfter("footer hr"),e="ethical-rtd"):l.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster"),o?($("
    ").attr("id",i).addClass(e).appendTo(o),(!(t=$("#"+i).offset())||t.top<$(window).height())&&(r=d.LOW_PROMO_PRIORITY),{div_id:i,display_type:n,priority:r}):null}function f(){var e="rtd-"+(Math.random()+1).toString(36).substring(4),t=d.PROMO_TYPES.FIXED_FOOTER,i=d.DEFAULT_PROMO_PRIORITY;return n&&n.mobile&&(i=d.MAXIMUM_PROMO_PRIORITY),$("
    ").attr("id",e).appendTo("body"),{div_id:e,display_type:t,priority:i}}function g(e){this.id=e.id,this.div_id=e.div_id||"",this.html=e.html||"",this.display_type=e.display_type||"",this.view_tracking_url=e.view_url,this.click_handler=function(){"undefined"!=typeof ga?ga("rtfd.send","event","Promo","Click",e.id):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Promo","Click",e.id])}}g.prototype.display=function(){var e="#"+this.div_id,t=this.view_tracking_url;$(e).html(this.html),$(e).find('a[href*="/sustainability/click/"]').on("click",this.click_handler);function i(){$.inViewport($(e),-3)&&($("").attr("src",t).css("display","none").appendTo(e),$(window).off(".rtdinview"),$(".wy-side-scroll").off(".rtdinview"))}$(window).on("DOMContentLoaded.rtdinview load.rtdinview scroll.rtdinview resize.rtdinview",i),$(".wy-side-scroll").on("scroll.rtdinview",i),$(".ethical-close").on("click",function(){return $(e).hide(),!1}),this.post_promo_display()},g.prototype.disable=function(){$("#"+this.div_id).hide()},g.prototype.post_promo_display=function(){this.display_type===d.PROMO_TYPES.FOOTER&&($("
    ").insertAfter("#"+this.div_id),$("
    ").insertBefore("#"+this.div_id+".ethical-alabaster .ethical-footer"))},t.exports={Promo:g,init:function(){var e,t,i={format:"jsonp"},n=[],r=[],o=[],s=[h,p,f];if(l=c.get(),t=function(){var e,t="rtd-"+(Math.random()+1).toString(36).substring(4),i=d.PROMO_TYPES.LEFTNAV;return e=l.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster",0<$(u).length?($("
    ").attr("id",t).addClass(e).appendTo(u),{div_id:t,display_type:i}):null}())n.push(t.div_id),r.push(t.display_type),o.push(t.priority||d.DEFAULT_PROMO_PRIORITY);else{if(!l.show_promo())return;for(var a=0;a").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}()&&(console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------"),function(){var e=p(),t=null;e&&e.div_id&&(t=$("#"+e.div_id).attr("class","keep-us-sustainable"),$("

    ").text("Support Read the Docs!").appendTo(t),$("

    ").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(t),$("

    ").text("Thank you! ❤️").appendTo(t))}())}})}}},{"./constants":14,"./rtd-data":16,bowser:7}],20:[function(e,t,i){var o=e("./rtd-data");t.exports={init:function(e){var t=o.get();if(!e.is_highest){var i=window.location.pathname.replace(t.version,e.slug),n=$('

    Note

    You are not reading the most recent version of this documentation. is the latest version available.

    ');n.find("a").attr("href",i).text(e.slug);var r=$("div.body");r.length||(r=$("div.document")),r.prepend(n)}}}},{"./rtd-data":16}],21:[function(e,t,i){var n=e("./doc-embed/sponsorship"),r=e("./doc-embed/footer.js"),o=(e("./doc-embed/rtd-data"),e("./doc-embed/sphinx")),s=e("./doc-embed/search");$.extend(e("verge")),$(document).ready(function(){r.init(),o.init(),s.init(),n.init()})},{"./doc-embed/footer.js":15,"./doc-embed/rtd-data":16,"./doc-embed/search":17,"./doc-embed/sphinx":18,"./doc-embed/sponsorship":19,verge:13}]},{},[21]); \ No newline at end of file diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index f07cb201656..8fea5f5ef79 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -25,6 +25,8 @@ {% block content %} +{% trans "100" as MAX_SUBSTRING_LIMIT %} + +{% endwith %} {% endblock %} From b7ce777b544da4ac333c649b89c4ba59399061e7 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 12 Jul 2019 14:26:55 +0530 Subject: [PATCH 55/59] fix lint --- readthedocs/search/parse_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readthedocs/search/parse_json.py b/readthedocs/search/parse_json.py index a371f91477c..92c39222bf1 100644 --- a/readthedocs/search/parse_json.py +++ b/readthedocs/search/parse_json.py @@ -92,7 +92,7 @@ def process_file(fjson_filename): def parse_content(content): """ - Removes the starting text and ¶ + Removes the starting text and ¶. It removes the starting text from the content because it contains the the title of that content, From 6701a4ee525813aee779edbee1f26aee5dcf8bea Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 12 Jul 2019 17:25:09 +0530 Subject: [PATCH 56/59] add test for domains and filter by version and project --- .../doc_builder/python_environments.py | 3 +- readthedocs/search/faceted_search.py | 2 +- readthedocs/search/tests/conftest.py | 35 +++++- .../search/tests/data/docs/support.json | 20 +++ .../search/tests/data/docs/wiping.json | 38 ++++++ .../search/tests/data/kuma/docker.json | 20 +++ .../search/tests/data/kuma/documentation.json | 20 +++ .../tests/data/pipeline/installation.json | 11 ++ .../search/tests/data/pipeline/signals.json | 20 +++ readthedocs/search/tests/test_api.py | 117 ++++++++++++------ readthedocs/search/tests/utils.py | 33 ++++- 11 files changed, 276 insertions(+), 43 deletions(-) diff --git a/readthedocs/doc_builder/python_environments.py b/readthedocs/doc_builder/python_environments.py index 8306a1e57b0..c07d69b3523 100644 --- a/readthedocs/doc_builder/python_environments.py +++ b/readthedocs/doc_builder/python_environments.py @@ -325,7 +325,8 @@ def install_core_requirements(self): negative='sphinx<2', ), 'sphinx-rtd-theme<0.5', - 'readthedocs-sphinx-ext<0.7', + # 'readthedocs-sphinx-ext<0.7', + 'git+https://github.com/readthedocs/readthedocs-sphinx-ext@master', ]) cmd = copy.copy(pip_install_cmd) diff --git a/readthedocs/search/faceted_search.py b/readthedocs/search/faceted_search.py index 92067b6af57..c98f2a27961 100644 --- a/readthedocs/search/faceted_search.py +++ b/readthedocs/search/faceted_search.py @@ -105,7 +105,7 @@ class PageSearchBase(RTDFacetedSearch): _section_fields = ['sections.title^3', 'sections.content'] _domain_fields = [ 'domains.type_display', - 'domains.name', + 'domains.name^2', 'domains.display_name', ] fields = _outer_fields diff --git a/readthedocs/search/tests/conftest.py b/readthedocs/search/tests/conftest.py index 8fa30478501..5f29c596235 100644 --- a/readthedocs/search/tests/conftest.py +++ b/readthedocs/search/tests/conftest.py @@ -8,6 +8,8 @@ from readthedocs.projects.models import Project, HTMLFile from readthedocs.search.documents import PageDocument +from readthedocs.sphinx_domains.models import SphinxDomain + from .dummy_data import ALL_PROJECTS, PROJECT_DATA_FILES @@ -32,6 +34,28 @@ def all_projects(es_index, mock_processed_json, db, settings): file_name = file_basename + '.html' version = project.versions.all()[0] html_file = G(HTMLFile, project=project, version=version, name=file_name) + + # creating sphinx domain test objects + file_path = get_json_file_path(project.slug, file_basename) + if os.path.exists(file_path): + with open (file_path) as f: + data = json.load(f) + domains = data['domains'] + + for domain_data in domains: + domain_role_name = domain_data.pop('role_name') + domain, type_ = domain_role_name.split(':') + + G( + SphinxDomain, + project=project, + version=version, + html_file=html_file, + domain=domain, + type=type_, + **domain_data + ) + PageDocument().update(html_file) projects_list.append(project) @@ -46,12 +70,17 @@ def project(all_projects): return all_projects[0] +def get_json_file_path(project_slug, basename): + current_path = os.path.abspath(os.path.dirname(__file__)) + file_name = f'{basename}.json' + file_path = os.path.join(current_path, 'data', project_slug, file_name) + return file_path + + def get_dummy_processed_json(instance): project_slug = instance.project.slug basename = os.path.splitext(instance.name)[0] - file_name = basename + '.json' - current_path = os.path.abspath(os.path.dirname(__file__)) - file_path = os.path.join(current_path, "data", project_slug, file_name) + file_path = get_json_file_path(project_slug, basename) if os.path.exists(file_path): with open(file_path) as f: diff --git a/readthedocs/search/tests/data/docs/support.json b/readthedocs/search/tests/data/docs/support.json index 7ce870e4fc7..86e641bfe65 100644 --- a/readthedocs/search/tests/data/docs/support.json +++ b/readthedocs/search/tests/data/docs/support.json @@ -17,5 +17,25 @@ "title": "Commercial Support", "content": "We offer commercial support for Read the Docs, commercial hosting, as well as consulting around all documentation systems. You can contact us at hello@readthedocs.com to learn more, or read more at https://readthedocs.com/services/#open-source-support." } + ], + "domains": [ + { + "role_name": "http:post", + "doc_name": "api/v3.html", + "anchor": "post--api-v3-projects-(string-project_slug)-versions-(string-version_slug)-builds-", + "type_display": "post", + "doc_display": "API v3", + "name": "/api/v3/projects/(string:project_slug)/versions/(string:version_slug)/builds/", + "display_name": "" + }, + { + "role_name": "http:patch", + "doc_name": "api/v3.html", + "anchor": "patch--api-v3-projects-(string-project_slug)-version-(string-version_slug)-", + "type_display": "patch", + "doc_display": "API v3", + "name": "/api/v3/projects/(string:project_slug)/version/(string:version_slug)/", + "display_name": "" + } ] } diff --git a/readthedocs/search/tests/data/docs/wiping.json b/readthedocs/search/tests/data/docs/wiping.json index e553d36c27d..fc5537131ff 100644 --- a/readthedocs/search/tests/data/docs/wiping.json +++ b/readthedocs/search/tests/data/docs/wiping.json @@ -7,5 +7,43 @@ "title": "Wiping a Build Environment", "content": "Sometimes it happen that your Builds start failing because the build environment where the documentation is created is stale or broken. This could happen for a couple of different reasons like pip not upgrading a package properly or a corrupted cached Python package.In any of these cases (and many others), the solution could be just wiping out the existing build environment files and allow Read the Docs to create a new fresh one.Follow these steps to wipe the build environment:Click on the Edit button of the version you want to wipe on the right side of the page. Go to the bottom of the page and click the wipe link, next to the “Save” buttonBy wiping the documentation build environment, all the rst, md, and code files associated with it will be removed but not the documentation already built (HTML and PDF files). Your documentation will still online after wiping the build environment.Now you can re-build the version with a fresh build environment!" } + ], + "domains": [ + { + "role_name": "http:get", + "doc_name": "api/v3.html", + "anchor": "get--api-v3-users-(str-username)", + "type_display": "get", + "doc_display": "API v3", + "name": "/api/v3/users/(str:username)", + "display_name": "" + }, + { + "role_name": "http:get", + "doc_name": "api/v3.html", + "anchor": "get--api-v3-projects-(string-project_slug)-versions-(string-version_slug)-", + "type_display": "get", + "doc_display": "API v3", + "name": "/api/v3/projects/(string:project_slug)/versions/(string:version_slug)/", + "display_name": "" + }, + { + "role_name": "http:get", + "doc_name": "api/v3.html", + "anchor": "get--api-v3-projects-(string-project_slug)-versions-", + "type_display": "get", + "doc_display": "API v3", + "name": "/api/v3/projects/(string:project_slug)/versions/", + "display_name": "" + }, + { + "role_name": "http:get", + "doc_name": "api/v3.html", + "anchor": "get--api-v3-projects-(string-project_slug)-", + "type_display": "get", + "doc_display": "API v3", + "name": "/api/v3/projects/(string:project_slug)/", + "display_name": "" + } ] } diff --git a/readthedocs/search/tests/data/kuma/docker.json b/readthedocs/search/tests/data/kuma/docker.json index 61040b69c27..cde17951efd 100644 --- a/readthedocs/search/tests/data/kuma/docker.json +++ b/readthedocs/search/tests/data/kuma/docker.json @@ -12,5 +12,25 @@ "title": "Docker Images", "content": "Docker images are used in development, usually with the local working files mounted in the images to set behaviour.. Images are built by Jenkins, after tests pass, and are published to DockerHub. We try to store the configuration in the environment, so that the published images can be used in deployments by setting environment variables to deployment-specific values.. Here are some of the images used in the Kuma project:. kuma. The kuma Docker image builds on the kuma_base image, installing a kuma branch and building the assets needed for running as a webservice. The environment can be customized for different deployments.. The image can be recreated locally with make build-kuma.. The image tagged latest is used by default for development. It can be created locally with make build-kuma VERSION=latest. The official latest image is created from the master branch in Jenkins and published to DockerHub.. kuma_base. The kuma_base Docker image contains the OS and libraries (C, Python, and Node.js) that support the kuma project. The kuma image extends this by installing the kuma source and building assets needed for production.. The image can be recreated locally with make build-base.. The image tagged latest is used by default for development. It can be created localled with make build-base VERSION=latest. The official latest image is created from the master branch in Jenkins and published to DockerHub. kumascript. The kumascript Docker image contains the kumascript rendering engine and support files. The environment can be customized for different deployments.. The image can be recreated locally with make build-kumascript.. The image tagged latest is used by default for development. It can be created locally with make build-kumascript KS_VERSION=latest. The official latest image is created from the master branch in Jenkins and published to DockerHub.. integration-tests. The integration-tests Docker image contains browser-based integration tests that check the functionality of a running Kuma deployment.. The image can be recreated locally with docker build -f docker/images/integration-tests/ ., but this is only necessary for image development. Most developers will follow the Client-side testing documentation to develop and run these integration tests.. The image is built and used in Jenkins in the stage-integration-tests and prod-integration-tests pipelines, configured by scripts in the Jenkinsfiles folder. It is not published to DockerHub." } + ], + "domains": [ + { + "role_name": "py:module", + "doc_name": "autoapi/notfound/utils/index.html", + "anchor": "module-notfound.utils", + "type_display": "module", + "doc_display": "notfound.utils", + "name": "notfound.utils", + "display_name": "" + }, + { + "role_name": "py:function", + "doc_name": "autoapi/notfound/utils/index.html", + "anchor": "notfound.utils.replace_uris", + "type_display": "function", + "doc_display": "notfound.utils", + "name": "notfound.utils.replace_uris", + "display_name": "" + } ] } diff --git a/readthedocs/search/tests/data/kuma/documentation.json b/readthedocs/search/tests/data/kuma/documentation.json index 285885bee7a..bced181ff22 100644 --- a/readthedocs/search/tests/data/kuma/documentation.json +++ b/readthedocs/search/tests/data/kuma/documentation.json @@ -12,5 +12,25 @@ "title": "Generating documentation", "content": "Sphinx uses a Makefile in the docs subfolder to build documentation in several formats. MDN only uses the HTML format, and the generated document index is at docs/_build/html/index.html.. To generate the documentation in a virtualenv on the host machine, first install the requirements:. pip install -r requirements/docs.txt. Then switch to the docs folder to use the Makefile:. cd docs make html python -m webbrowser file://${PWD}/_build/html/index.html. To generate the documentation with Docker:. docker-compose run --rm --user $(id -u) web sh -c \"\\ virtualenv /tmp/.venvs/docs && \\ . /tmp/.venvs/docs/bin/activate && \\ pip install -r /app/requirements/docs.txt && \\ cd /app/docs && \\ make html\" python -m webbrowser file://${PWD}/docs/_build/html/index.html. A virtualenv is required, to avoid a pip bug when changing the version of a system-installed package." } + ], + "domains": [ + { + "role_name": "py:module", + "doc_name": "autoapi/notfound/index.html", + "anchor": "module-notfound", + "type_display": "module", + "doc_display": "notfound", + "name": "notfound", + "display_name": "" + }, + { + "role_name": "py:data", + "doc_name": "autoapi/notfound/index.html", + "anchor": "notfound.version", + "type_display": "data", + "doc_display": "notfound", + "name": "notfound.version", + "display_name": "" + } ] } diff --git a/readthedocs/search/tests/data/pipeline/installation.json b/readthedocs/search/tests/data/pipeline/installation.json index afc3f33c63b..eed6a351b3c 100644 --- a/readthedocs/search/tests/data/pipeline/installation.json +++ b/readthedocs/search/tests/data/pipeline/installation.json @@ -22,5 +22,16 @@ "title": "Recommendations", "content": "Pipeline’s default CSS and JS compressor is Yuglify. Yuglify wraps UglifyJS and cssmin, applying the default YUI configurations to them. It can be downloaded from: https://github.com/yui/yuglify/.. If you do not install yuglify, make sure to disable the compressor in your settings." } + ], + "domains": [ + { + "role_name": "std:confval", + "doc_name": "configuration.html", + "anchor": "confval-notfound_default_language", + "type_display": "confval", + "doc_display": "Configuration", + "name": "notfound_default_language", + "display_name": "" + } ] } diff --git a/readthedocs/search/tests/data/pipeline/signals.json b/readthedocs/search/tests/data/pipeline/signals.json index 511e51a6d07..97b1095d29f 100644 --- a/readthedocs/search/tests/data/pipeline/signals.json +++ b/readthedocs/search/tests/data/pipeline/signals.json @@ -17,5 +17,25 @@ "title": "js_compressed", "content": "pipeline.signals.js_compressed. Whenever a js package is compressed, this signal is sent after the compression.. Arguments sent with this signal :. sender:. The Packager class that compressed the group.. package:. The package actually compressed." } + ], + "domains": [ + { + "role_name": "py:method", + "doc_name": "autoapi/notfound/extension/index.html", + "anchor": "notfound.extension.OrphanMetadataCollector.process_doc", + "type_display": "method", + "doc_display": "notfound.extension", + "name": "notfound.extension.OrphanMetadataCollector.process_doc", + "display_name": "" + }, + { + "role_name": "py:method", + "doc_name": "autoapi/notfound/extension/index.html", + "anchor": "notfound.extension.OrphanMetadataCollector.clear_doc", + "type_display": "method", + "doc_display": "notfound.extension", + "name": "notfound.extension.OrphanMetadataCollector.clear_doc", + "display_name": "" + } ] } diff --git a/readthedocs/search/tests/test_api.py b/readthedocs/search/tests/test_api.py index 49598cfd30d..aa25aff4182 100644 --- a/readthedocs/search/tests/test_api.py +++ b/readthedocs/search/tests/test_api.py @@ -51,9 +51,28 @@ def test_search_works_with_title_query(self, api_client, project, page_num, data assert len(title_highlight) == 1 assert query.lower() in title_highlight[0].lower() - @pytest.mark.parametrize('data_type', ['sections.title', 'sections.content']) - @pytest.mark.parametrize('page_num', [1, 0]) - def test_search_works_with_sections_query(self, api_client, project, page_num, data_type): + @pytest.mark.parametrize( + 'data_type', + [ + # page sections fields + 'sections.title', + 'sections.content', + + # domain fields + 'domains.type_display', + 'domains.name', + + # TODO: Add test for "domains.display_name" + ] + ) + @pytest.mark.parametrize('page_num', [0]) + def test_search_works_with_sections_and_domains_query( + self, + api_client, + project, + page_num, + data_type + ): query = get_search_query_from_project_file( project_slug=project.slug, page_num=page_num, @@ -73,67 +92,95 @@ def test_search_works_with_sections_query(self, api_client, project, page_num, d # Matching first result project_data = data[0] - inner_hits = list(project_data['inner_hits']) - assert project_data['project'] == project.slug + + inner_hits = list(project_data['inner_hits']) + # since there was a nested query, + # inner_hits should not be empty assert len(inner_hits) >= 1 inner_hit_0 = inner_hits[0] # first inner_hit - assert inner_hit_0['type'] == 'sections' + expected_type = data_type.split('.')[0] # can be "sections" or "domains" + assert inner_hit_0['type'] == expected_type highlight = inner_hit_0['highlight'][data_type] assert ( len(highlight) == 1 ), 'number_of_fragments is set to 1' - queries = query.split() + # checking highlighting of results + queries = query.split() # if query is more than one word + queries_len = len(queries) total_query_words_highlighted = 0 - for q in queries: - if f'{q.lower()}' in highlight[0].lower(): - total_query_words_highlighted += 1 - # it is not necessary to get all the words highlighted - assert ( - abs(total_query_words_highlighted - len(queries)) <= 1 - ) + for q in queries: + if f'{q.lower()}' in highlight[0].lower(): + total_query_words_highlighted += 1 + + if queries_len == 1: + # if the search was of one word, + # then the it must be highlighted + assert total_query_words_highlighted - queries_len <= 0 + else: + # if the search was of two words or more, + # then it is not necessary for every word + # to get highlighted + assert total_query_words_highlighted - queries_len <= 1 def test_doc_search_filter_by_project(self, api_client): """Test Doc search results are filtered according to project""" # `documentation` word is present both in `kuma` and `docs` files # and not in `pipeline`, so search with this phrase but filter through project - search_params = {'q': 'documentation', 'project': 'docs', 'version': 'latest'} + search_params = { + 'q': 'documentation', + 'project': 'docs', + 'version': 'latest' + } resp = api_client.get(self.url, search_params) assert resp.status_code == 200 data = resp.data['results'] assert len(data) == 2 # both pages of `docs` contains the word `documentation` + + # all results must be from same project for res in data: assert res['project'] == 'docs' - # def test_doc_search_filter_by_version(self, api_client, project): - # """Test Doc search result are filtered according to version""" - # query = get_search_query_from_project_file(project_slug=project.slug) - # latest_version = project.versions.all()[0] - # # Create another version - # dummy_version = G(Version, project=project, active=True) - # # Create HTMLFile same as the latest version - # latest_version_files = HTMLFile.objects.all().filter(version=latest_version) - # for f in latest_version_files: - # f.version = dummy_version - # # Make primary key to None, so django will create new object - # f.pk = None - # f.save() - # PageDocument().update(f) + def test_doc_search_filter_by_version(self, api_client, project): + """Test Doc search result are filtered according to version""" + query = get_search_query_from_project_file(project_slug=project.slug) + latest_version = project.versions.all()[0] + # Create another version + dummy_version = G(Version, project=project, active=True) + # Create HTMLFile same as the latest version + latest_version_files = HTMLFile.objects.all().filter(version=latest_version) + for f in latest_version_files: + f.version = dummy_version + # Make primary key to None, so django will create new object + f.pk = None + f.save() + PageDocument().update(f) - # search_params = {'q': query, 'project': project.slug, 'version': dummy_version.slug} - # resp = api_client.get(self.url, search_params) - # assert resp.status_code == 200 + search_params = { + 'q': query, + 'project': project.slug, + 'version': dummy_version.slug + } + resp = api_client.get(self.url, search_params) + assert resp.status_code == 200 - # data = resp.data['results'] - # assert len(data) == 1 - # assert data[0]['project'] == project.slug + data = resp.data['results'] + + # there may be more than one results + # for some query like `documentation` + # for project `kuma` + assert len(data) >= 1 + + # all results must be from same project + for res in data: + assert res['project'] == project.slug # def test_doc_search_pagination(self, api_client, project): # """Test Doc search result can be paginated""" diff --git a/readthedocs/search/tests/utils.py b/readthedocs/search/tests/utils.py index e75db924414..4a2c8d23c02 100644 --- a/readthedocs/search/tests/utils.py +++ b/readthedocs/search/tests/utils.py @@ -19,7 +19,7 @@ def get_search_query_from_project_file(project_slug, page_num=0, data_type='titl if data_type == 'title': - # use first word of page title as query + # uses first word of page title as query query = query_data.split()[0] elif data_type.startswith('sections'): @@ -33,7 +33,7 @@ def get_search_query_from_project_file(project_slug, page_num=0, data_type='titl query = ' '.join(query) # generates query from section content - if data_type.endswith('content'): + elif data_type.endswith('content'): query_data = query_data[0]['content'].split() start = random.randint(0, 6) @@ -44,5 +44,32 @@ def get_search_query_from_project_file(project_slug, page_num=0, data_type='titl query = query_data[start:end] query = ' '.join(query) - + + elif data_type.startswith('domains'): + + # uses first word of domains.type_display as query + if data_type.endswith('type_display'): + query = query_data[0]['type_display'].split()[0] + + # generates query from domains.name + if data_type.endswith('name'): + # test data contains domains.name + # some of which contains '.' and some '/' + # and others are plain words. + # Splitting with '.' and '/' is done + # to ensure that the query contains proper words + if '.' in query_data[0]['name']: + query_data = query_data[0]['name'].split('.') + start = 0 + end = random.randint(1, len(query_data)) + query = '.'.join(query_data[start:end]) + + elif '/' in query_data[0]['name']: + query_data = query_data[0]['name'].split('/') + start = 0 + end = random.randint(1, len(query_data)) + query = '/'.join(query_data[start:end]) + else: + query = query_data[0]['name'].split()[0] + return query From cee24ed59adada0cce6babcdfbfef6f00542fc96 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 12 Jul 2019 17:39:16 +0530 Subject: [PATCH 57/59] revert changes to python_environments.py --- readthedocs/doc_builder/python_environments.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/readthedocs/doc_builder/python_environments.py b/readthedocs/doc_builder/python_environments.py index c07d69b3523..8306a1e57b0 100644 --- a/readthedocs/doc_builder/python_environments.py +++ b/readthedocs/doc_builder/python_environments.py @@ -325,8 +325,7 @@ def install_core_requirements(self): negative='sphinx<2', ), 'sphinx-rtd-theme<0.5', - # 'readthedocs-sphinx-ext<0.7', - 'git+https://github.com/readthedocs/readthedocs-sphinx-ext@master', + 'readthedocs-sphinx-ext<0.7', ]) cmd = copy.copy(pip_install_cmd) From 685f6db64517e02eab00573147cf0d4abf090377 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 12 Jul 2019 20:43:40 +0530 Subject: [PATCH 58/59] remove tests from this pr --- .../tests/test_search_json_parsing.py | 11 +- readthedocs/search/tests/conftest.py | 35 +-- readthedocs/search/tests/data/docs/story.json | 31 ++ .../search/tests/data/docs/support.json | 41 --- .../search/tests/data/docs/wiping.json | 60 +--- .../search/tests/data/kuma/docker.json | 57 ++-- .../search/tests/data/kuma/documentation.json | 53 ++-- .../tests/data/pipeline/installation.json | 66 ++--- .../search/tests/data/pipeline/signals.json | 64 ++--- readthedocs/search/tests/dummy_data.py | 2 +- readthedocs/search/tests/test_api.py | 270 ++++++------------ readthedocs/search/tests/utils.py | 63 +--- 12 files changed, 237 insertions(+), 516 deletions(-) create mode 100644 readthedocs/search/tests/data/docs/story.json delete mode 100644 readthedocs/search/tests/data/docs/support.json diff --git a/readthedocs/rtd_tests/tests/test_search_json_parsing.py b/readthedocs/rtd_tests/tests/test_search_json_parsing.py index 550736ca16d..42b0839c4e9 100644 --- a/readthedocs/rtd_tests/tests/test_search_json_parsing.py +++ b/readthedocs/rtd_tests/tests/test_search_json_parsing.py @@ -17,12 +17,7 @@ def test_h2_parsing(self): 'files/api.fjson', ), ) - self.assertEqual(data['path'], 'api') self.assertEqual(data['sections'][1]['id'], 'a-basic-api-client-using-slumber') - self.assertTrue(data['sections'][1]['content'].startswith( - 'You can use Slumber' - )) - self.assertEqual(data['title'], 'Read the Docs Public API') - - for section in data['sections']: - self.assertFalse('\n' in section['content']) + # Only capture h2's after the first section + for obj in data['sections'][1:]: + self.assertEqual(obj['content'][:5], '\n

    ') diff --git a/readthedocs/search/tests/conftest.py b/readthedocs/search/tests/conftest.py index 5f29c596235..8fa30478501 100644 --- a/readthedocs/search/tests/conftest.py +++ b/readthedocs/search/tests/conftest.py @@ -8,8 +8,6 @@ from readthedocs.projects.models import Project, HTMLFile from readthedocs.search.documents import PageDocument -from readthedocs.sphinx_domains.models import SphinxDomain - from .dummy_data import ALL_PROJECTS, PROJECT_DATA_FILES @@ -34,28 +32,6 @@ def all_projects(es_index, mock_processed_json, db, settings): file_name = file_basename + '.html' version = project.versions.all()[0] html_file = G(HTMLFile, project=project, version=version, name=file_name) - - # creating sphinx domain test objects - file_path = get_json_file_path(project.slug, file_basename) - if os.path.exists(file_path): - with open (file_path) as f: - data = json.load(f) - domains = data['domains'] - - for domain_data in domains: - domain_role_name = domain_data.pop('role_name') - domain, type_ = domain_role_name.split(':') - - G( - SphinxDomain, - project=project, - version=version, - html_file=html_file, - domain=domain, - type=type_, - **domain_data - ) - PageDocument().update(html_file) projects_list.append(project) @@ -70,17 +46,12 @@ def project(all_projects): return all_projects[0] -def get_json_file_path(project_slug, basename): - current_path = os.path.abspath(os.path.dirname(__file__)) - file_name = f'{basename}.json' - file_path = os.path.join(current_path, 'data', project_slug, file_name) - return file_path - - def get_dummy_processed_json(instance): project_slug = instance.project.slug basename = os.path.splitext(instance.name)[0] - file_path = get_json_file_path(project_slug, basename) + file_name = basename + '.json' + current_path = os.path.abspath(os.path.dirname(__file__)) + file_path = os.path.join(current_path, "data", project_slug, file_name) if os.path.exists(file_path): with open(file_path) as f: diff --git a/readthedocs/search/tests/data/docs/story.json b/readthedocs/search/tests/data/docs/story.json new file mode 100644 index 00000000000..2c998bcec3b --- /dev/null +++ b/readthedocs/search/tests/data/docs/story.json @@ -0,0 +1,31 @@ +{ + "content": "ReadtheDocsPhilosophy\nRead the Docs is Open Source software. We have licensed the code base as MIT, which provides almost no restrictions on the use of the code.\nHowever, as a project there are things that we care about more than others. We built Read the Docs to support in the Open Source community. The code is open for people to contribute to, so that they may build features into https://readthedocs.org that they want.

    XSS exploit

    We also believe sharing the code openly is a valuable learning tool, especially for demonsrating how to collaborate and maintain an enormous website.\nOfficial website Support\nThe time of the core developers of Read the Docs is limited. We provide official developers support for the following things:\nLocal development on the Python code base\nUsage of https://readthedocs.org for Open Source projects\nBug fixes in the code base, as it applies to running it on https://readthedocs.org\nUnsupported\nThere are use cases that we don\u2019t support, because it doesn\u2019t further our goal of promoting in the Open Source Community.\nWe do not support:\nSpecific usage of Sphinx and Mkdocs, that don\u2019t affect our hosting\nCustom s of Read the Docs at your company\n of Read the Docs on other platforms\nAny issues outside of the Read the Docs Python Code\nRationale\nRead the Docs was founded to improve in the Open Source Community. We fully recognize and allow the code to be used for internal installs at companies, but we will not spend our time supporting it. Our time is limited, and we want to spend it on the mission that we set out to originally support.\nIf you feel strongly about installing Read the Docs internal to a company, we will happily link to third party resources on this topic. Please open an issue with a proposal if you want to take on this task.", + "headers": [ + "Unsupported", + "Rationale" + ], + "title": "Philosophy", + "sections": [ + { + "content": "\nRead the Docs is Open Source software.\nWe have licensed the code base as MIT,\nwhich provides almost no restrictions on the use of the code.\n\nHowever,\nas a project there are things that we care about more than others.\nWe built Read the Docs to support in the Open Source community.\nThe code is open for people to contribute to,\nso that they may build features into https://readthedocs.org that they want.\nWe also believe sharing the code openly is a valuable learning tool,\nespecially for demonsrating how to collaborate and maintain an enormous website.\n", + "id": "read-the-docs-open-source-philosophy", + "title": "Read the Docs Open Source Philosophy" + }, + { + "content": "\n

    Official Support\u00b6

    \n

    The time of the core developers of Read the Docs is limited.\nWe provide official support for the following things:

    \n\n", + "id": "official-support", + "title": "Official Support" + }, + { + "content": "\n

    Unsupported\u00b6

    \n

    There are use cases that we don\u2019t support,\nbecause it doesn\u2019t further our goal of promoting in the Open Source Community.

    \n

    We do not support:

    \n
      \n
    • Specific usage of Sphinx and Mkdocs, that don\u2019t affect our hosting
    • \n
    • Custom of Read the Docs at your company
    • \n
    • of Read the Docs on other platforms
    • \n
    • Any issues outside of the Read the Docs Python Code
    • \n
    \n", + "id": "unsupported", + "title": "Unsupported" + }, + { + "content": "\n

    Rationale\u00b6

    \n

    Read the Docs was founded to improve in the Open Source Community.\nWe fully recognize and allow the code to be used for internal installs at companies,\nbut we will not spend our time supporting it.\nOur time is limited,\nand we want to spend it on the mission that we set out to originally support.

    \n

    If you feel strongly about installing Read the Docs internal to a company,\nwe will happily link to third party resources on this topic.\nPlease open an issue with a proposal if you want to take on this task.

    \n", + "id": "rationale", + "title": "Rationale" + } + ], + "path": "open-source-philosophy" +} diff --git a/readthedocs/search/tests/data/docs/support.json b/readthedocs/search/tests/data/docs/support.json deleted file mode 100644 index 86e641bfe65..00000000000 --- a/readthedocs/search/tests/data/docs/support.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "path": "support", - "title": "Support", - "sections": [ - { - "id": "usage-questions", - "title": "Usage Questions", - "content": "If you have questions about how to use Read the Docs, or have an issue that isn’t related to a bug, Stack Overflow is the best place to ask. Tag questions with read-the-docs so other folks can find them easily.. Good questions for Stack Overflow would be:. “What is the best way to structure the table of contents across a project?”. “How do I structure translations inside of my project for easiest contribution from users?”. “How do I use Sphinx to use SVG images in HTML output but PNG in PDF output?”" - }, - { - "id": "community-support", - "title": "Community Support", - "content": "Read the Docs is supported by community contributions and advertising. We hope to bring in enough money with our Gold and Ethical Ads programs to keep Read the Docs sustainable.. All people answering your questions are doing it with their own time, so please be kind and provide as much information as possible.. Bugs & Support Issues. You can file bug reports on our GitHub issue tracker, and they will be addressed as soon as possible. Support is a volunteer effort, and there is no guaranteed response time. If you need answers quickly, you can buy commercial support below.. Reporting Issues. When reporting a bug, please include as much information as possible that will help us solve this issue. This includes:. Project name. URL. Action taken. Expected result. Actual result. Specific Requests. If you need a specific request for your project or account, like more resources, change of the project’s slug or username. Send an email to support@readthedocs.org." - }, - { - "id": "commercial-support", - "title": "Commercial Support", - "content": "We offer commercial support for Read the Docs, commercial hosting, as well as consulting around all documentation systems. You can contact us at hello@readthedocs.com to learn more, or read more at https://readthedocs.com/services/#open-source-support." - } - ], - "domains": [ - { - "role_name": "http:post", - "doc_name": "api/v3.html", - "anchor": "post--api-v3-projects-(string-project_slug)-versions-(string-version_slug)-builds-", - "type_display": "post", - "doc_display": "API v3", - "name": "/api/v3/projects/(string:project_slug)/versions/(string:version_slug)/builds/", - "display_name": "" - }, - { - "role_name": "http:patch", - "doc_name": "api/v3.html", - "anchor": "patch--api-v3-projects-(string-project_slug)-version-(string-version_slug)-", - "type_display": "patch", - "doc_display": "API v3", - "name": "/api/v3/projects/(string:project_slug)/version/(string:version_slug)/", - "display_name": "" - } - ] -} diff --git a/readthedocs/search/tests/data/docs/wiping.json b/readthedocs/search/tests/data/docs/wiping.json index fc5537131ff..50b3ee1658e 100644 --- a/readthedocs/search/tests/data/docs/wiping.json +++ b/readthedocs/search/tests/data/docs/wiping.json @@ -1,49 +1,15 @@ { - "path": "guides/wipe-environment", - "title": "Wiping a Build Environment", - "sections": [ - { - "id": "wiping-a-build-environment", - "title": "Wiping a Build Environment", - "content": "Sometimes it happen that your Builds start failing because the build environment where the documentation is created is stale or broken. This could happen for a couple of different reasons like pip not upgrading a package properly or a corrupted cached Python package.In any of these cases (and many others), the solution could be just wiping out the existing build environment files and allow Read the Docs to create a new fresh one.Follow these steps to wipe the build environment:Click on the Edit button of the version you want to wipe on the right side of the page. Go to the bottom of the page and click the wipe link, next to the “Save” buttonBy wiping the documentation build environment, all the rst, md, and code files associated with it will be removed but not the documentation already built (HTML and PDF files). Your documentation will still online after wiping the build environment.Now you can re-build the version with a fresh build environment!" - } - ], - "domains": [ - { - "role_name": "http:get", - "doc_name": "api/v3.html", - "anchor": "get--api-v3-users-(str-username)", - "type_display": "get", - "doc_display": "API v3", - "name": "/api/v3/users/(str:username)", - "display_name": "" - }, - { - "role_name": "http:get", - "doc_name": "api/v3.html", - "anchor": "get--api-v3-projects-(string-project_slug)-versions-(string-version_slug)-", - "type_display": "get", - "doc_display": "API v3", - "name": "/api/v3/projects/(string:project_slug)/versions/(string:version_slug)/", - "display_name": "" - }, - { - "role_name": "http:get", - "doc_name": "api/v3.html", - "anchor": "get--api-v3-projects-(string-project_slug)-versions-", - "type_display": "get", - "doc_display": "API v3", - "name": "/api/v3/projects/(string:project_slug)/versions/", - "display_name": "" - }, - { - "role_name": "http:get", - "doc_name": "api/v3.html", - "anchor": "get--api-v3-projects-(string-project_slug)-", - "type_display": "get", - "doc_display": "API v3", - "name": "/api/v3/projects/(string:project_slug)/", - "display_name": "" - } - ] + "content": "ReadtheDocsWiping a Build Environment\nSometimes it happen that your Builds start failing because the build environment where the is created is stale or broken. This could happen for a couple of different reasons like pip not upgrading a package properly or a corrupted cached Python package.\nIn any of these cases (and many others), the solution could be just wiping out the existing build environment files and allow Read the Docs to create a new fresh one.\nFollow these steps to wipe the build environment:\nGo to Versions\nClick on the Edit button of the version you want to wipe on the right side of the page\nGo to the bottom of the page and click the wipe link, next to the \u201cSave\u201d button\nNote\nBy wiping the build environment, all the rst, md, and code files associated with it will be removed but not the already built (HTML and PDF files). Your will still online after wiping the build environment.\nNow you can re-build the version with a fresh build environment!", + "headers": [ + "Wiping a Build Environment" + ], + "title": "Wiping a Build Environment", + "sections": [ + { + "content": "\nSometimes it happen that your Builds start failing because the build\nenvironment where the is created is stale or\nbroken. This could happen for a couple of different reasons like pip\nnot upgrading a package properly or a corrupted cached Python package.\n\nIn any of these cases (and many others), the solution could be just\nwiping out the existing build environment files and allow Read the\nDocs to create a new fresh one.\n\nFollow these steps to wipe the build environment:\n\n\n
  • Go to Versions
  • \n
  • Click on the Edit button of the version you want to wipe on the\nright side of the page
  • \n
  • Go to the bottom of the page and click the wipe link, next to\nthe \u201cSave\u201d button
  • \n\n\n\n

    Note

    \n

    By wiping the build environment, all the rst, md,\nand code files associated with it will be removed but not the\n already built (HTML and PDF files). Your\n will still online after wiping the build environment.

    \n\n\nNow you can re-build the version with a fresh build environment!\n", + "id": "wiping-a-build-environment", + "title": "Wiping a Build Environment" + } + ], + "path": "guides/wipe-environment" } diff --git a/readthedocs/search/tests/data/kuma/docker.json b/readthedocs/search/tests/data/kuma/docker.json index cde17951efd..16f4f1e7434 100644 --- a/readthedocs/search/tests/data/kuma/docker.json +++ b/readthedocs/search/tests/data/kuma/docker.json @@ -1,36 +1,25 @@ { - "path": "docker", - "title": "Docker", - "sections": [ - { - "id": "docker", - "title": "Docker", - "content": "Docker is used for development and for deployment." - }, - { - "id": "docker-images", - "title": "Docker Images", - "content": "Docker images are used in development, usually with the local working files mounted in the images to set behaviour.. Images are built by Jenkins, after tests pass, and are published to DockerHub. We try to store the configuration in the environment, so that the published images can be used in deployments by setting environment variables to deployment-specific values.. Here are some of the images used in the Kuma project:. kuma. The kuma Docker image builds on the kuma_base image, installing a kuma branch and building the assets needed for running as a webservice. The environment can be customized for different deployments.. The image can be recreated locally with make build-kuma.. The image tagged latest is used by default for development. It can be created locally with make build-kuma VERSION=latest. The official latest image is created from the master branch in Jenkins and published to DockerHub.. kuma_base. The kuma_base Docker image contains the OS and libraries (C, Python, and Node.js) that support the kuma project. The kuma image extends this by installing the kuma source and building assets needed for production.. The image can be recreated locally with make build-base.. The image tagged latest is used by default for development. It can be created localled with make build-base VERSION=latest. The official latest image is created from the master branch in Jenkins and published to DockerHub. kumascript. The kumascript Docker image contains the kumascript rendering engine and support files. The environment can be customized for different deployments.. The image can be recreated locally with make build-kumascript.. The image tagged latest is used by default for development. It can be created locally with make build-kumascript KS_VERSION=latest. The official latest image is created from the master branch in Jenkins and published to DockerHub.. integration-tests. The integration-tests Docker image contains browser-based integration tests that check the functionality of a running Kuma deployment.. The image can be recreated locally with docker build -f docker/images/integration-tests/ ., but this is only necessary for image development. Most developers will follow the Client-side testing documentation to develop and run these integration tests.. The image is built and used in Jenkins in the stage-integration-tests and prod-integration-tests pipelines, configured by scripts in the Jenkinsfiles folder. It is not published to DockerHub." - } - ], - "domains": [ - { - "role_name": "py:module", - "doc_name": "autoapi/notfound/utils/index.html", - "anchor": "module-notfound.utils", - "type_display": "module", - "doc_display": "notfound.utils", - "name": "notfound.utils", - "display_name": "" - }, - { - "role_name": "py:function", - "doc_name": "autoapi/notfound/utils/index.html", - "anchor": "notfound.utils.replace_uris", - "type_display": "function", - "doc_display": "notfound.utils", - "name": "notfound.utils.replace_uris", - "display_name": "" - } - ] + "content": "kumadocker Docker is used for development and (soon) for deployment.\nDocker Images\nDocker images are used in development, usually with the local working files mounted in the images to set behaviour.\nImages are built by Jenkins, after tests pass, and are published to quay.io. We try to store the configuration in the environment, so that the published images can be used in deployments by setting environment variables to deployment-specific values.\nHere are some of the images used in the Kuma project:\nkuma\nThe kuma Docker image builds on the kuma_base image, installing a kuma branch and building the assets needed for running as a webservice. The environment can be customized for different deployments.\nThe image can be recreated locally with make build-kuma.\nThe image tagged latest is used by default for development. It can be created locally with make build-kuma VERSION=latest. The latest image is created from the master branch in Jenkins and published to quay.io.\nkuma_base\nThe kuma_base Docker image contains the OS and libraries (C, Python, and Node.js) that support the kuma project. The kuma image extends this by installing the kuma source and building assets needed for production.\nThe image can be recreated locally with make build-base.\nThe image tagged latest is used by default for development. It can be created localled with make build-base VERSION=latest. The latest image is created from the master branch in Jenkins and published to quay.io\nkumascript\nThe kumascript Docker image contains the kumascript rendering engine and support files. The environment can be customized for different deployments.\nThe image can be recreated locally with make build-kumascript.\nThe image tagged latest is used by default for development. It can be created locally with make build-kumascript KS_VERSION=latest. The latest image is created from the master branch in Jenkins and published to quay.io.\nintegration-tests\nThe integration-tests Docker image contains browser-based integration tests that check the functionality of a running Kuma deployment.\nThe image can be recreated locally with docker build -f docker/images/integration-tests/ ., but this is only necessary for image development. Most developer will follow the Client-side testing to develop and run these integration tests.\nThe image is built and used in Jenkins in the stage-integration-tests and prod-integration-tests pipelines, configured by scripts in the Jenkinsfiles folder. It is not published to quay.io.", + "headers": [ + "Docker", + "Docker Images", + "kuma", + "kuma_base", + "kumascript", + "integration-tests" + ], + "title": "Docker", + "sections": [ + { + "content": "\nDocker is used for development and (soon) for deployment.\n", + "id": "docker", + "title": "Docker" + }, + { + "content": "\n

    Docker Images\u00b6

    \n

    Docker images are used in development, usually with the local\nworking files mounted in the images to set behaviour.

    \n

    Images are built by Jenkins, after tests pass, and are\npublished to quay.io. We try to\nstore the configuration in the environment, so that the\npublished images can be used in deployments by setting\nenvironment variables to deployment-specific values.

    \n

    Here are some of the images used in the Kuma project:

    \n
    \n

    kuma\u00b6

    \n

    The kuma Docker image builds on the kuma_base image, installing a kuma branch\nand building the assets needed for running as a webservice. The environment\ncan be customized for different deployments.

    \n

    The image can be recreated locally with make build-kuma.

    \n

    The image tagged latest is used by default for development. It can be\ncreated locally with make build-kuma VERSION=latest. The latest\nimage is created from the master branch in Jenkins and published to\nquay.io.

    \n
    \n
    \n

    kuma_base\u00b6

    \n

    The kuma_base Docker image contains the OS and libraries (C, Python, and\nNode.js) that support the kuma project. The kuma image extends this by\ninstalling the kuma source and building assets needed for production.

    \n

    The image can be recreated locally with make build-base.

    \n

    The image tagged latest is used by default for development. It can be\ncreated localled with make build-base VERSION=latest. The \nlatest image is created from the master branch in Jenkins and published to\nquay.io

    \n
    \n
    \n

    kumascript\u00b6

    \n

    The kumascript Docker image contains the kumascript rendering engine and\nsupport files. The environment can be customized for different deployments.

    \n

    The image can be recreated locally with make build-kumascript.

    \n

    The image tagged latest is used by default for development. It can be\ncreated locally with make build-kumascript KS_VERSION=latest. The \nlatest image is created from the master branch in Jenkins and published to\nquay.io.

    \n
    \n
    \n

    integration-tests\u00b6

    \n

    The integration-tests Docker image contains browser-based integration tests\nthat check the functionality of a running Kuma deployment.

    \n

    The image can be recreated locally with\ndocker build -f docker/images/integration-tests/ ., but this is only\nnecessary for image development. Most developer will follow the\nClient-side testing to develop and run these integration tests.

    \n

    The image is built and used in Jenkins in the stage-integration-tests and\nprod-integration-tests pipelines, configured by scripts in the\nJenkinsfiles folder. It is not published to quay.io.

    \n
    \n", + "id": "docker-images", + "title": "Docker Images" + } + ], + "path": "docker" } diff --git a/readthedocs/search/tests/data/kuma/documentation.json b/readthedocs/search/tests/data/kuma/documentation.json index bced181ff22..1dcefa8c2c3 100644 --- a/readthedocs/search/tests/data/kuma/documentation.json +++ b/readthedocs/search/tests/data/kuma/documentation.json @@ -1,36 +1,21 @@ { - "path": "documentation", - "title": "Documentation", - "sections": [ - { - "id": "documentation", - "title": "Documentation", - "content": "This documentation is generated and published at Read the Docs whenever the master branch is updated.GitHub can render our .rst documents as ReStructuredText, which is close enough to Sphinx for most code reviews, without features like links between documents.It is occasionally necessary to generate the documentation locally. It is easiest to do this with a virtualenv on the host system, using Docker only to regenerate the MDN Sphinx template. If you are not comfortable with that style of development, it can be done entirely in Docker using docker-compose." - }, - { - "id": "generating-documentation", - "title": "Generating documentation", - "content": "Sphinx uses a Makefile in the docs subfolder to build documentation in several formats. MDN only uses the HTML format, and the generated document index is at docs/_build/html/index.html.. To generate the documentation in a virtualenv on the host machine, first install the requirements:. pip install -r requirements/docs.txt. Then switch to the docs folder to use the Makefile:. cd docs make html python -m webbrowser file://${PWD}/_build/html/index.html. To generate the documentation with Docker:. docker-compose run --rm --user $(id -u) web sh -c \"\\ virtualenv /tmp/.venvs/docs && \\ . /tmp/.venvs/docs/bin/activate && \\ pip install -r /app/requirements/docs.txt && \\ cd /app/docs && \\ make html\" python -m webbrowser file://${PWD}/docs/_build/html/index.html. A virtualenv is required, to avoid a pip bug when changing the version of a system-installed package." - } - ], - "domains": [ - { - "role_name": "py:module", - "doc_name": "autoapi/notfound/index.html", - "anchor": "module-notfound", - "type_display": "module", - "doc_display": "notfound", - "name": "notfound", - "display_name": "" - }, - { - "role_name": "py:data", - "doc_name": "autoapi/notfound/index.html", - "anchor": "notfound.version", - "type_display": "data", - "doc_display": "notfound", - "name": "notfound.version", - "display_name": "" - } - ] + "content": "kumadocumentation This documentation is generated and published at Read the Docs whenever the master branch is updated. GitHub can render our .rst documents as ReStructuredText, which is close enough to Sphinx for most code reviews, without features like links between documents.\nIt is occasionally necessary to generate the documentation locally. It is easiest to do this with a virtualenv on the host system, using only to regenerate the MDN Sphinx template. If you are not comfortable with that style of development, it can be done entirely in using -compose.\nGenerating documentation\nSphinx uses a Makefile in the docs subfolder to build documentation in several formats. MDN only uses the HTML format, and the generated document index is at docs/_build/html/index.html.\nTo generate the documentation in a virtualenv on the host machine, first install the requirements:\npip install -r requirements/docs.txt\nThen switch to the docs folder to use the Makefile:\ncd docs make html python -m webbrowser file://${PWD}/_build/html/index.html\nTo generate the documentation with :\n-compose run --rm --user $(id -u) web sh -c \"\\ virtualenv /tmp/.venvs/docs && \\ . /tmp/.venvs/docs/bin/activate && \\ pip install -r /app/requirements/docs.txt && \\ cd /app/docs && \\ make html\" python -m webbrowser file://${PWD}/docs/_build/html/index.html\nA virtualenv is required, to avoid a pip bug when changing the version of a system-installed package.", + "headers": [ + "Documentation", + "Generating documentation" + ], + "title": "Documentation", + "sections": [ + { + "content": "\nThis documentation is generated and published at\nRead the Docs whenever the master branch is updated.\n\nGitHub can render our .rst documents as ReStructuredText, which is\nclose enough to Sphinx for most code reviews, without features like links\nbetween documents.\n\nIt is occasionally necessary to generate the documentation locally. It is\neasiest to do this with a virtualenv on the host system, using only to\nregenerate the MDN Sphinx template. If you are not comfortable with that style\nof development, it can be done entirely in using -compose.\n", + "id": "documentation", + "title": "Documentation" + }, + { + "content": "\n

    Generating documentation\u00b6

    \n

    Sphinx uses a Makefile in the docs subfolder to build documentation in\nseveral formats. MDN only uses the HTML format, and the generated document\nindex is at docs/_build/html/index.html.

    \n

    To generate the documentation in a virtualenv on the host machine, first\ninstall the requirements:

    \n
    pip install -r requirements/docs.txt\n
    \n
    \n

    Then switch to the docs folder to use the Makefile:

    \n
    cd docs\nmake html\npython -m webbrowser file://${PWD}/_build/html/index.html\n
    \n
    \n

    To generate the documentation with :

    \n
    -compose run --rm --user $(id -u) web sh -c \"\\\n  virtualenv /tmp/.venvs/docs && \\\n  . /tmp/.venvs/docs/bin/activate && \\\n  pip install -r /app/requirements/docs.txt && \\\n  cd /app/docs && \\\n  make html\"\npython -m webbrowser file://${PWD}/docs/_build/html/index.html\n
    \n
    \n

    A virtualenv is required, to avoid a pip bug when changing the version\nof a system-installed package.

    \n", + "id": "generating-documentation", + "title": "Generating documentation" + } + ], + "path": "documentation" } diff --git a/readthedocs/search/tests/data/pipeline/installation.json b/readthedocs/search/tests/data/pipeline/installation.json index eed6a351b3c..40d21fed5d4 100644 --- a/readthedocs/search/tests/data/pipeline/installation.json +++ b/readthedocs/search/tests/data/pipeline/installation.json @@ -1,37 +1,33 @@ { - "path": "installation", - "title": "Installation", - "sections": [ - { - "id": "installation", - "title": "Installation", - "content": "pip install django-pipeline. Add ‘pipeline’ to your INSTALLED_APPS. INSTALLED_APPS = ( 'pipeline', ). Use a pipeline storage for STATICFILES_STORAGE. STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'. Add the PipelineFinder to STATICFILES_FINDERS. STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'pipeline.finders.PipelineFinder', )You need to use Django>=1.7 to be able to use this version of pipeline." - }, - { - "id": "upgrading-from-1-3", - "title": "Upgrading from 1.3", - "content": "To upgrade from pipeline 1.3, you will need to follow these steps:. Update templates to use the new syntax. {# pipeline<1.4 #} {% load compressed %} {% compressed_js 'group' %} {% compressed_css 'group' %}. {# pipeline>=1.4 #} {% load pipeline %} {% javascript 'group' %} {% stylesheet 'group' %}. Add the PipelineFinder to STATICFILES_FINDERS. STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'pipeline.finders.PipelineFinder', )" - }, - { - "id": "upgrading-from-1-5", - "title": "Upgrading from 1.5", - "content": "To upgrade from pipeline 1.5, you will need update all your PIPELINE_* settings and move them under the new PIPELINE setting. See Configuration." - }, - { - "id": "recommendations", - "title": "Recommendations", - "content": "Pipeline’s default CSS and JS compressor is Yuglify. Yuglify wraps UglifyJS and cssmin, applying the default YUI configurations to them. It can be downloaded from: https://github.com/yui/yuglify/.. If you do not install yuglify, make sure to disable the compressor in your settings." - } - ], - "domains": [ - { - "role_name": "std:confval", - "doc_name": "configuration.html", - "anchor": "confval-notfound_default_language", - "type_display": "confval", - "doc_display": "Configuration", - "name": "notfound_default_language", - "display_name": "" - } - ] + "content": "PipelineInstallation Official Either check out Pipeline from GitHub or to pull a release off PyPI\npip install django-pipeline\nAdd \u2018pipeline\u2019 to your INSTALLED_APPS\nINSTALLED_APPS = ( 'pipeline', )\nUse a pipeline storage for STATICFILES_STORAGE\nSTATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'\nAdd the PipelineFinder to STATICFILES_FINDERS\nSTATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'pipeline.finders.PipelineFinder', )\nNote\nYou need to use Django>=1.7 to be able to use this version of pipeline.\nUpgrading from 1.3\nTo upgrade from pipeline 1.3, you will need to follow these steps:\nUpdate templates to use the new syntax\n{# pipeline<1.4 #} {% load compressed %} {% compressed_js 'group' %} {% compressed_css 'group' %}\n{# pipeline>=1.4 #} {% load pipeline %} {% javascript 'group' %} {% stylesheet 'group' %}\nAdd the PipelineFinder to STATICFILES_FINDERS\nSTATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'pipeline.finders.PipelineFinder', )\nUpgrading from 1.5\nTo upgrade from pipeline 1.5, you will need update all your PIPELINE_* settings and move them under the new PIPELINE setting. See Configuration.\nRecommendations\nPipeline\u2019s default CSS and JS compressor is Yuglify. Yuglify wraps UglifyJS and cssmin, applying the default YUI configurations to them. It can be downloaded from: https://github.com/yui/yuglify/.\nIf you do not install yuglify, make sure to disable the compressor in your settings.", + "headers": [ + "Installation", + "Upgrading from 1.3", + "Upgrading from 1.5", + "Recommendations" + ], + "title": "Installation", + "sections": [ + { + "content": "\n\n
  • Either check out Pipeline from GitHub or to pull a release off PyPI

    \n
    pip install django-pipeline\n
    \n
    \n
  • \n
  • Add \u2018pipeline\u2019 to your INSTALLED_APPS

    \n
    INSTALLED_APPS = (\n    'pipeline',\n)\n
    \n
    \n
  • \n
  • Use a pipeline storage for STATICFILES_STORAGE

    \n
    STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'\n
    \n
    \n
  • \n
  • Add the PipelineFinder to STATICFILES_FINDERS

    \n
    STATICFILES_FINDERS = (\n    'django.contrib.staticfiles.finders.FileSystemFinder',\n    'django.contrib.staticfiles.finders.AppDirectoriesFinder',\n    'pipeline.finders.PipelineFinder',\n)\n
    \n
    \n
  • \n\n\n\n

    Note

    \n

    You need to use Django>=1.7 to be able to use this version of pipeline.

    \n\n", + "id": "installation", + "title": "Installation" + }, + { + "content": "\n

    Upgrading from 1.3\u00b6

    \n

    To upgrade from pipeline 1.3, you will need to follow these steps:

    \n
      \n
    1. Update templates to use the new syntax

      \n
      \n
      {# pipeline<1.4 #}\n{% load compressed %}\n{% compressed_js 'group' %}\n{% compressed_css 'group' %}\n
      \n
      \n
      {# pipeline>=1.4 #}\n{% load pipeline %}\n{% javascript 'group' %}\n{% stylesheet 'group' %}\n
      \n
      \n
      \n
    2. \n
    3. Add the PipelineFinder to STATICFILES_FINDERS

      \n
      STATICFILES_FINDERS = (\n    'django.contrib.staticfiles.finders.FileSystemFinder',\n    'django.contrib.staticfiles.finders.AppDirectoriesFinder',\n    'pipeline.finders.PipelineFinder',\n)\n
      \n
      \n
    4. \n
    \n", + "id": "upgrading-from-1-3", + "title": "Upgrading from 1.3" + }, + { + "content": "\n

    Upgrading from 1.5\u00b6

    \n

    To upgrade from pipeline 1.5, you will need update all your PIPELINE_*\nsettings and move them under the new PIPELINE setting.\nSee Configuration.

    \n", + "id": "upgrading-from-1-5", + "title": "Upgrading from 1.5" + }, + { + "content": "\n

    Recommendations\u00b6

    \n

    Pipeline\u2019s default CSS and JS compressor is Yuglify.\nYuglify wraps UglifyJS and cssmin, applying the default YUI configurations to them.\nIt can be downloaded from: https://github.com/yui/yuglify/.

    \n

    If you do not install yuglify, make sure to disable the compressor in your settings.

    \n", + "id": "recommendations", + "title": "Recommendations" + } + ], + "path": "installation" } diff --git a/readthedocs/search/tests/data/pipeline/signals.json b/readthedocs/search/tests/data/pipeline/signals.json index 97b1095d29f..78349e5e3aa 100644 --- a/readthedocs/search/tests/data/pipeline/signals.json +++ b/readthedocs/search/tests/data/pipeline/signals.json @@ -1,41 +1,27 @@ { - "path": "signals", - "title": "Signals", - "sections": [ - { - "id": "signals", - "title": "Signals", - "content": "List of all signals sent by pipeline." - }, - { - "id": "css-compressed", - "title": "css_compressed", - "content": "pipeline.signals.css_compressed. Whenever a css package is compressed, this signal is sent after the compression.. Arguments sent with this signal :. sender:. The Packager class that compressed the group.. package:. The package actually compressed." - }, - { - "id": "js-compressed", - "title": "js_compressed", - "content": "pipeline.signals.js_compressed. Whenever a js package is compressed, this signal is sent after the compression.. Arguments sent with this signal :. sender:. The Packager class that compressed the group.. package:. The package actually compressed." - } - ], - "domains": [ - { - "role_name": "py:method", - "doc_name": "autoapi/notfound/extension/index.html", - "anchor": "notfound.extension.OrphanMetadataCollector.process_doc", - "type_display": "method", - "doc_display": "notfound.extension", - "name": "notfound.extension.OrphanMetadataCollector.process_doc", - "display_name": "" - }, - { - "role_name": "py:method", - "doc_name": "autoapi/notfound/extension/index.html", - "anchor": "notfound.extension.OrphanMetadataCollector.clear_doc", - "type_display": "method", - "doc_display": "notfound.extension", - "name": "notfound.extension.OrphanMetadataCollector.clear_doc", - "display_name": "" - } - ] + "content": "pipelineSignals List of all signals sent by pipeline.\ncss_compressed\npipeline.signals.css_compressed\nWhenever a css package is compressed, this signal is sent after the compression.\nArguments sent with this signal :\nsender:\nThe Packager class that compressed the group.\npackage:\nThe package actually compressed.\njs_compressed\npipeline.signals.js_compressed\nWhenever a js package is compressed, this signal is sent after the compression.\nArguments sent with this signal :\nsender:\nThe Packager class that compressed the group.\npackage:\nThe package actually compressed.", + "headers": [ + "Signals", + "css_compressed", + "js_compressed" + ], + "title": "Signals", + "sections": [ + { + "content": "\nList of all signals sent by pipeline.\n", + "id": "signals", + "title": "Signals" + }, + { + "content": "\n

    css_compressed\u00b6

    \n

    pipeline.signals.css_compressed

    \n
    \n

    Whenever a css package is compressed, this signal is sent after the compression.

    \n

    Arguments sent with this signal :

    \n
    \n
    \n\n\n\n\n\n\n\n\n
    sender:The Packager class that compressed the group.
    package:The package actually compressed.
    \n
    \n
    \n", + "id": "css-compressed", + "title": "css_compressed" + }, + { + "content": "\n

    js_compressed\u00b6

    \n

    pipeline.signals.js_compressed

    \n
    \n

    Whenever a js package is compressed, this signal is sent after the compression.

    \n

    Arguments sent with this signal :

    \n
    \n
    \n\n\n\n\n\n\n\n\n
    sender:The Packager class that compressed the group.
    package:The package actually compressed.
    \n
    \n
    \n", + "id": "js-compressed", + "title": "js_compressed" + } + ], + "path": "signals" } diff --git a/readthedocs/search/tests/dummy_data.py b/readthedocs/search/tests/dummy_data.py index 8c1cc9e5951..ed1d5c7e2f6 100644 --- a/readthedocs/search/tests/dummy_data.py +++ b/readthedocs/search/tests/dummy_data.py @@ -1,7 +1,7 @@ PROJECT_DATA_FILES = { 'pipeline': ['installation', 'signals'], 'kuma': ['documentation', 'docker'], - 'docs': ['support', 'wiping'], + 'docs': ['story', 'wiping'], } ALL_PROJECTS = PROJECT_DATA_FILES.keys() diff --git a/readthedocs/search/tests/test_api.py b/readthedocs/search/tests/test_api.py index aa25aff4182..42e8187a856 100644 --- a/readthedocs/search/tests/test_api.py +++ b/readthedocs/search/tests/test_api.py @@ -11,7 +11,7 @@ @pytest.mark.django_db @pytest.mark.search -class TestDocumentSearch: +class TestDocumentSearch(object): @classmethod def setup_class(cls): @@ -20,133 +20,40 @@ def setup_class(cls): # installed cls.url = reverse('doc_search') - @pytest.mark.parametrize('data_type', ['title']) - @pytest.mark.parametrize('page_num', [1, 0]) - def test_search_works_with_title_query(self, api_client, project, page_num, data_type): - query = get_search_query_from_project_file( - project_slug=project.slug, - page_num=page_num, - data_type=data_type - ) - - version = project.versions.all().first() - search_params = { - 'project': project.slug, - 'version': version.slug, - 'q': query - } - resp = api_client.get(self.url, search_params) - assert resp.status_code == 200 - - data = resp.data['results'] - assert len(data) >= 1 + @pytest.mark.parametrize('data_type', ['content', 'headers', 'title']) + @pytest.mark.parametrize('page_num', [0, 1]) + def test_search_works(self, api_client, project, data_type, page_num): + query = get_search_query_from_project_file(project_slug=project.slug, page_num=page_num, + data_type=data_type) - # Matching first result - project_data = data[0] - assert project_data['project'] == project.slug - - # Check highlight return correct object of first result - title_highlight = project_data['highlight'][data_type] - - assert len(title_highlight) == 1 - assert query.lower() in title_highlight[0].lower() - - @pytest.mark.parametrize( - 'data_type', - [ - # page sections fields - 'sections.title', - 'sections.content', - - # domain fields - 'domains.type_display', - 'domains.name', - - # TODO: Add test for "domains.display_name" - ] - ) - @pytest.mark.parametrize('page_num', [0]) - def test_search_works_with_sections_and_domains_query( - self, - api_client, - project, - page_num, - data_type - ): - query = get_search_query_from_project_file( - project_slug=project.slug, - page_num=page_num, - data_type=data_type - ) - version = project.versions.all().first() - search_params = { - 'project': project.slug, - 'version': version.slug, - 'q': query - } + version = project.versions.all()[0] + search_params = {'project': project.slug, 'version': version.slug, 'q': query} resp = api_client.get(self.url, search_params) assert resp.status_code == 200 data = resp.data['results'] - assert len(data) >= 1 - - # Matching first result + assert len(data) == 1 project_data = data[0] assert project_data['project'] == project.slug - inner_hits = list(project_data['inner_hits']) - # since there was a nested query, - # inner_hits should not be empty - assert len(inner_hits) >= 1 - - inner_hit_0 = inner_hits[0] # first inner_hit - - expected_type = data_type.split('.')[0] # can be "sections" or "domains" - assert inner_hit_0['type'] == expected_type - - highlight = inner_hit_0['highlight'][data_type] - assert ( - len(highlight) == 1 - ), 'number_of_fragments is set to 1' - - # checking highlighting of results - queries = query.split() # if query is more than one word - queries_len = len(queries) - total_query_words_highlighted = 0 - - for q in queries: - if f'{q.lower()}' in highlight[0].lower(): - total_query_words_highlighted += 1 - - if queries_len == 1: - # if the search was of one word, - # then the it must be highlighted - assert total_query_words_highlighted - queries_len <= 0 - else: - # if the search was of two words or more, - # then it is not necessary for every word - # to get highlighted - assert total_query_words_highlighted - queries_len <= 1 + # Check highlight return correct object + all_highlights = project_data['highlight'][data_type] + for highlight in all_highlights: + # Make it lower because our search is case insensitive + assert query.lower() in highlight.lower() def test_doc_search_filter_by_project(self, api_client): - """Test Doc search results are filtered according to project""" - - # `documentation` word is present both in `kuma` and `docs` files - # and not in `pipeline`, so search with this phrase but filter through project - search_params = { - 'q': 'documentation', - 'project': 'docs', - 'version': 'latest' - } + """Test Doc search result are filtered according to project""" + + # `Github` word is present both in `kuma` and `pipeline` files + # so search with this phrase but filter through `kuma` project + search_params = {'q': 'GitHub', 'project': 'kuma', 'version': 'latest'} resp = api_client.get(self.url, search_params) assert resp.status_code == 200 data = resp.data['results'] - assert len(data) == 2 # both pages of `docs` contains the word `documentation` - - # all results must be from same project - for res in data: - assert res['project'] == 'docs' + assert len(data) == 1 + assert data[0]['project'] == 'kuma' def test_doc_search_filter_by_version(self, api_client, project): """Test Doc search result are filtered according to version""" @@ -163,81 +70,70 @@ def test_doc_search_filter_by_version(self, api_client, project): f.save() PageDocument().update(f) - search_params = { - 'q': query, - 'project': project.slug, - 'version': dummy_version.slug - } + search_params = {'q': query, 'project': project.slug, 'version': dummy_version.slug} resp = api_client.get(self.url, search_params) assert resp.status_code == 200 data = resp.data['results'] + assert len(data) == 1 + assert data[0]['project'] == project.slug - # there may be more than one results - # for some query like `documentation` - # for project `kuma` - assert len(data) >= 1 - - # all results must be from same project - for res in data: - assert res['project'] == project.slug - - # def test_doc_search_pagination(self, api_client, project): - # """Test Doc search result can be paginated""" - # latest_version = project.versions.all()[0] - # html_file = HTMLFile.objects.filter(version=latest_version)[0] - # title = html_file.processed_json['title'] - # query = title.split()[0] - - # # Create 60 more same html file - # for _ in range(60): - # # Make primary key to None, so django will create new object - # html_file.pk = None - # html_file.save() - # PageDocument().update(html_file) - - # search_params = {'q': query, 'project': project.slug, 'version': latest_version.slug} - # resp = api_client.get(self.url, search_params) - # assert resp.status_code == 200 - - # # Check the count is 61 (1 existing and 60 new created) - # assert resp.data['count'] == 61 - # # Check there are next url - # assert resp.data['next'] is not None - # # There should be only 50 data as the pagination is 50 by default - # assert len(resp.data['results']) == 50 - - # # Add `page_size` parameter and check the data is paginated accordingly - # search_params['page_size'] = 5 - # resp = api_client.get(self.url, search_params) - # assert resp.status_code == 200 - - # assert len(resp.data['results']) == 5 - - # def test_doc_search_without_parameters(self, api_client, project): - # """Hitting Document Search endpoint without query parameters should return error""" - # resp = api_client.get(self.url) - # assert resp.status_code == 400 - # # Check error message is there - # assert sorted(['q', 'project', 'version']) == sorted(resp.data.keys()) - - # def test_doc_search_subprojects(self, api_client, all_projects): - # """Test Document search return results from subprojects also""" - # project = all_projects[0] - # subproject = all_projects[1] - # version = project.versions.all()[0] - # # Add another project as subproject of the project - # project.add_subproject(subproject) - - # # Now search with subproject content but explicitly filter by the parent project - # query = get_search_query_from_project_file(project_slug=subproject.slug) - # search_params = {'q': query, 'project': project.slug, 'version': version.slug} - # resp = api_client.get(self.url, search_params) - # assert resp.status_code == 200 - - # data = resp.data['results'] - # assert len(data) == 1 - # assert data[0]['project'] == subproject.slug - # # Check the link is the subproject document link - # document_link = subproject.get_docs_url(version_slug=version.slug) - # assert document_link in data[0]['link'] + def test_doc_search_pagination(self, api_client, project): + """Test Doc search result can be paginated""" + latest_version = project.versions.all()[0] + html_file = HTMLFile.objects.filter(version=latest_version)[0] + title = html_file.processed_json['title'] + query = title.split()[0] + + # Create 60 more same html file + for _ in range(60): + # Make primary key to None, so django will create new object + html_file.pk = None + html_file.save() + PageDocument().update(html_file) + + search_params = {'q': query, 'project': project.slug, 'version': latest_version.slug} + resp = api_client.get(self.url, search_params) + assert resp.status_code == 200 + + # Check the count is 61 (1 existing and 60 new created) + assert resp.data['count'] == 61 + # Check there are next url + assert resp.data['next'] is not None + # There should be only 50 data as the pagination is 50 by default + assert len(resp.data['results']) == 50 + + # Add `page_size` parameter and check the data is paginated accordingly + search_params['page_size'] = 5 + resp = api_client.get(self.url, search_params) + assert resp.status_code == 200 + + assert len(resp.data['results']) == 5 + + def test_doc_search_without_parameters(self, api_client, project): + """Hitting Document Search endpoint without query parameters should return error""" + resp = api_client.get(self.url) + assert resp.status_code == 400 + # Check error message is there + assert sorted(['q', 'project', 'version']) == sorted(resp.data.keys()) + + def test_doc_search_subprojects(self, api_client, all_projects): + """Test Document search return results from subprojects also""" + project = all_projects[0] + subproject = all_projects[1] + version = project.versions.all()[0] + # Add another project as subproject of the project + project.add_subproject(subproject) + + # Now search with subproject content but explicitly filter by the parent project + query = get_search_query_from_project_file(project_slug=subproject.slug) + search_params = {'q': query, 'project': project.slug, 'version': version.slug} + resp = api_client.get(self.url, search_params) + assert resp.status_code == 200 + + data = resp.data['results'] + assert len(data) == 1 + assert data[0]['project'] == subproject.slug + # Check the link is the subproject document link + document_link = subproject.get_docs_url(version_slug=version.slug) + assert document_link in data[0]['link'] diff --git a/readthedocs/search/tests/utils.py b/readthedocs/search/tests/utils.py index 4a2c8d23c02..ee9bd8728df 100644 --- a/readthedocs/search/tests/utils.py +++ b/readthedocs/search/tests/utils.py @@ -1,7 +1,4 @@ # -*- coding: utf-8 -*- - -import random - from readthedocs.projects.models import HTMLFile @@ -15,61 +12,11 @@ def get_search_query_from_project_file(project_slug, page_num=0, data_type='titl html_file = HTMLFile.objects.filter(project__slug=project_slug).order_by('id')[page_num] file_data = html_file.processed_json - query_data = file_data[data_type.split('.')[0]] - - if data_type == 'title': - - # uses first word of page title as query - query = query_data.split()[0] - - elif data_type.startswith('sections'): - - # generates query from section title - if data_type.endswith('title'): - query_data = query_data[0]['title'].split() - start = 0 - end = random.randint(1, len(query_data)) - query = query_data[start:end] - query = ' '.join(query) - - # generates query from section content - elif data_type.endswith('content'): - query_data = query_data[0]['content'].split() - start = random.randint(0, 6) - - # 3 words to generate query to make sure that - # query does not only contains 'is', 'and', 'the' - # and other stop words - end = start + 3 - - query = query_data[start:end] - query = ' '.join(query) - - elif data_type.startswith('domains'): - - # uses first word of domains.type_display as query - if data_type.endswith('type_display'): - query = query_data[0]['type_display'].split()[0] - - # generates query from domains.name - if data_type.endswith('name'): - # test data contains domains.name - # some of which contains '.' and some '/' - # and others are plain words. - # Splitting with '.' and '/' is done - # to ensure that the query contains proper words - if '.' in query_data[0]['name']: - query_data = query_data[0]['name'].split('.') - start = 0 - end = random.randint(1, len(query_data)) - query = '.'.join(query_data[start:end]) + query_data = file_data[data_type] - elif '/' in query_data[0]['name']: - query_data = query_data[0]['name'].split('/') - start = 0 - end = random.randint(1, len(query_data)) - query = '/'.join(query_data[start:end]) - else: - query = query_data[0]['name'].split()[0] + if data_type in ['headers']: + # The data is in list. slice in order to get the text + query_data = query_data[0] + query = query_data.split()[0] return query From d7edeee0839ca0f8c31642d7548ee0766030d036 Mon Sep 17 00:00:00 2001 From: dojutsu-user Date: Fri, 12 Jul 2019 21:04:22 +0530 Subject: [PATCH 59/59] update template to make 100 as constant --- .../templates/search/elastic_search.html | 415 +++++++++--------- 1 file changed, 207 insertions(+), 208 deletions(-) diff --git a/readthedocs/templates/search/elastic_search.html b/readthedocs/templates/search/elastic_search.html index 16a23546b49..68471fa9b28 100644 --- a/readthedocs/templates/search/elastic_search.html +++ b/readthedocs/templates/search/elastic_search.html @@ -25,227 +25,226 @@ {% block content %} -{% with "100" as MAX_SUBSTRING_LIMIT %} - -