| 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 import copy | 5 import copy |
| 6 import os | 6 import os |
| 7 | 7 |
| 8 from docs_server_utils import GetLinkToRefType | 8 from docs_server_utils import GetLinkToRefType |
| 9 import third_party.json_schema_compiler.model as model | 9 import third_party.json_schema_compiler.model as model |
| 10 | 10 |
| 11 def _RemoveNoDocs(item): | 11 def _RemoveNoDocs(item): |
| 12 if type(item) == dict: | 12 if type(item) == dict: |
| 13 if item.get('nodoc', False): | 13 if item.get('nodoc', False): |
| 14 return True | 14 return True |
| 15 for key, value in item.items(): | 15 for key, value in item.items(): |
| 16 if _RemoveNoDocs(value): | 16 if _RemoveNoDocs(value): |
| 17 del item[key] | 17 del item[key] |
| 18 elif type(item) == list: | 18 elif type(item) == list: |
| 19 for i in item: | 19 for i in item: |
| 20 if _RemoveNoDocs(i): | 20 if _RemoveNoDocs(i): |
| 21 item.remove(i) | 21 item.remove(i) |
| 22 return False | 22 return False |
| 23 | 23 |
| 24 def _CreateId(node, prefix): |
| 25 if node.parent is not None and not isinstance(node.parent, model.Namespace): |
| 26 return '-'.join([prefix, node.parent.simple_name, node.simple_name]) |
| 27 return '-'.join([prefix, node.simple_name]) |
| 28 |
| 24 def _FormatValue(value): | 29 def _FormatValue(value): |
| 25 """Inserts commas every three digits for integer values. It is magic. | 30 """Inserts commas every three digits for integer values. It is magic. |
| 26 """ | 31 """ |
| 27 s = str(value) | 32 s = str(value) |
| 28 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) | 33 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) |
| 29 | 34 |
| 30 class HandlebarDictGenerator(object): | 35 class HandlebarDictGenerator(object): |
| 31 """Uses a Model from the JSON Schema Compiler and generates a dict that | 36 """Uses a Model from the JSON Schema Compiler and generates a dict that |
| 32 a Handlebar template can use for a data source. | 37 a Handlebar template can use for a data source. |
| 33 """ | 38 """ |
| 34 def __init__(self, json): | 39 def __init__(self, json): |
| 35 clean_json = copy.deepcopy(json) | 40 clean_json = copy.deepcopy(json) |
| 36 if _RemoveNoDocs(clean_json): | 41 if _RemoveNoDocs(clean_json): |
| 37 self._namespace = None | 42 self._namespace = None |
| 38 else: | 43 else: |
| 39 self._namespace = model.Namespace(clean_json, clean_json['namespace']) | 44 self._namespace = model.Namespace(clean_json, clean_json['namespace']) |
| 40 | 45 |
| 41 def _StripPrefix(self, name): | |
| 42 if name.startswith(self._namespace.name + '.'): | |
| 43 return name[len(self._namespace.name + '.'):] | |
| 44 return name | |
| 45 | |
| 46 def _FormatDescription(self, description): | 46 def _FormatDescription(self, description): |
| 47 if description is None or '$ref:' not in description: | 47 if description is None or '$ref:' not in description: |
| 48 return description | 48 return description |
| 49 refs = description.split('$ref:') | 49 refs = description.split('$ref:') |
| 50 formatted_description = [refs[0]] | 50 formatted_description = [refs[0]] |
| 51 for ref in refs[1:]: | 51 for ref in refs[1:]: |
| 52 parts = ref.split(' ', 1) | 52 parts = ref.split(' ', 1) |
| 53 if len(parts) == 1: | 53 if len(parts) == 1: |
| 54 ref = parts[0] | 54 ref = parts[0] |
| 55 rest = '' | 55 rest = '' |
| 56 else: | 56 else: |
| 57 ref, rest = parts | 57 ref, rest = parts |
| 58 rest = ' ' + rest | 58 rest = ' ' + rest |
| 59 if not ref[-1].isalnum(): | 59 if not ref[-1].isalnum(): |
| 60 rest = ref[-1] + rest | 60 rest = ref[-1] + rest |
| 61 ref = ref[:-1] | 61 ref = ref[:-1] |
| 62 ref_dict = GetLinkToRefType(self._namespace.name, ref) | 62 ref_dict = GetLinkToRefType(self._namespace.name, ref) |
| 63 formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' % | 63 formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' % |
| 64 { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest }) | 64 { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest }) |
| 65 return ''.join(formatted_description) | 65 return ''.join(formatted_description) |
| 66 | 66 |
| 67 def Generate(self): | 67 def Generate(self): |
| 68 if self._namespace is None: | 68 if self._namespace is None: |
| 69 return {} | 69 return {} |
| 70 return { | 70 return { |
| 71 'name': self._namespace.name, | 71 'name': self._namespace.name, |
| 72 'types': map(self._GenerateType, self._namespace.types.values()), | 72 'types': [self._GenerateType(t) for t in self._namespace.types.values() |
| 73 if t.type_ != model.PropertyType.ADDITIONAL_PROPERTIES], |
| 73 'functions': self._GenerateFunctions(self._namespace.functions), | 74 'functions': self._GenerateFunctions(self._namespace.functions), |
| 74 'events': map(self._GenerateEvent, self._namespace.events.values()), | 75 'events': self._GenerateEvents(self._namespace.events), |
| 75 'properties': self._GenerateProperties(self._namespace.properties) | 76 'properties': self._GenerateProperties(self._namespace.properties) |
| 76 } | 77 } |
| 77 | 78 |
| 78 def _GenerateType(self, type_): | 79 def _GenerateType(self, type_): |
| 79 type_dict = { | 80 type_dict = { |
| 80 'name': self._StripPrefix(type_.name), | 81 'name': type_.simple_name, |
| 81 'description': self._FormatDescription(type_.description), | 82 'description': self._FormatDescription(type_.description), |
| 82 'properties': self._GenerateProperties(type_.properties), | 83 'properties': self._GenerateProperties(type_.properties), |
| 83 'functions': self._GenerateFunctions(type_.functions), | 84 'functions': self._GenerateFunctions(type_.functions), |
| 84 'events': map(self._GenerateEvent, type_.events.values()) | 85 'events': self._GenerateEvents(type_.events), |
| 86 'id': _CreateId(type_, 'type') |
| 85 } | 87 } |
| 86 self._RenderTypeInformation(type_, type_dict) | 88 self._RenderTypeInformation(type_, type_dict) |
| 87 return type_dict | 89 return type_dict |
| 88 | 90 |
| 89 def _GenerateFunctions(self, functions): | 91 def _GenerateFunctions(self, functions): |
| 90 return map(self._GenerateFunction, functions.values()) | 92 return [self._GenerateFunction(f) for f in functions.values()] |
| 91 | 93 |
| 92 def _GenerateFunction(self, function): | 94 def _GenerateFunction(self, function): |
| 93 function_dict = { | 95 function_dict = { |
| 94 'name': function.name, | 96 'name': function.simple_name, |
| 95 'description': self._FormatDescription(function.description), | 97 'description': self._FormatDescription(function.description), |
| 96 'callback': self._GenerateCallback(function.callback), | 98 'callback': self._GenerateCallback(function.callback), |
| 97 'parameters': [], | 99 'parameters': [], |
| 98 'returns': None | 100 'returns': None, |
| 101 'id': _CreateId(function, 'method') |
| 99 } | 102 } |
| 103 if (function.parent is not None and |
| 104 not isinstance(function.parent, model.Namespace)): |
| 105 function_dict['parent_name'] = function.parent.simple_name |
| 106 else: |
| 107 function_dict['parent_name'] = None |
| 100 if function.returns: | 108 if function.returns: |
| 101 function_dict['returns'] = self._GenerateProperty(function.returns) | 109 function_dict['returns'] = self._GenerateProperty(function.returns) |
| 102 for param in function.params: | 110 for param in function.params: |
| 103 function_dict['parameters'].append(self._GenerateProperty(param)) | 111 function_dict['parameters'].append(self._GenerateProperty(param)) |
| 104 if function_dict['callback']: | 112 if function_dict['callback']: |
| 105 function_dict['parameters'].append(function_dict['callback']) | 113 function_dict['parameters'].append(function_dict['callback']) |
| 106 if len(function_dict['parameters']) > 0: | 114 if len(function_dict['parameters']) > 0: |
| 107 function_dict['parameters'][-1]['last'] = True | 115 function_dict['parameters'][-1]['last'] = True |
| 108 return function_dict | 116 return function_dict |
| 109 | 117 |
| 118 def _GenerateEvents(self, events): |
| 119 return [self._GenerateEvent(e) for e in events.values()] |
| 120 |
| 110 def _GenerateEvent(self, event): | 121 def _GenerateEvent(self, event): |
| 111 event_dict = { | 122 event_dict = { |
| 112 'name': self._StripPrefix(event.name), | 123 'name': event.simple_name, |
| 113 'description': self._FormatDescription(event.description), | 124 'description': self._FormatDescription(event.description), |
| 114 'parameters': map(self._GenerateProperty, event.params), | 125 'parameters': map(self._GenerateProperty, event.params), |
| 115 'callback': self._GenerateCallback(event.callback), | 126 'callback': self._GenerateCallback(event.callback), |
| 116 'conditions': [GetLinkToRefType(self._namespace.name, c) | 127 'conditions': [GetLinkToRefType(self._namespace.name, c) |
| 117 for c in event.conditions], | 128 for c in event.conditions], |
| 118 'actions': [GetLinkToRefType(self._namespace.name, a) | 129 'actions': [GetLinkToRefType(self._namespace.name, a) |
| 119 for a in event.actions], | 130 for a in event.actions], |
| 120 'filters': map(self._GenerateProperty, event.filters), | 131 'filters': map(self._GenerateProperty, event.filters), |
| 121 'supportsRules': event.supports_rules | 132 'supportsRules': event.supports_rules, |
| 133 'id': _CreateId(event, 'event') |
| 122 } | 134 } |
| 135 if (event.parent is not None and |
| 136 not isinstance(event.parent, model.Namespace)): |
| 137 event_dict['parent_name'] = event.parent.simple_name |
| 138 else: |
| 139 event_dict['parent_name'] = None |
| 123 if event_dict['callback']: | 140 if event_dict['callback']: |
| 124 event_dict['parameters'].append(event_dict['callback']) | 141 event_dict['parameters'].append(event_dict['callback']) |
| 125 if len(event_dict['parameters']) > 0: | 142 if len(event_dict['parameters']) > 0: |
| 126 event_dict['parameters'][-1]['last'] = True | 143 event_dict['parameters'][-1]['last'] = True |
| 127 return event_dict | 144 return event_dict |
| 128 | 145 |
| 129 def _GenerateCallback(self, callback): | 146 def _GenerateCallback(self, callback): |
| 130 if not callback: | 147 if not callback: |
| 131 return None | 148 return None |
| 132 callback_dict = { | 149 callback_dict = { |
| 133 'name': callback.name, | 150 'name': callback.simple_name, |
| 134 'description': self._FormatDescription(callback.description), | 151 'description': self._FormatDescription(callback.description), |
| 135 'simple_type': {'simple_type': 'function'}, | 152 'simple_type': {'simple_type': 'function'}, |
| 136 'optional': callback.optional, | 153 'optional': callback.optional, |
| 137 'parameters': [] | 154 'parameters': [] |
| 138 } | 155 } |
| 139 for param in callback.params: | 156 for param in callback.params: |
| 140 callback_dict['parameters'].append(self._GenerateProperty(param)) | 157 callback_dict['parameters'].append(self._GenerateProperty(param)) |
| 141 if (len(callback_dict['parameters']) > 0): | 158 if (len(callback_dict['parameters']) > 0): |
| 142 callback_dict['parameters'][-1]['last'] = True | 159 callback_dict['parameters'][-1]['last'] = True |
| 143 return callback_dict | 160 return callback_dict |
| 144 | 161 |
| 145 def _GenerateProperties(self, properties): | 162 def _GenerateProperties(self, properties): |
| 146 return map(self._GenerateProperty, properties.values()) | 163 return [self._GenerateProperty(v) for v in properties.values() |
| 164 if v.type_ != model.PropertyType.ADDITIONAL_PROPERTIES] |
| 147 | 165 |
| 148 def _GenerateProperty(self, property_): | 166 def _GenerateProperty(self, property_): |
| 149 property_dict = { | 167 property_dict = { |
| 150 'name': self._StripPrefix(property_.name), | 168 'name': property_.simple_name, |
| 151 'optional': property_.optional, | 169 'optional': property_.optional, |
| 152 'description': self._FormatDescription(property_.description), | 170 'description': self._FormatDescription(property_.description), |
| 153 'properties': self._GenerateProperties(property_.properties), | 171 'properties': self._GenerateProperties(property_.properties), |
| 154 'functions': self._GenerateFunctions(property_.functions) | 172 'functions': self._GenerateFunctions(property_.functions), |
| 173 'id': _CreateId(property_, 'property') |
| 155 } | 174 } |
| 175 if (property_.parent is not None and |
| 176 not isinstance(property_.parent, model.Namespace)): |
| 177 property_dict['parent_name'] = property_.parent.simple_name |
| 178 else: |
| 179 property_dict['parent_name'] = None |
| 156 if property_.has_value: | 180 if property_.has_value: |
| 157 if isinstance(property_.value, int): | 181 if isinstance(property_.value, int): |
| 158 property_dict['value'] = _FormatValue(property_.value) | 182 property_dict['value'] = _FormatValue(property_.value) |
| 159 else: | 183 else: |
| 160 property_dict['value'] = property_.value | 184 property_dict['value'] = property_.value |
| 161 else: | 185 else: |
| 162 self._RenderTypeInformation(property_, property_dict) | 186 self._RenderTypeInformation(property_, property_dict) |
| 163 return property_dict | 187 return property_dict |
| 164 | 188 |
| 165 def _RenderTypeInformation(self, property_, dst_dict): | 189 def _RenderTypeInformation(self, property_, dst_dict): |
| 166 if property_.type_ == model.PropertyType.CHOICES: | 190 if property_.type_ == model.PropertyType.CHOICES: |
| 167 dst_dict['choices'] = map(self._GenerateProperty, | 191 dst_dict['choices'] = map(self._GenerateProperty, |
| 168 property_.choices.values()) | 192 property_.choices.values()) |
| 169 # We keep track of which is last for knowing when to add "or" between | 193 # We keep track of which is last for knowing when to add "or" between |
| 170 # choices in templates. | 194 # choices in templates. |
| 171 if len(dst_dict['choices']) > 0: | 195 if len(dst_dict['choices']) > 0: |
| 172 dst_dict['choices'][-1]['last'] = True | 196 dst_dict['choices'][-1]['last'] = True |
| 173 elif property_.type_ == model.PropertyType.ADDITIONAL_PROPERTIES: | |
| 174 dst_dict['additional_properties'] = True | |
| 175 elif property_.type_ == model.PropertyType.REF: | 197 elif property_.type_ == model.PropertyType.REF: |
| 176 dst_dict['link'] = GetLinkToRefType(self._namespace.name, | 198 dst_dict['link'] = GetLinkToRefType(self._namespace.name, |
| 177 property_.ref_type) | 199 property_.ref_type) |
| 178 elif property_.type_ == model.PropertyType.ARRAY: | 200 elif property_.type_ == model.PropertyType.ARRAY: |
| 179 dst_dict['array'] = self._GenerateProperty(property_.item_type) | 201 dst_dict['array'] = self._GenerateProperty(property_.item_type) |
| 180 elif property_.type_ == model.PropertyType.ENUM: | 202 elif property_.type_ == model.PropertyType.ENUM: |
| 181 dst_dict['enum_values'] = [] | 203 dst_dict['enum_values'] = [] |
| 182 for enum_value in property_.enum_values: | 204 for enum_value in property_.enum_values: |
| 183 dst_dict['enum_values'].append({'name': enum_value}) | 205 dst_dict['enum_values'].append({'name': enum_value}) |
| 184 if len(dst_dict['enum_values']) > 0: | 206 if len(dst_dict['enum_values']) > 0: |
| 185 dst_dict['enum_values'][-1]['last'] = True | 207 dst_dict['enum_values'][-1]['last'] = True |
| 186 elif property_.instance_of is not None: | 208 elif property_.instance_of is not None: |
| 187 dst_dict['simple_type'] = property_.instance_of.lower() | 209 dst_dict['simple_type'] = property_.instance_of.lower() |
| 188 else: | 210 else: |
| 189 dst_dict['simple_type'] = property_.type_.name.lower() | 211 dst_dict['simple_type'] = property_.type_.name.lower() |
| OLD | NEW |