OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 from copy import copy | 5 from copy import copy |
6 import logging | 6 import logging |
7 import re | 7 import re |
8 | 8 |
9 from file_system import FileNotFoundError | 9 from file_system import FileNotFoundError |
10 from third_party.json_schema_compiler.model import PropertyType | 10 from third_party.json_schema_compiler.model import PropertyType |
(...skipping 29 matching lines...) Expand all Loading... |
40 # happening anyway unless there's a bug, such as http://crbug.com/314102. | 40 # happening anyway unless there's a bug, such as http://crbug.com/314102. |
41 max_size = 256 | 41 max_size = 256 |
42 if len(key) > max_size: | 42 if len(key) > max_size: |
43 logging.error('Key was >%s characters: %s' % (max_size, key)) | 43 logging.error('Key was >%s characters: %s' % (max_size, key)) |
44 key = key[:max_size] | 44 key = key[:max_size] |
45 return key | 45 return key |
46 | 46 |
47 | 47 |
48 class ReferenceResolver(object): | 48 class ReferenceResolver(object): |
49 """Resolves references to $ref's by searching through the APIs to find the | 49 """Resolves references to $ref's by searching through the APIs to find the |
50 correct node. | 50 correct node. See document_renderer.py for more information on $ref syntax. |
51 | |
52 $ref's have two forms: | |
53 | |
54 $ref:api.node - Replaces the $ref with a link to node on the API page. The | |
55 title is set to the name of the node. | |
56 | |
57 $ref:[api.node The Title] - Same as the previous form but title is set to | |
58 "The Title". | |
59 """ | 51 """ |
60 | |
61 # Matches after a $ref: that doesn't have []s. | |
62 _bare_ref = re.compile('\w+(\.\w+)*') | |
63 | |
64 def __init__(self, api_models, object_store): | 52 def __init__(self, api_models, object_store): |
65 self._api_models = api_models | 53 self._api_models = api_models |
66 self._object_store = object_store | 54 self._object_store = object_store |
67 | 55 |
68 def _GetRefLink(self, ref, api_list, namespace): | 56 def _GetRefLink(self, ref, api_list, namespace): |
69 # Check nodes within each API the ref might refer to. | 57 # Check nodes within each API the ref might refer to. |
70 parts = ref.split('.') | 58 parts = ref.split('.') |
71 for i, part in enumerate(parts): | 59 for i in xrange(1, len(parts)): |
72 api_name = '.'.join(parts[:i]) | 60 api_name = '.'.join(parts[:i]) |
73 if api_name not in api_list: | 61 if api_name not in api_list: |
74 continue | 62 continue |
75 try: | 63 try: |
76 api_model = self._api_models.GetModel(api_name).Get() | 64 api_model = self._api_models.GetModel(api_name).Get() |
77 except FileNotFoundError: | 65 except FileNotFoundError: |
78 continue | 66 continue |
79 name = '.'.join(parts[i:]) | 67 name = '.'.join(parts[i:]) |
80 # Attempt to find |name| in the API. | 68 # Attempt to find |name| in the API. |
81 node_info = _ClassifySchemaNode(name, api_model) | 69 node_info = _ClassifySchemaNode(name, api_model) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 if ref_data is not None: | 137 if ref_data is not None: |
150 return ref_data | 138 return ref_data |
151 logging.error('$ref %s could not be resolved in namespace %s.' % | 139 logging.error('$ref %s could not be resolved in namespace %s.' % |
152 (ref, namespace)) | 140 (ref, namespace)) |
153 type_name = ref.rsplit('.', 1)[-1] | 141 type_name = ref.rsplit('.', 1)[-1] |
154 return { | 142 return { |
155 'href': '#type-%s' % type_name, | 143 'href': '#type-%s' % type_name, |
156 'text': title or ref, | 144 'text': title or ref, |
157 'name': ref | 145 'name': ref |
158 } | 146 } |
159 | |
160 # TODO(ahernandez.miralles): This function is no longer needed, | |
161 # and uses a deprecated style of ref | |
162 def ResolveAllLinks(self, text, relative_to='', namespace=None): | |
163 """This method will resolve all $ref links in |text| using namespace | |
164 |namespace| if not None. Any links that cannot be resolved will be replaced | |
165 using the default link format that |SafeGetLink| uses. | |
166 The links will be generated relative to |relative_to|. | |
167 """ | |
168 if text is None or '$ref:' not in text: | |
169 return text | |
170 | |
171 # requestPath should be of the form (apps|extensions)/...../page.html. | |
172 # link_prefix should that the target will point to | |
173 # (apps|extensions)/target.html. Note multiplying a string by a negative | |
174 # number gives the empty string. | |
175 link_prefix = '../' * (relative_to.count('/') - 1) | |
176 split_text = text.split('$ref:') | |
177 # |split_text| is an array of text chunks that all start with the | |
178 # argument to '$ref:'. | |
179 formatted_text = [split_text[0]] | |
180 for ref_and_rest in split_text[1:]: | |
181 title = None | |
182 if ref_and_rest.startswith('[') and ']' in ref_and_rest: | |
183 # Text was '$ref:[foo.bar maybe title] other stuff'. | |
184 ref_with_title, rest = ref_and_rest[1:].split(']', 1) | |
185 ref_with_title = ref_with_title.split(None, 1) | |
186 if len(ref_with_title) == 1: | |
187 # Text was '$ref:[foo.bar] other stuff'. | |
188 ref = ref_with_title[0] | |
189 else: | |
190 # Text was '$ref:[foo.bar title] other stuff'. | |
191 ref, title = ref_with_title | |
192 else: | |
193 # Text was '$ref:foo.bar other stuff'. | |
194 match = self._bare_ref.match(ref_and_rest) | |
195 if match is None: | |
196 ref = '' | |
197 rest = ref_and_rest | |
198 else: | |
199 ref = match.group() | |
200 rest = ref_and_rest[match.end():] | |
201 | |
202 ref_dict = self.SafeGetLink(ref, namespace=namespace, title=title) | |
203 formatted_text.append('<a href="%s%s">%s</a>%s' % | |
204 (link_prefix, ref_dict['href'], ref_dict['text'], rest)) | |
205 return ''.join(formatted_text) | |
OLD | NEW |