def format_property_details(self, prop_name, prop_type, prop_description, enum, enum_details, supplemental_details, parent_prop_info, profile=None): """Generate a formatted table of enum information for inclusion in Property details.""" contents = [] parent_version = parent_prop_info.get('versionAdded') if parent_version: parent_version = self.format_version(parent_version) # Are we in profile mode? If so, consult the profile passed in for this property. # For Action Parameters, look for ParameterValues/RecommendedValues; for # Property enums, look for MinSupportValues/RecommendedValues. profile_mode = self.config.get('profile_mode') if profile_mode: if profile is None: profile = {} profile_values = profile.get('Values', []) profile_min_support_values = profile.get( 'MinSupportValues', []) # No longer a valid name? profile_parameter_values = profile.get('ParameterValues', []) profile_recommended_values = profile.get('RecommendedValues', []) # profile_all_values is not used. What were we going for here? profile_all_values = (profile_values + profile_min_support_values + profile_parameter_values + profile_recommended_values) # In subset mode, an action parameter with no Values (property) or ParameterValues (Action) # means all values are supported. # Otherwise, Values/ParameterValues specifies the set that should be listed. if profile_mode == 'subset': if len(profile_values): enum = [x for x in enum if x in profile_values] elif len(profile_parameter_values): enum = [x for x in enum if x in profile_parameter_values] if prop_description: contents.append( self.formatter.para( self.escape_for_markdown( prop_description, self.config.get('escape_chars', [])))) if isinstance(prop_type, list): prop_type = ', '.join(prop_type) if supplemental_details: contents.append('\n' + supplemental_details + '\n') enum_translations = parent_prop_info.get('enumTranslations', {}) if enum_details: if profile_mode and profile_mode != 'subset': contents.append('| ' + prop_type + ' | ' + _('Description') + ' | ' + _('Profile Specifies') + ' |') contents.append('| --- | --- | --- |') else: contents.append('| ' + prop_type + ' | ' + _('Description') + ' |') contents.append('| --- | --- |') enum.sort(key=str.lower) for enum_item in enum: enum_name = enum_item enum_translation = enum_translations.get(enum_item) version = version_depr = deprecated_descr = None version_display = None if parent_prop_info.get('enumVersionAdded'): version_added = parent_prop_info.get( 'enumVersionAdded').get(enum_name) if version_added: version = self.format_version(version_added) if parent_prop_info.get('enumVersionDeprecated'): version_deprecated = parent_prop_info.get( 'enumVersionDeprecated').get(enum_name) if version_deprecated: version_depr = self.format_version(version_deprecated) if parent_prop_info.get('enumDeprecated'): deprecated_descr = parent_prop_info.get( 'enumDeprecated').get(enum_name) if enum_translation: enum_name += ' (' + enum_translation + ')' if version: if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_display = self.truncate_version(version, 2) + '+' if version_display: if version_depr: deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( _('(v%(version_number)s, deprecated v%(deprecated_version)s)' ) % { 'version_number': version_display, 'deprecated_version': deprecated_display }) if deprecated_descr: deprecated_descr = (_( 'Deprecated in v%(version_number)s and later. %(explanation)s' ) % { 'version_number': deprecated_display, 'explanation': deprecated_descr }) else: enum_name += ' ' + self.formatter.italic( _('(v%(version_number)s)') % {'version_number': version_display}) elif version_depr: deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic( _('(deprecated v%(version_number)s)') % {'version_number': deprecated_display}) if deprecated_descr: deprecated_descr = (_( 'Deprecated in v%(version_number)s and later. %(explanation)s' ) % { 'version_number': deprecated_display, 'explanation': deprecated_descr }) descr = enum_details.get(enum_item, '') if deprecated_descr: if descr: descr += ' ' + self.formatter.italic(deprecated_descr) else: descr = self.formatter.italic(deprecated_descr) if profile_mode and profile_mode != 'subset': profile_spec = '' # Note: don't wrap the following strings for trnaslation; self.text_map handles that. if enum_item in profile_values: profile_spec = 'Mandatory' elif enum_item in profile_min_support_values: profile_spec = 'Mandatory' elif enum_item in profile_parameter_values: profile_spec = 'Mandatory' elif enum_item in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + descr + ' | ' + self.text_map(profile_spec) + ' |') else: contents.append('| ' + enum_name + ' | ' + descr + ' |') elif enum: if profile_mode and profile_mode != 'subset': contents.append('| ' + prop_type + ' | ' + _('Profile Specifies') + ' |') contents.append('| --- | --- |') else: contents.append('| ' + prop_type + ' |') contents.append('| --- |') for enum_item in enum: enum_name = enum_item version = version_depr = deprecated_descr = None version_display = None if parent_prop_info.get('enumVersionAdded'): version_added = parent_prop_info.get( 'enumVersionAdded').get(enum_name) if version_added: version = self.format_version(version_added) if parent_prop_info('enumVersionDeprecated'): version_deprecated = parent_prop_info.get( 'enumVersionDeprecated').get(enum_name) if version_deprecated: version_depr = self.format_version(version_deprecated) if parent_prop_info.get('enumDeprecated'): deprecated_descr = parent_prop_info.get( 'enumDeprecated').get(enum_name) if version: if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version( version_text, 2) + '+' if version_display: if version_depr: deprecated_display = self.truncate_version( version_depr, 2) if deprecated_descr: enum_name += ' ' + self.formatter.italic( _('(v%(version_number)s, deprecated v%(deprecated_version)s. %(explanation)s' ) % { 'version_number': version_display, 'deprecated_version': deprecated_display, 'explanation': deprecated_descr }) else: enum_name += ' ' + self.formatter.italic( _('(v%(version_number)s, deprecated v%(deprecated_version)s)' ) % { 'version_number': version_display, 'deprecated_version': deprecated_display }) else: enum_name += ' ' + self.formatter.italic( _('(v%(version_number)s)') % {'version_number': version_display}) else: if version_depr: deprecated_display = self.truncate_version( version_depr, 2) if deprecated_descr: enum_name += ' ' + self.formatter.italic( _('Deprecated in v%(deprecated_version)s and later. %(explanation)s' ) % { 'deprecated_version': deprecated_display, 'explanation': deprecated_descr }) else: enum_name += ' ' + self.formatter.italic( _('(deprecated in v%(deprecated_version)s and later.)' ) % {'deprecated_version': deprecated_display}) if profile_mode and profile_mode != 'subset': profile_spec = '' # Note: don't wrap the following strings for trnaslation; self.text_map handles that. if enum_name in profile_values: profile_spec = 'Mandatory' elif enum_name in profile_min_support_values: profile_spec = 'Mandatory' elif enum_name in profile_parameter_values: profile_spec = 'Mandatory' elif enum_name in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + self.text_map(profile_spec) + ' |') else: contents.append('| ' + enum_name + ' | ') caption = self.formatter.add_table_caption( _("%(prop_name)s property values") % {'prop_name': prop_name}) preamble = self.formatter.add_table_reference( _("The defined property values are listed in ")) return preamble + '\n'.join(contents) + '\n' + caption
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False): """Format information for a single property. Returns an object with 'row', 'details', 'action_details', and 'profile_conditional_details': 'row': content for the main table being generated. 'details': content for the Property Details section. 'action_details': content for the Actions section. 'profile_conditional_details': populated only in profile_mode, formatted conditional details This may include embedded objects with their own properties. """ traverser = self.traverser formatted = [] # The row itself current_depth = len(prop_path) if in_array: current_depth = current_depth - 1 # strip_top_object is used for fragments, to allow output of just the properties # without the enclosing object: if self.config.get('strip_top_object') and current_depth > 0: indentation_string = ' ' * 6 * (current_depth - 1) else: indentation_string = ' ' * 6 * current_depth # If prop_path starts with Actions and is more than 1 deep, we are outputting for an Action Details # section and should dial back the indentation by one level. if len(prop_path) > 1 and prop_path[0] == 'Actions': indentation_string = ' ' * 6 * (current_depth - 1) collapse_array = False # Should we collapse a list description into one row? For lists of simple types has_enum = False if current_depth < self.current_depth: for i in range(current_depth, self.current_depth): if i in self.current_version: del self.current_version[i] self.current_depth = current_depth parent_depth = current_depth - 1 if isinstance(prop_info, list): meta = prop_info[0].get('_doc_generator_meta') has_enum = 'enum' in prop_info[0] elif isinstance(prop_info, dict): meta = prop_info.get('_doc_generator_meta') has_enum = 'enum' in prop_info if not meta: meta = {} # We want to modify a local copy of meta, deleting redundant version info meta = copy.deepcopy(meta) name_and_version = self.formatter.bold(html.escape(prop_name, False)) deprecated_descr = None version = meta.get('version') self.current_version[current_depth] = version # Don't display version if there is a parent version and this is not newer: if self.current_version.get(parent_depth) and version: if DocGenUtilities.compare_versions( version, self.current_version.get(parent_depth)) <= 0: del meta['version'] if meta.get('version', '1.0.0') != '1.0.0': version_text = html.escape(meta['version'], False) version_display = self.truncate_version(version_text, 2) + '+' if 'version_deprecated' in meta: version_depr = html.escape(meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) name_and_version += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') deprecated_descr = html.escape( "Deprecated v" + deprecated_display + '+. ' + meta['version_deprecated_explanation'], False) else: name_and_version += ' ' + self.formatter.italic( '(v' + version_display + ')') elif 'version_deprecated' in meta: version_depr = html.escape(meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) name_and_version += ' ' + self.formatter.italic( '(deprecated v' + deprecated_display + ')') deprecated_descr = html.escape( "Deprecated v" + deprecated_display + '+. ' + meta['version_deprecated_explanation'], False) formatted_details = self.parse_property_info(schema_ref, prop_name, prop_info, prop_path, meta.get('within_action')) if formatted_details.get('promote_me'): return ({ 'row': '\n'.join(formatted_details['item_description']), 'details': formatted_details['prop_details'], 'action_details': formatted_details.get('action_details') }) if self.config.get('strip_top_object') and current_depth == 0: # In this case, we're done for this bit of documentation, and we just want the properties of this object. formatted.append('\n'.join( formatted_details['object_description'])) return ({ 'row': '\n'.join(formatted), 'details': formatted_details['prop_details'], 'action_details': formatted_details.get('action_details'), 'profile_conditional_details': formatted_details.get('profile_conditional_details') }) # Eliminate dups in these these properties and join with a delimiter: props = { 'prop_type': self.separators['inline'], 'descr': self.separators['linebreak'], 'object_description': '\n', 'item_description': '\n' } for property_name, delim in props.items(): if isinstance(formatted_details[property_name], list): property_values = [] self.append_unique_values(formatted_details[property_name], property_values) formatted_details[property_name] = delim.join(property_values) if formatted_details['prop_is_object'] and not in_array: if formatted_details['object_description'] == '': name_and_version += ' { }' else: name_and_version += ' {' if formatted_details['prop_is_array']: if formatted_details['item_description'] == '': if formatted_details['array_of_objects']: name_and_version += ' [ { } ]' else: name_and_version += ' [ ] ' else: if formatted_details['array_of_objects']: name_and_version += ' [ {' else: collapse_array = True name_and_version += ' [ ] ' elif in_array: if formatted_details['prop_is_object']: name_and_version += ' [ { } ]' else: name_and_version += ' [ ] ' name_and_version = '<nobr>' + name_and_version + '</nobr>' if formatted_details['descr'] is None: formatted_details['descr'] = '' formatted_details['descr'] = self.formatter.markdown_to_html( html.escape(formatted_details['descr'], False), no_para=True) if formatted_details['add_link_text']: if formatted_details['descr']: formatted_details['descr'] += ' ' formatted_details['descr'] += formatted_details['add_link_text'] # Append reference info to descriptions, if appropriate: if not formatted_details.get('fulldescription_override'): # If there are prop_details (enum details), add a note to the description: if formatted_details[ 'has_direct_prop_details'] and not formatted_details[ 'has_action_details']: if has_enum: anchor = schema_ref + '|details|' + prop_name text_descr = 'See <a href="#' + anchor + '">' + prop_name + '</a> in Property Details, below, for the possible values of this property.' else: text_descr = 'See Property Details, below, for more information about this property.' if formatted_details['descr']: formatted_details[ 'descr'] += '<br>' + self.formatter.italic(text_descr) else: formatted_details['descr'] = self.formatter.italic( text_descr) # If this is an Action with details, add a note to the description: if formatted_details['has_action_details']: anchor = schema_ref + '|action_details|' + prop_name text_descr = 'For more information, see the <a href="#' + anchor + '">Action Details</a> section below.' formatted_details['descr'] += '<br>' + self.formatter.italic( text_descr) if deprecated_descr: formatted_details['descr'] += ' ' + self.formatter.italic( deprecated_descr) prop_type = html.escape(formatted_details['prop_type'], False) if has_enum: prop_type += '<br>(enum)' if formatted_details['prop_units']: prop_type += '<br>(' + formatted_details['prop_units'] + ')' if in_array: prop_type = 'array (' + prop_type + ')' if collapse_array: item_list = formatted_details['item_list'] if len(item_list): if isinstance(item_list, list): item_list = ', '.join([html.escape(x) for x in item_list]) prop_type += '<br>(' + item_list + ')' prop_access = '' if not formatted_details['prop_is_object']: if formatted_details['read_only']: prop_access = '<nobr>read-only</nobr>' else: prop_access = '<nobr>read-write</nobr>' if formatted_details['prop_required_on_create']: prop_access += ' <nobr>required on create</nobr>' elif formatted_details['prop_required'] or formatted_details.get( 'required_parameter'): prop_access += ' <nobr>required</nobr>' if formatted_details['nullable']: prop_access += ' (null)' # If profile reqs are present, massage them: profile_access = self.format_base_profile_access(formatted_details) descr = formatted_details['descr'] if formatted_details['profile_purpose']: descr += '<br>' + self.formatter.bold( "Profile Purpose: " + formatted_details['profile_purpose']) # Conditional Requirements cond_req = formatted_details['profile_conditional_req'] if cond_req: anchor = schema_ref + '|conditional_reqs|' + prop_name cond_req_text = 'See <a href="#' + anchor + '"> Conditional Requirements</a>, below, for more information.' descr += ' ' + self.formatter.nobr( self.formatter.italic(cond_req_text)) profile_access += "<br>" + self.formatter.nobr( self.formatter.italic('Conditional Requirements')) if not profile_access: profile_access = ' ' * 10 # Comparison if formatted_details['profile_values']: comparison_descr = ( 'Must be ' + formatted_details['profile_comparison'] + ' (' + ', '.join('"' + x + '"' for x in formatted_details['profile_values']) + ')') profile_access += '<br>' + self.formatter.italic(comparison_descr) row = [] row.append(indentation_string + name_and_version) if self.config.get('profile_mode'): row.append(profile_access) row.append(prop_type) if not self.config.get('profile_mode'): row.append(prop_access) row.append(descr) formatted.append(self.formatter.make_row(row)) if len(formatted_details['object_description']) > 0: formatted_object = formatted_details['object_description'] # Add a closing } to the last row of this object. formatted_object = self._add_closing_brace(formatted_object, indentation_string, '}') formatted.append(formatted_object) if not collapse_array and len( formatted_details['item_description']) > 0: formatted_array = formatted_details['item_description'] # Add closing }] or ] to the last row of this array: if formatted_details['array_of_objects']: formatted_array = self._add_closing_brace( formatted_array, indentation_string, '} ]') else: formatted_array = self._add_closing_brace( formatted_array, indentation_string, ']') formatted.append(formatted_array) return ({ 'row': '\n'.join(formatted), 'details': formatted_details['prop_details'], 'action_details': formatted_details.get('action_details'), 'profile_conditional_details': formatted_details.get('profile_conditional_details') })
def format_property_details(self, prop_name, prop_type, prop_description, enum, enum_details, supplemental_details, meta, anchor=None, profile=None): """Generate a formatted table of enum information for inclusion in Property Details.""" contents = [] contents.append( self.formatter.head_four( html.escape(prop_name, False) + ':', self.level, anchor)) parent_version = meta.get('version') enum_meta = meta.get('enum', {}) # Are we in profile mode? If so, consult the profile passed in for this property. # For Action Parameters, look for ParameterValues/RecommendedValues; for # Property enums, look for MinSupportValues/RecommendedValues. profile_mode = self.config.get('profile_mode') if profile_mode: if profile is None: profile = {} profile_values = profile.get('Values', []) profile_min_support_values = profile.get('MinSupportValues', []) profile_parameter_values = profile.get('ParameterValues', []) profile_recommended_values = profile.get('RecommendedValues', []) profile_all_values = (profile_values + profile_min_support_values + profile_parameter_values + profile_recommended_values) if prop_description: contents.append(self.formatter.para(prop_description)) if isinstance(prop_type, list): prop_type = ', '.join([html.escape(x, False) for x in prop_type]) else: prop_type = html.escape(prop_type, False) if supplemental_details: contents.append( self.formatter.markdown_to_html(supplemental_details)) if enum_details: headings = [prop_type, 'Description'] if profile_mode: headings.append('Profile Specifies') header_row = self.formatter.make_header_row(headings) table_rows = [] enum.sort(key=str.lower) for enum_item in enum: enum_name = html.escape(enum_item, False) enum_item_meta = enum_meta.get(enum_item, {}) version_display = None deprecated_descr = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version( version_text, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = html.escape( enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get( 'version_deprecated_explanation'): deprecated_descr = html.escape( 'Deprecated v' + deprecated_display + '+. ' + enum_item_meta[ 'version_deprecated_explanation'], False) else: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ')') elif 'version_deprecated' in enum_item_meta: version_depr = html.escape( enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic( '(deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): deprecated_descr = html.escape( 'Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation'], False) descr = html.escape(enum_details.get(enum_item, ''), False) if deprecated_descr: if descr: descr += ' ' + self.formatter.italic(deprecated_descr) else: descr = self.formatter.italic(deprecated_descr) cells = [enum_name, descr] if profile_mode: if enum_name in profile_values: cells.append('Required') elif enum_name in profile_min_support_values: cells.append('Required') elif enum_name in profile_parameter_values: cells.append('Required') elif enum_name in profile_recommended_values: cells.append('Recommended') else: cells.append('') table_rows.append(self.formatter.make_row(cells)) contents.append( self.formatter.make_table(table_rows, [header_row], 'enum enum-details')) elif enum: headings = [prop_type] if profile_mode: headings.append('Profile Specifies') header_row = self.formatter.make_header_row(headings) table_rows = [] enum.sort(key=str.lower) for enum_item in enum: enum_name = html.escape(enum_item, False) enum_item_meta = enum_meta.get(enum_item, {}) version_display = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version( version_text, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = html.escape( enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get( 'version_deprecated_explanation'): enum_name += '<br>' + self.formatter.italic( html.escape( 'Deprecated v' + deprecated_display + '+. ' + enum_item_meta[ 'version_deprecated_explanation'], False)) else: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ')') elif 'version_deprecated' in enum_item_meta: version_depr = html.escape( enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic( '(deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): enum_name += '<br>' + self.formatter.italic( html.escape( 'Deprecated v' + deprecated_display + '+. ' + enum_item_meta[ 'version_deprecated_explanation'], False)) cells = [enum_name] if profile_mode: if enum_name in profile_values: cells.append('Required') elif enum_name in profile_min_support_values: cells.append('Required') elif enum_name in profile_parameter_values: cells.append('Required') elif enum_name in profile_recommended_values: cells.append('Recommended') else: cells.append('') table_rows.append(self.formatter.make_row(cells)) contents.append( self.formatter.make_table(table_rows, [header_row], 'enum')) return '\n'.join(contents) + '\n'
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False): """Format information for a single property. Returns an object with 'row', 'details', 'action_details', and 'profile_conditional_details': 'row': content for the main table being generated. 'details': content for the Property Details section. 'action_details': content for the Actions section. 'profile_conditional_details': populated only in profile_mode, formatted conditional details This may include embedded objects with their own properties. """ traverser = self.traverser formatted = [] # The row itself current_depth = len(prop_path) if in_array: current_depth = current_depth -1 # strip_top_object is used for fragments, to allow output of just the properties # without the enclosing object: if self.config.get('strip_top_object') and current_depth > 0: indentation_string = ' ' * 6 * (current_depth -1) else: indentation_string = ' ' * 6 * current_depth # If prop_path starts with Actions and is more than 1 deep, we are outputting for an Actions # section and should dial back the indentation by one level. if len(prop_path) > 1 and prop_path[0] == 'Actions': indentation_string = ' ' * 6 * (current_depth -1) collapse_array = False # Should we collapse a list description into one row? For lists of simple types has_enum = False if current_depth < self.current_depth: for i in range(current_depth, self.current_depth): if i in self.current_version: del self.current_version[i] self.current_depth = current_depth parent_depth = current_depth - 1 if isinstance(prop_info, list): meta = prop_info[0].get('_doc_generator_meta') has_enum = 'enum' in prop_info[0] is_excerpt = prop_info[0].get('_is_excerpt') or prop_info[0].get('excerptCopy') elif isinstance(prop_info, dict): meta = prop_info.get('_doc_generator_meta') has_enum = 'enum' in prop_info is_excerpt = prop_info.get('_is_excerpt') if not meta: meta = {} # We want to modify a local copy of meta, deleting redundant version info meta = copy.deepcopy(meta) name_and_version = self.formatter.bold(html.escape(prop_name, False)) deprecated_descr = None version = meta.get('version') self.current_version[current_depth] = version # Don't display version if there is a parent version and this is not newer: if self.current_version.get(parent_depth) and version: if DocGenUtilities.compare_versions(version, self.current_version.get(parent_depth)) <= 0: del meta['version'] if meta.get('version', '1.0.0') != '1.0.0': version_text = html.escape(meta['version'], False) version_display = self.truncate_version(version_text, 2) + '+' if 'version_deprecated' in meta: version_depr = html.escape(meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) name_and_version += ' ' + self.formatter.italic('(v' + version_display + ', deprecated v' + deprecated_display + ')') deprecated_descr = html.escape("Deprecated v" + deprecated_display + '+. ' + meta['version_deprecated_explanation'], False) else: name_and_version += ' ' + self.formatter.italic('(v' + version_display + ')') elif 'version_deprecated' in meta: version_depr = html.escape(meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) name_and_version += ' ' + self.formatter.italic('(deprecated v' + deprecated_display + ')') deprecated_descr = html.escape( "Deprecated v" + deprecated_display + '+. ' + meta['version_deprecated_explanation'], False) formatted_details = self.parse_property_info(schema_ref, prop_name, prop_info, prop_path, meta.get('within_action')) if formatted_details.get('promote_me'): return({'row': '\n'.join(formatted_details['item_description']), 'details':formatted_details['prop_details'], 'action_details':formatted_details.get('action_details')}) if self.config.get('strip_top_object') and current_depth == 0: # In this case, we're done for this bit of documentation, and we just want the properties of this object. formatted.append('\n'.join(formatted_details['object_description'])) return({'row': '\n'.join(formatted), 'details':formatted_details['prop_details'], 'action_details':formatted_details.get('action_details'), 'profile_conditional_details':formatted_details.get('profile_conditional_details')}) # Eliminate dups in these these properties and join with a delimiter: props = { 'prop_type': self.separators['inline'], 'descr': self.separators['linebreak'], 'object_description': '\n', 'item_description': '\n' } for property_name, delim in props.items(): if isinstance(formatted_details[property_name], list): property_values = [] self.append_unique_values(formatted_details[property_name], property_values) formatted_details[property_name] = delim.join(property_values) if formatted_details['prop_is_object'] and not in_array: if formatted_details['object_description'] == '': name_and_version += ' { }' else: name_and_version += ' {' if formatted_details['prop_is_array']: if formatted_details['item_description'] == '': if formatted_details['array_of_objects']: name_and_version += ' [ { } ]' else: name_and_version += ' [ ] ' else: if formatted_details['array_of_objects']: name_and_version += ' [ {' else: collapse_array = True name_and_version += ' [ ] ' elif in_array: if formatted_details['prop_is_object']: name_and_version += ' [ { } ]' else: name_and_version += ' [ ] ' name_and_version = '<nobr>' + name_and_version + '</nobr>' if formatted_details['descr'] is None: formatted_details['descr'] = '' if not formatted_details.get('verbatim_description', False): formatted_details['descr'] = self.formatter.markdown_to_html(html.escape(formatted_details['descr'], False), no_para=True) if formatted_details['add_link_text']: if formatted_details['descr']: formatted_details['descr'] += self.formatter.br() formatted_details['descr'] += self.formatter.italic(formatted_details['add_link_text']) # Append reference info to descriptions, if appropriate: if not formatted_details.get('fulldescription_override'): # If there are prop_details (enum details), add a note to the description: if formatted_details['has_direct_prop_details'] and not formatted_details['has_action_details']: if has_enum: anchor = schema_ref + '|details|' + prop_name text_descr = 'See <a href="#' + anchor + '">' + prop_name + '</a> in Property Details, below, for the possible values of this property.' else: text_descr = 'See Property Details, below, for more information about this property.' if formatted_details['descr']: formatted_details['descr'] += '<br>' + self.formatter.italic(text_descr) else: formatted_details['descr'] = self.formatter.italic(text_descr) # If this is an Action with details, add a note to the description: if formatted_details['has_action_details']: anchor = schema_ref + '|action_details|' + prop_name text_descr = 'For more information, see the <a href="#' + anchor + '">Actions</a> section below.' formatted_details['descr'] += '<br>' + self.formatter.italic(text_descr) if deprecated_descr: formatted_details['descr'] += ' ' + self.formatter.italic(deprecated_descr) prop_type = html.escape(formatted_details['prop_type'], False) if has_enum: prop_type += '<br>(enum)' if formatted_details['prop_units']: prop_type += '<br>(' + formatted_details['prop_units'] + ')' if is_excerpt: prop_type += '<br>(excerpt)' if in_array: prop_type = 'array (' + prop_type + ')' if collapse_array: item_list = formatted_details['item_list'] if len(item_list): if isinstance(item_list, list): item_list = ', '.join([html.escape(x) for x in item_list]) prop_type += '<br>(' + item_list + ')' prop_access = '' if not meta.get('is_pattern') and not formatted_details['prop_is_object']: if formatted_details['read_only']: prop_access = '<nobr>read-only</nobr>' else: prop_access = '<nobr>read-write</nobr>' if formatted_details['prop_required'] or formatted_details.get('required_parameter'): prop_access += ' <nobr>required</nobr>' elif formatted_details['prop_required_on_create']: prop_access += ' <nobr>required on create</nobr>' if formatted_details['nullable']: prop_access += ' (null)' # If profile reqs are present, massage them: profile_access = self.format_base_profile_access(formatted_details) descr = formatted_details['descr'] if formatted_details['profile_purpose']: descr += '<br>' + self.formatter.bold("Profile Purpose: " + formatted_details['profile_purpose']) # Conditional Requirements cond_req = formatted_details['profile_conditional_req'] if cond_req: anchor = schema_ref + '|conditional_reqs|' + prop_name cond_req_text = 'See <a href="#' + anchor + '"> Conditional Requirements</a>, below, for more information.' descr += ' ' + self.formatter.nobr(self.formatter.italic(cond_req_text)) profile_access += "<br>" + self.formatter.nobr(self.formatter.italic('Conditional Requirements')) if not profile_access: profile_access = ' ' * 10 # Comparison if formatted_details['profile_values']: comparison_descr = ('Must be ' + formatted_details['profile_comparison'] + ' (' + ', '.join('"' + x + '"' for x in formatted_details['profile_values']) + ')') profile_access += '<br>' + self.formatter.italic(comparison_descr) row = [] row.append(indentation_string + name_and_version) if self.config.get('profile_mode'): row.append(profile_access) row.append(prop_type) if not self.config.get('profile_mode'): row.append(prop_access) row.append(descr) formatted.append(self.formatter.make_row(row)) if len(formatted_details['object_description']) > 0: formatted_object = formatted_details['object_description'] # Add a closing } to the last row of this object. formatted_object = self._add_closing_brace(formatted_object, indentation_string, '}') formatted.append(formatted_object) if not collapse_array and len(formatted_details['item_description']) > 0: formatted_array = formatted_details['item_description'] # Add closing }] or ] to the last row of this array: if formatted_details['array_of_objects']: formatted_array = self._add_closing_brace(formatted_array, indentation_string, '} ]') else: formatted_array = self._add_closing_brace(formatted_array, indentation_string, ']') formatted.append(formatted_array) return({'row': '\n'.join(formatted), 'details':formatted_details['prop_details'], 'action_details':formatted_details.get('action_details'), 'profile_conditional_details':formatted_details.get('profile_conditional_details')})
def format_property_details(self, prop_name, prop_type, prop_description, enum, enum_details, supplemental_details, meta, anchor=None, profile=None): """Generate a formatted table of enum information for inclusion in Property Details.""" contents = [] contents.append(self.formatter.head_four(html.escape(prop_name, False) + ':', self.level, anchor)) parent_version = meta.get('version') enum_meta = meta.get('enum', {}) # Are we in profile mode? If so, consult the profile passed in for this property. # For Action Parameters, look for ParameterValues/RecommendedValues; for # Property enums, look for MinSupportValues/RecommendedValues. profile_mode = self.config.get('profile_mode') if profile_mode: if profile is None: profile = {} profile_values = profile.get('Values', []) profile_min_support_values = profile.get('MinSupportValues', []) profile_parameter_values = profile.get('ParameterValues', []) profile_recommended_values = profile.get('RecommendedValues', []) profile_all_values = (profile_values + profile_min_support_values + profile_parameter_values + profile_recommended_values) if prop_description: contents.append(self.formatter.para(prop_description)) if isinstance(prop_type, list): prop_type = ', '.join([html.escape(x, False) for x in prop_type]) else: prop_type = html.escape(prop_type, False) if supplemental_details: contents.append(self.formatter.markdown_to_html(supplemental_details)) if enum_details: headings = [prop_type, 'Description'] if profile_mode: headings.append('Profile Specifies') header_row = self.formatter.make_header_row(headings) table_rows = [] enum.sort(key=str.lower) for enum_item in enum: enum_name = html.escape(enum_item, False) enum_item_meta = enum_meta.get(enum_item, {}) version_display = None deprecated_descr = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions(version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version(version_text, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = html.escape(enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): deprecated_descr = html.escape('Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation'], False) else: enum_name += ' ' + self.formatter.italic('(v' + version_display + ')') elif 'version_deprecated' in enum_item_meta: version_depr = html.escape(enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): deprecated_descr = html.escape('Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation'], False) descr = html.escape(enum_details.get(enum_item, ''), False) if deprecated_descr: if descr: descr += ' ' + self.formatter.italic(deprecated_descr) else: descr = self.formatter.italic(deprecated_descr) cells = [enum_name, descr] if profile_mode: if enum_name in profile_values: cells.append('Required') elif enum_name in profile_min_support_values: cells.append('Required') elif enum_name in profile_parameter_values: cells.append('Required') elif enum_name in profile_recommended_values: cells.append('Recommended') else: cells.append('') table_rows.append(self.formatter.make_row(cells)) contents.append(self.formatter.make_table(table_rows, [header_row], 'enum enum-details')) elif enum: headings = [prop_type] if profile_mode: headings.append('Profile Specifies') header_row = self.formatter.make_header_row(headings) table_rows = [] enum.sort(key=str.lower) for enum_item in enum: enum_name = html.escape(enum_item, False) enum_item_meta = enum_meta.get(enum_item, {}) version_display = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions(version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version(version_text, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = html.escape(enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): enum_name += '<br>' + self.formatter.italic(html.escape('Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation'], False)) else: enum_name += ' ' + self.formatter.italic('(v' + version_display + ')') elif 'version_deprecated' in enum_item_meta: version_depr = html.escape(enum_item_meta['version_deprecated'], False) deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): enum_name += '<br>' + self.formatter.italic(html.escape('Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation'], False)) cells = [enum_name] if profile_mode: if enum_name in profile_values: cells.append('Required') elif enum_name in profile_min_support_values: cells.append('Required') elif enum_name in profile_parameter_values: cells.append('Required') elif enum_name in profile_recommended_values: cells.append('Recommended') else: cells.append('') table_rows.append(self.formatter.make_row(cells)) contents.append(self.formatter.make_table(table_rows, [header_row], 'enum')) return '\n'.join(contents) + '\n'
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False): """Format information for a single property. Returns an object with 'row', 'details', 'action_details', and 'profile_conditional_details': 'row': content for the main table being generated. 'details': content for the Property details section. 'action_details': content for the Actions section. 'profile_conditional_details': populated only in profile_mode, formatted conditional details This may include embedded objects with their own properties. """ traverser = self.traverser formatted = [] # The row itself within_action = prop_path == ['Actions'] current_depth = len(prop_path) if in_array: current_depth = current_depth - 1 # strip_top_object is used for fragments, to allow output of just the properties # without the enclosing object: if self.config.get('strip_top_object') and current_depth > 0: indentation_string = ' ' * 6 * (current_depth - 1) else: indentation_string = ' ' * 6 * current_depth # If prop_path starts with Actions and is more than 1 deep, we are outputting for an Actions # section and should dial back the indentation by one level. if len(prop_path) > 1 and prop_path[0] == 'Actions': indentation_string = ' ' * 6 * (current_depth - 1) collapse_array = False # Should we collapse a list description into one row? For lists of simple types has_enum = False if current_depth < self.current_depth: for i in range(current_depth, self.current_depth): if i in self.current_version: del self.current_version[i] self.current_depth = current_depth parent_depth = current_depth - 1 version_added = None version_deprecated = None version_deprecated_explanation = '' if isinstance(prop_info, list): version_added = prop_info[0].get('versionAdded') version_deprecated = prop_info[0].get('versionDeprecated') version_deprecated_explanation = prop_info[0].get('deprecated') has_enum = 'enum' in prop_info[0] is_excerpt = prop_info[0].get('_is_excerpt') or prop_info[0].get( 'excerptCopy') elif isinstance(prop_info, dict): version_added = prop_info.get('versionAdded') version_deprecated = prop_info.get('versionDeprecated') version_deprecated_explanation = prop_info.get('deprecated') has_enum = 'enum' in prop_info is_excerpt = prop_info[0].get('_is_excerpt') if prop_name: name_and_version = self.formatter.bold( self.escape_for_markdown(prop_name, self.config.get('escape_chars', []))) else: name_and_version = '' deprecated_descr = None version = None if version_added: version = self.format_version(version_added) if version_deprecated: version_depr = self.format_version(version_deprecated) self.current_version[current_depth] = version # Don't display version if there is a parent version and this is not newer: if version and self.current_version.get(parent_depth): if DocGenUtilities.compare_versions( version, self.current_version.get(parent_depth)) <= 0: version = None if version and version != '1.0.0': version_display = self.truncate_version(version, 2) + '+' if version_deprecated: deprecated_display = self.truncate_version(version_depr, 2) name_and_version += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') deprecated_descr = ("Deprecated in v" + deprecated_display + ' and later. ' + self.escape_for_markdown( version_deprecated_explanation, self.config.get('escape_chars', []))) else: name_and_version += ' ' + self.formatter.italic( '(v' + version_display + ')') elif version_deprecated: deprecated_display = self.truncate_version(version_depr, 2) name_and_version += ' ' + self.formatter.italic( '(deprecated v' + deprecated_display + ')') deprecated_descr = ( "Deprecated in v" + deprecated_display + ' and later. ' + self.escape_for_markdown(version_deprecated_explanation, self.config.get('escape_chars', []))) formatted_details = self.parse_property_info(schema_ref, prop_name, prop_info, prop_path) if formatted_details.get('promote_me'): return ({ 'row': '\n'.join(formatted_details['item_description']), 'details': formatted_details['prop_details'], 'action_details': formatted_details.get('action_details') }) if self.config.get('strip_top_object') and current_depth == 0: # In this case, we're done for this bit of documentation, and we just want the properties of this object. formatted.append('\n'.join( formatted_details['object_description'])) return ({ 'row': '\n'.join(formatted), 'details': formatted_details['prop_details'], 'action_details': formatted_details.get('action_details'), 'profile_conditional_details': formatted_details.get('profile_conditional_details') }) # Eliminate dups in these these properties and join with a delimiter: props = { 'prop_type': self.separators['inline'], 'descr': self.separators['linebreak'], 'object_description': self.separators['linebreak'], 'item_description': self.separators['linebreak'] } for property_name, delim in props.items(): if isinstance(formatted_details[property_name], list): property_values = [] self.append_unique_values(formatted_details[property_name], property_values) formatted_details[property_name] = delim.join(property_values) if formatted_details['prop_is_object'] and not in_array: if formatted_details['object_description'] == '': name_and_version += ' {}' else: name_and_version += ' {' if formatted_details['prop_is_array']: if formatted_details['item_description'] == '': if formatted_details['array_of_objects']: name_and_version += ' [ {} ]' else: name_and_version += ' [ ]' else: if formatted_details['array_of_objects']: name_and_version += ' [ {' else: collapse_array = True name_and_version += ' [ ]' elif in_array: if formatted_details['prop_is_object']: name_and_version += ' [ { } ]' else: name_and_version += ' [ ]' if formatted_details['descr'] is None: formatted_details['descr'] = '' if formatted_details['profile_purpose'] and ( self.config.get('profile_mode') != 'subset'): if formatted_details['descr']: formatted_details['descr'] += ' ' formatted_details['descr'] += self.formatter.bold( formatted_details['profile_purpose']) if formatted_details['add_link_text']: if formatted_details['descr']: formatted_details['descr'] += ' ' formatted_details['descr'] += formatted_details['add_link_text'] # Append reference info to descriptions, if appropriate: if not formatted_details.get('fulldescription_override'): if formatted_details[ 'has_direct_prop_details'] and not formatted_details[ 'has_action_details']: # If there are prop_details (enum details), add a note to the description: if has_enum: text_descr = 'For the possible property values, see ' + prop_name + ' in Property details.' else: text_descr = 'For more information about this property, see Property details.' formatted_details['descr'] += ' ' + self.formatter.italic( text_descr) if formatted_details['has_action_details']: text_descr = 'For more information, see the Actions section below.' formatted_details['descr'] += ' ' + self.formatter.italic( text_descr) if deprecated_descr: formatted_details['descr'] += ' ' + self.formatter.italic( deprecated_descr) prop_type = formatted_details['prop_type'] if has_enum: prop_type += '<br>(enum)' if formatted_details['prop_units']: prop_type += '<br>(' + formatted_details['prop_units'] + ')' if is_excerpt: prop_type += '<br>(excerpt)' if in_array: prop_type = 'array (' + prop_type + ')' if collapse_array: item_list = formatted_details['item_list'] if len(item_list): if isinstance(item_list, list): item_list = ', '.join(item_list) prop_type += ' (' + item_list + ')' prop_access = '' if (not formatted_details['prop_is_object'] and not formatted_details.get('array_of_objects') and not as_action_parameters): if formatted_details['read_only']: prop_access = 'read-only' else: # Special case for subset mode; if profile indicates WriteRequirement === None (present and None), # emit read-only. if ((self.config.get('profile_mode') == 'subset') and formatted_details.get('profile_write_req') and (formatted_details['profile_write_req'] == 'None')): prop_access = 'read-only' else: prop_access = 'read-write' # Action parameters don't have read/write properties, but they can be required/optional. if as_action_parameters: if formatted_details['prop_required'] or formatted_details[ 'required_parameter']: prop_access = 'required' else: prop_access = 'optional' else: if formatted_details['prop_required'] or formatted_details[ 'required_parameter']: prop_access += ' required' elif formatted_details['prop_required_on_create']: prop_access += ' required on create' if formatted_details['nullable']: prop_access += '<br>(null)' # If profile reqs are present, massage them: profile_access = self.format_base_profile_access(formatted_details) if self.config.get('profile_mode' ) and self.config.get('profile_mode') != 'subset': if profile_access: prop_type += '<br><br>' + self.formatter.italic(profile_access) elif prop_access: prop_type += '<br><br>' + self.formatter.italic(prop_access) row = [] row.append(indentation_string + name_and_version) row.append(prop_type) row.append(formatted_details['descr']) formatted.append('| ' + ' | '.join(row) + ' |') if len(formatted_details['object_description']) > 0: formatted.append(formatted_details['object_description']) formatted.append('| ' + indentation_string + '} | | |') if not collapse_array and len( formatted_details['item_description']) > 0: formatted.append(formatted_details['item_description']) if formatted_details['array_of_objects']: formatted.append('| ' + indentation_string + '} ] | | |') else: formatted.append('| ' + indentation_string + '] | | |') return ({ 'row': '\n'.join(formatted), 'details': formatted_details['prop_details'], 'action_details': formatted_details.get('action_details'), 'profile_conditional_details': formatted_details.get('profile_conditional_details') })
def format_property_details(self, prop_name, prop_type, prop_description, enum, enum_details, supplemental_details, parent_prop_info, anchor=None, profile=None): """Generate a formatted table of enum information for inclusion in Property details.""" contents = [] contents.append(self.formatter.head_three(prop_name + ':', self.level)) parent_version = parent_prop_info.get('versionAdded') if parent_version: parent_version = self.format_version(parent_version) # Are we in profile mode? If so, consult the profile passed in for this property. # For Action Parameters, look for ParameterValues/RecommendedValues; for # Property enums, look for MinSupportValues/RecommendedValues. profile_mode = self.config.get('profile_mode') if profile_mode: if profile is None: profile = {} profile_values = profile.get('Values', []) profile_min_support_values = profile.get( 'MinSupportValues', []) # No longer a valid name? profile_parameter_values = profile.get('ParameterValues', []) profile_recommended_values = profile.get('RecommendedValues', []) # profile_all_values is not used. What were we going for here? profile_all_values = (profile_values + profile_min_support_values + profile_parameter_values + profile_recommended_values) # In subset mode, an action parameter with no Values (property) or ParameterValues (Action) # means all values are supported. # Otherwise, Values/ParameterValues specifies the set that should be listed. if profile_mode == 'subset': if len(profile_values): enum = [x for x in enum if x in profile_values] elif len(profile_parameter_values): enum = [x for x in enum if x in profile_parameter_values] if prop_description: contents.append( self.formatter.para( self.escape_for_markdown( prop_description, self.config.get('escape_chars', [])))) if isinstance(prop_type, list): prop_type = ', '.join(prop_type) if supplemental_details: contents.append('\n' + supplemental_details + '\n') if enum_details: if profile_mode and profile_mode != 'subset': contents.append('| ' + prop_type + ' | Description | Profile Specifies |') contents.append('| --- | --- | --- |') else: contents.append('| ' + prop_type + ' | Description |') contents.append('| --- | --- |') enum.sort(key=str.lower) for enum_item in enum: enum_name = enum_item version = version_depr = deprecated_descr = None version_display = None if parent_prop_info.get('enumVersionAdded'): version_added = parent_prop_info.get( 'enumVersionAdded').get(enum_name) if version_added: version = self.format_version(version_added) if parent_prop_info.get('enumVersionDeprecated'): version_deprecated = parent_prop_info.get( 'enumVersionDeprecated').get(enum_name) if version_deprecated: version_depr = self.format_version(version_deprecated) if parent_prop_info.get('enumDeprecated'): deprecated_descr = parent_prop_info.get( 'enumDeprecated').get(enum_name) if version: if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_display = self.truncate_version(version, 2) + '+' if version_display: if version_depr: deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') if deprecated_descr: deprecated_descr = 'Deprecated in v' + deprecated_display + ' and later. ' + deprecated_descr else: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ')') elif version_depr: deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic( '(deprecated v' + deprecated_display + ')') if deprecated_descr: deprecated_descr = 'Deprecated in v' + deprecated_display + ' and later. ' + deprecated_descr descr = enum_details.get(enum_item, '') if deprecated_descr: if descr: descr += ' ' + self.formatter.italic(deprecated_descr) else: descr = self.formatter.italic(deprecated_descr) if profile_mode and profile_mode != 'subset': profile_spec = '' if enum_name in profile_values: profile_spec = 'Required' elif enum_name in profile_min_support_values: profile_spec = 'Required' elif enum_name in profile_parameter_values: profile_spec = 'Required' elif enum_name in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + descr + ' | ' + profile_spec + ' |') else: contents.append('| ' + enum_name + ' | ' + descr + ' |') elif enum: if profile_mode and profile_mode != 'subset': contents.append('| ' + prop_type + ' | Profile Specifies |') contents.append('| --- | --- |') else: contents.append('| ' + prop_type + ' |') contents.append('| --- |') for enum_item in enum: enum_name = enum_item version = version_depr = deprecated_descr = None version_display = None if parent_prop_info.get('enumVersionAdded'): version_added = parent_prop_info.get( 'enumVersionAdded').get(enum_name) if version_added: version = self.format_version(version_added) if parent_prop_info('enumVersionDeprecated'): version_deprecated = parent_prop_info.get( 'enumVersionDeprecated').get(enum_name) if version_deprecated: version_depr = self.format_version(version_deprecated) if parent_prop_info.get('enumDeprecated'): deprecated_descr = parent_prop_info.get( 'enumDeprecated').get(enum_name) if version: if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version( version_text, 2) + '+' if version_display: if version_depr: deprecated_display = self.truncate_version( version_depr, 2) if deprecated_descr: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + '+. ' + deprecated_descr) else: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') else: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ')') else: if version_depr: deprecated_display = self.truncate_version( version_depr, 2) if deprecated_descr: enum_name += ' ' + self.formatter.italic( 'Deprecated in v' + deprecated_display + ' and later. ' + deprecated_descr) else: enum_name += ' ' + self.formatter.italic( '(deprecated in v' + deprecated_display + ' and later.)') if profile_mode and profile_mode != 'subset': profile_spec = '' if enum_name in profile_values: profile_spec = 'Required' elif enum_name in profile_min_support_values: profile_spec = 'Required' elif enum_name in profile_parameter_values: profile_spec = 'Required' elif enum_name in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + profile_spec + ' |') else: contents.append('| ' + enum_name + ' | ') return '\n'.join(contents) + '\n'
def format_property_details(self, prop_name, prop_type, prop_description, enum, enum_details, supplemental_details, meta, anchor=None, profile=None): """Generate a formatted table of enum information for inclusion in Property Details.""" contents = [] contents.append(self.formatter.head_three(prop_name + ':', self.level)) parent_version = meta.get('version') enum_meta = meta.get('enum', {}) # Are we in profile mode? If so, consult the profile passed in for this property. # For Action Parameters, look for ParameterValues/RecommendedValues; for # Property enums, look for MinSupportValues/RecommendedValues. profile_mode = self.config.get('profile_mode') if profile_mode: if profile is None: profile = {} profile_values = profile.get('Values', []) profile_min_support_values = profile.get('MinSupportValues', []) profile_parameter_values = profile.get('ParameterValues', []) profile_recommended_values = profile.get('RecommendedValues', []) profile_all_values = (profile_values + profile_min_support_values + profile_parameter_values + profile_recommended_values) if prop_description: contents.append( self.formatter.para( self.escape_for_markdown( prop_description, self.config.get('escape_chars', [])))) if isinstance(prop_type, list): prop_type = ', '.join(prop_type) if supplemental_details: contents.append('\n' + supplemental_details + '\n') if enum_details: if profile_mode: contents.append('| ' + prop_type + ' | Description | Profile Specifies |') contents.append('| --- | --- | --- |') else: contents.append('| ' + prop_type + ' | Description |') contents.append('| --- | --- |') enum.sort(key=str.lower) for enum_item in enum: enum_name = enum_item enum_item_meta = enum_meta.get(enum_item, {}) version_display = None deprecated_descr = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_display = self.truncate_version(version, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get( 'version_deprecated_explanation'): deprecated_descr = ( "Deprecated v" + deprecated_display + '+. ' + enum_item_meta[ 'version_deprecated_explanation']) else: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ')') else: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( '(deprecated v' + deprecated_display + ')') if enum_item_meta.get( 'version_deprecated_explanation'): deprecated_descr = ( "Deprecated v" + deprecated_display + '+. ' + enum_item_meta[ 'version_deprecated_explanation']) descr = enum_details.get(enum_item, '') if deprecated_descr: if descr: descr += ' ' + self.formatter.italic(deprecated_descr) else: descr = self.formatter.italic(deprecated_descr) if profile_mode: profile_spec = '' if enum_name in profile_values: profile_spec = 'Required' elif enum_name in profile_min_support_values: profile_spec = 'Required' elif enum_name in profile_parameter_values: profile_spec = 'Required' elif enum_name in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + descr + ' | ' + profile_spec + ' |') else: contents.append('| ' + enum_name + ' | ' + descr + ' |') elif enum: if profile_mode: contents.append('| ' + prop_type + ' | Profile Specifies |') contents.append('| --- | --- |') else: contents.append('| ' + prop_type + ' |') contents.append('| --- |') for enum_item in enum: enum_name = enum_item enum_item_meta = enum_meta.get(enum_item, {}) version_display = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions( version, parent_version) > 0: version_display = self.truncate_version(version, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( '(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get( 'version_deprecated_explanation'): deprecated_descr = ( 'Deprecated v' + deprecated_display + '+. ' + enum_item_meta[ 'version_deprecated_explanation']) else: enum_name += ' ' + self.formatter.italic( '(v' + version_display + ')') else: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version( version_depr, 2) enum_name += ' ' + self.formatter.italic( '(deprecated v' + deprecated_display + ')') if enum_item_meta.get( 'version_deprecated_explanation'): enum_name += ' ' + self.formatter.italic( 'Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation'] ) if profile_mode: profile_spec = '' if enum_name in profile_values: profile_spec = 'Required' elif enum_name in profile_min_support_values: profile_spec = 'Required' elif enum_name in profile_parameter_values: profile_spec = 'Required' elif enum_name in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + profile_spec + ' |') else: contents.append('| ' + enum_name + ' | ') return '\n'.join(contents) + '\n'
def format_property_details(self, prop_name, prop_type, prop_description, enum, enum_details, supplemental_details, parent_prop_info, profile=None): """Generate a formatted table of enum information for inclusion in Property details.""" contents = [] parent_version = parent_prop_info.get('versionAdded') if parent_version: parent_version = self.format_version(parent_version) # Are we in profile mode? If so, consult the profile passed in for this property. # For Action Parameters, look for ParameterValues/RecommendedValues; for # Property enums, look for MinSupportValues/RecommendedValues. profile_mode = self.config.get('profile_mode') if profile_mode: if profile is None: profile = {} profile_values = profile.get('Values', []) profile_min_support_values = profile.get('MinSupportValues', []) # No longer a valid name? profile_parameter_values = profile.get('ParameterValues', []) profile_recommended_values = profile.get('RecommendedValues', []) # profile_all_values is not used. What were we going for here? profile_all_values = (profile_values + profile_min_support_values + profile_parameter_values + profile_recommended_values) # In subset mode, an action parameter with no Values (property) or ParameterValues (Action) # means all values are supported. # Otherwise, Values/ParameterValues specifies the set that should be listed. if profile_mode == 'subset': if len(profile_values): enum = [x for x in enum if x in profile_values] elif len(profile_parameter_values): enum = [x for x in enum if x in profile_parameter_values] if prop_description: contents.append(self.formatter.para(prop_description)) if isinstance(prop_type, list): prop_type = ', '.join([html.escape(x, False) for x in prop_type]) else: prop_type = html.escape(prop_type, False) if supplemental_details: contents.append(self.formatter.markdown_to_html(supplemental_details)) if enum_details: headings = [prop_type, 'Description'] if profile_mode and profile_mode != 'subset': headings.append('Profile Specifies') header_row = self.formatter.make_header_row(headings) table_rows = [] enum.sort(key=str.lower) for enum_item in enum: enum_name = html.escape(enum_item, False) version = version_depr = deprecated_descr = None version_display = None if parent_prop_info.get('enumVersionAdded'): version_added = parent_prop_info.get('enumVersionAdded').get(enum_name) if version_added: version = self.format_version(version_added) if parent_prop_info.get('enumVersionDeprecated'): version_deprecated = parent_prop_info.get('enumVersionDeprecated').get(enum_name) if version_deprecated: version_depr = self.format_version(version_deprecated) if parent_prop_info.get('enumDeprecated'): deprecated_descr = parent_prop_info.get('enumDeprecated').get(enum_name) if version: if not parent_version or DocGenUtilities.compare_versions(version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version(version_text, 2) + '+' if version_display: if version_depr: version_depr_text = html.escape(version_depr, False) deprecated_display = self.truncate_version(version_depr_text, 2) enum_name += ' ' + self.formatter.italic('(v' + version_display + ', deprecated v' + deprecated_display + ')') if deprecated_descr: deprecated_descr_text = html.escape('Deprecated in v' + deprecated_display + ' and later. ' + deprecated_descr) else: enum_name += ' ' + self.formatter.italic('(v' + version_display + ')') elif version_depr: version_depr_text = html.escape(version_depr, False) deprecated_display = self.truncate_version(version_depr_text, 2) enum_name += ' ' + self.formatter.italic('(deprecated v' + deprecated_display + ')') if deprecated_descr: deprecated_descr_text = html.escape('Deprecated in v' + deprecated_display + ' and later. ' + deprecated_descr) descr = html.escape(enum_details.get(enum_item, ''), False) if deprecated_descr: if descr: descr += ' ' + self.formatter.italic(deprecated_descr) else: descr = self.formatter.italic(deprecated_descr) cells = [enum_name, descr] if profile_mode and profile_mode != 'subset': if enum_name in profile_values: cells.append('Mandatory') elif enum_name in profile_min_support_values: cells.append('Mandatory') elif enum_name in profile_parameter_values: cells.append('Mandatory') elif enum_name in profile_recommended_values: cells.append('Recommended') else: cells.append('') table_rows.append(self.formatter.make_row(cells)) contents.append(self.formatter.make_table(table_rows, [header_row], 'enum enum-details')) elif enum: headings = [prop_type] if profile_mode and profile_mode != 'subset': headings.append('Profile Specifies') header_row = self.formatter.make_header_row(headings) table_rows = [] enum.sort(key=str.lower) for enum_item in enum: enum_name = html.escape(enum_item, False) version = version_depr = deprecated_descr = None version_display = None if parent_prop_info.get('enumVersionAdded'): version_added = parent_prop_info.get('enumVersionAdded').get(enum_name) if version_added: version = self.format_version(version_added) if parent_prop_info('enumVersionDeprecated'): version_deprecated = parent_prop_info.get('enumVersionDeprecated').get(enum_name) if version_deprecated: version_depr = self.format_version(version_deprecated) if parent_prop_info.get('enumDeprecated'): deprecated_descr = parent_prop_info.get('enumDeprecated').get(enum_name) if version: if not parent_version or DocGenUtilities.compare_versions(version, parent_version) > 0: version_text = html.escape(version, False) version_display = self.truncate_version(version_text, 2) + '+' if version_display: if version_depr: version_depr_text = html.escape(version_depr, False) deprecated_display = self.truncate_version(version_depr_text, 2) enum_name += ' ' + self.formatter.italic('(v' + version_display + ', deprecated v' + deprecated_display + ')') if deprecated_descr: enum_name += '<br>' + self.formatter.italic(html.escape( 'Deprecated in v' + deprecated_display + ' and later. ' + deprecated_descr)) else: enum_name += ' ' + self.formatter.italic('(v' + version_display + ')') elif version_depr: version_depr_text = html.escape(version_depr, False) deprecated_display = self.truncate_version(version_depr_text, 2) enum_name += ' ' + self.formatter.italic('(deprecated v' + deprecated_display + ')') if deprecated_descr: enum_name += '<br>' + self.formatter.italic(html.escape( 'Deprecated in v' + deprecated_display + ' and later. ' + deprecated_descr)) cells = [enum_name] if profile_mode and profile_mode != 'subset': if enum_name in profile_values: cells.append('Mandatory') elif enum_name in profile_min_support_values: cells.append('Mandatory') elif enum_name in profile_parameter_values: cells.append('Mandatory') elif enum_name in profile_recommended_values: cells.append('Recommended') else: cells.append('') table_rows.append(self.formatter.make_row(cells)) contents.append(self.formatter.make_table(table_rows, [header_row], 'enum')) return '\n'.join(contents) + '\n'
def format_property_details(self, prop_name, prop_type, prop_description, enum, enum_details, supplemental_details, meta, anchor=None, profile=None): """Generate a formatted table of enum information for inclusion in Property Details.""" contents = [] contents.append(self.formatter.head_three(prop_name + ':', self.level)) parent_version = meta.get('version') enum_meta = meta.get('enum', {}) # Are we in profile mode? If so, consult the profile passed in for this property. # For Action Parameters, look for ParameterValues/RecommendedValues; for # Property enums, look for MinSupportValues/RecommendedValues. profile_mode = self.config.get('profile_mode') if profile_mode: if profile is None: profile = {} profile_values = profile.get('Values', []) profile_min_support_values = profile.get('MinSupportValues', []) profile_parameter_values = profile.get('ParameterValues', []) profile_recommended_values = profile.get('RecommendedValues', []) profile_all_values = (profile_values + profile_min_support_values + profile_parameter_values + profile_recommended_values) if prop_description: contents.append(self.formatter.para(self.escape_for_markdown(prop_description, self.config.get('escape_chars', [])))) if isinstance(prop_type, list): prop_type = ', '.join(prop_type) if supplemental_details: contents.append('\n' + supplemental_details + '\n') if enum_details: if profile_mode: contents.append('| ' + prop_type + ' | Description | Profile Specifies |') contents.append('| --- | --- | --- |') else: contents.append('| ' + prop_type + ' | Description |') contents.append('| --- | --- |') enum.sort(key=str.lower) for enum_item in enum: enum_name = enum_item enum_item_meta = enum_meta.get(enum_item, {}) version_display = None deprecated_descr = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions(version, parent_version) > 0: version_display = self.truncate_version(version, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): deprecated_descr = ("Deprecated v" + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation']) else: enum_name += ' ' + self.formatter.italic('(v' + version_display + ')') else: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): deprecated_descr = ("Deprecated v" + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation']) descr = enum_details.get(enum_item, '') if deprecated_descr: if descr: descr += ' ' + self.formatter.italic(deprecated_descr) else: descr = self.formatter.italic(deprecated_descr) if profile_mode: profile_spec = '' if enum_name in profile_values: profile_spec = 'Required' elif enum_name in profile_min_support_values: profile_spec = 'Required' elif enum_name in profile_parameter_values: profile_spec = 'Required' elif enum_name in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + descr + ' | ' + profile_spec + ' |') else: contents.append('| ' + enum_name + ' | ' + descr + ' |') elif enum: if profile_mode: contents.append('| ' + prop_type + ' | Profile Specifies |') contents.append('| --- | --- |') else: contents.append('| ' + prop_type + ' |') contents.append('| --- |') for enum_item in enum: enum_name = enum_item enum_item_meta = enum_meta.get(enum_item, {}) version_display = None if 'version' in enum_item_meta: version = enum_item_meta['version'] if not parent_version or DocGenUtilities.compare_versions(version, parent_version) > 0: version_display = self.truncate_version(version, 2) + '+' if version_display: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(v' + version_display + ', deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): deprecated_descr = ('Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation']) else: enum_name += ' ' + self.formatter.italic('(v' + version_display + ')') else: if 'version_deprecated' in enum_item_meta: version_depr = enum_item_meta['version_deprecated'] deprecated_display = self.truncate_version(version_depr, 2) enum_name += ' ' + self.formatter.italic('(deprecated v' + deprecated_display + ')') if enum_item_meta.get('version_deprecated_explanation'): enum_name += ' ' + self.formatter.italic('Deprecated v' + deprecated_display + '+. ' + enum_item_meta['version_deprecated_explanation']) if profile_mode: profile_spec = '' if enum_name in profile_values: profile_spec = 'Required' elif enum_name in profile_min_support_values: profile_spec = 'Required' elif enum_name in profile_parameter_values: profile_spec = 'Required' elif enum_name in profile_recommended_values: profile_spec = 'Recommended' contents.append('| ' + enum_name + ' | ' + profile_spec + ' |') else: contents.append('| ' + enum_name + ' | ') return '\n'.join(contents) + '\n'