def setUp(self): # Cruft, should be unnecessary soon self.tag_validators = {} self.parser = GtkDocParser(self) self.doc_database = DocDatabase() self.link_resolver = LinkResolver(self.doc_database) self.formatter = GtkDocStringFormatter()
class CHtmlFormatter(HtmlFormatter): def __init__(self): HtmlFormatter.__init__(self, []) self._docstring_formatter = GtkDocStringFormatter() def _format_comment(self, comment, link_resolver): return self._docstring_formatter.translate_comment( comment, link_resolver, 'html')
def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ParameterSymbol: self._format_parameter_symbol, ReturnItemSymbol: self._format_return_item_symbol, FieldSymbol: self._format_field_symbol, SignalSymbol: self._format_signal_symbol, VFunctionSymbol: self._format_vfunction_symbol, PropertySymbol: self._format_property_symbol, ClassSymbol: self._format_class_symbol, InterfaceSymbol: self._format_interface_symbol, } self._ordering = [InterfaceSymbol, ClassSymbol, FunctionSymbol, FunctionMacroSymbol, SignalSymbol, PropertySymbol, StructSymbol, VFunctionSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] if HtmlFormatter.theme_path: self.__load_theme_templates(searchpath, HtmlFormatter.theme_path) if HtmlFormatter.extra_theme_path: self.__load_theme_templates(searchpath, HtmlFormatter.extra_theme_path) searchpath.append(os.path.join(HERE, "html_templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()] ) self.all_scripts = set() self.all_stylesheets = set() self._docstring_formatter = GtkDocStringFormatter()
def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ParameterSymbol: self._format_parameter_symbol, ReturnItemSymbol: self._format_return_item_symbol, FieldSymbol: self._format_field_symbol, SignalSymbol: self._format_signal_symbol, VFunctionSymbol: self._format_vfunction_symbol, PropertySymbol: self._format_property_symbol, ClassSymbol: self._format_class_symbol, } self._ordering = [ClassSymbol, FunctionSymbol, FunctionMacroSymbol, SignalSymbol, PropertySymbol, StructSymbol, VFunctionSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] if HtmlFormatter.theme_path: theme_templates_path = os.path.join( HtmlFormatter.theme_path, 'templates') if os.path.exists(theme_templates_path): searchpath.insert(0, theme_templates_path) searchpath.append(os.path.join(HERE, "html_templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()] ) self.all_scripts = set() self.all_stylesheets = set() self._docstring_formatter = GtkDocStringFormatter()
class HtmlFormatter(Formatter): """ Banana banana """ theme_path = None add_anchors = False def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ParameterSymbol: self._format_parameter_symbol, ReturnItemSymbol: self._format_return_item_symbol, FieldSymbol: self._format_field_symbol, SignalSymbol: self._format_signal_symbol, VFunctionSymbol: self._format_vfunction_symbol, PropertySymbol: self._format_property_symbol, ClassSymbol: self._format_class_symbol, } self._ordering = [ClassSymbol, FunctionSymbol, FunctionMacroSymbol, SignalSymbol, PropertySymbol, StructSymbol, VFunctionSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] if HtmlFormatter.theme_path: theme_templates_path = os.path.join( HtmlFormatter.theme_path, 'templates') if os.path.exists(theme_templates_path): searchpath.insert(0, theme_templates_path) searchpath.append(os.path.join(HERE, "html_templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()] ) self.all_scripts = set() self.all_stylesheets = set() self._docstring_formatter = GtkDocStringFormatter() def format_comment(self, comment, link_resolver): if comment: self._docstring_formatter.translate_tags(comment, link_resolver) return super(HtmlFormatter, self).format_comment( comment, link_resolver) # pylint: disable=too-many-locals def write_page(self, page, output): root = etree.HTML(unicode(page.detailed_description)) id_nodes = {n.attrib['id']: "".join([x for x in n.itertext()]) for n in root.xpath('.//*[@id]')} targets = root.xpath( './/*[self::h1 or self::h2 or self::h3 or ' 'self::h4 or self::h5 or self::img]') for target in targets: if 'id' in target.attrib: continue if target.tag == 'img': text = target.attrib.get('alt') else: text = "".join([x for x in target.itertext()]) if not text: continue id_ = _id_from_text(text) ref_id = id_ index = 1 while id_ in id_nodes: id_ = '%s%s' % (ref_id, index) index += 1 target.attrib['id'] = id_ id_nodes[id_] = text empty_links = root.xpath('.//a[not(text()) and not(*)]') for link in empty_links: href = link.attrib.get('href') if href and href.startswith('#'): title = id_nodes.get(href.strip('#')) if title: link.text = title else: warn('bad-local-link', "Empty anchor link to %s in %s points nowhere" % (href, page.source_file)) link.text = "FIXME broken link to %s" % href page.detailed_description = lxml.html.tostring( root, doctype="<!DOCTYPE html>", encoding='unicode', include_meta_content_type=True) return Formatter.write_page(self, page, output) # pylint: disable=no-self-use def _get_extension(self): return "html" def get_output_folder(self): return os.path.join(super(HtmlFormatter, self).get_output_folder(), 'html') def _format_docstring(self, docstring, link_resolver, to_native): if to_native: format_ = 'markdown' else: format_ = 'html' return self._docstring_formatter.translate( docstring, link_resolver, format_) def _format_link(self, link, title): out = '' if not link: print "Issue here plz check", title return title template = self.engine.get_template('link.html') out += '%s' % template.render({'link': link, 'link_title': title}) return out def _format_type_tokens(self, type_tokens): out = '' link_before = False for tok in type_tokens: if isinstance(tok, Link): ref = tok.get_link() if ref: out += self._format_link(ref, tok.title) link_before = True else: if link_before: out += ' ' out += tok.title link_before = False else: if link_before: out += ' ' out += tok link_before = False return out # pylint: disable=unidiomatic-typecheck def _format_linked_symbol(self, symbol): out = "" if isinstance(symbol, QualifiedSymbol): out += self._format_type_tokens(symbol.type_tokens) # FIXME : ugly elif hasattr(symbol, "link"): out += self._format_link(symbol.link.get_link(), symbol.link.title) if type(symbol) == ParameterSymbol: out += ' ' + symbol.argname elif type(symbol) == FieldSymbol and symbol.member_name: template = self.engine.get_template('inline_code.html') member_name = template.render({'code': symbol.member_name}) if symbol.is_function_pointer: out = member_name out += "()" else: out += ' ' + member_name return out def _format_callable_prototype(self, return_value, function_name, parameters, is_pointer): template = self.engine.get_template('callable_prototype.html') return template.render({'return_value': return_value, 'name': function_name, 'parameters': parameters, 'is_pointer': is_pointer}) def __format_parameter_detail(self, name, detail, extra=None): extra = extra or {} template = self.engine.get_template('parameter_detail.html') return template.render({'name': name, 'detail': detail, 'extra': extra}) def _format_symbol_descriptions(self, symbols_list): detailed_descriptions = [] for element in symbols_list.symbols: if element.skip: continue if element.detailed_description: detailed_descriptions.append(element.detailed_description) symbol_type = symbols_list.name symbol_descriptions = None if detailed_descriptions: symbol_descriptions = SymbolDescriptions(detailed_descriptions, symbol_type) return symbol_descriptions def _format_struct(self, struct): raw_code = None if struct.raw_text is not None: raw_code = self._format_raw_code(struct.raw_text) members_list = self._format_members_list(struct.members, 'Fields') template = self.engine.get_template("struct.html") out = template.render({"symbol": struct, "struct": struct, "raw_code": raw_code, "members_list": members_list}) return (out, False) def _format_enum(self, enum): for member in enum.members: template = self.engine.get_template("enum_member.html") member.detailed_description = template.render({ 'link': member.link, 'detail': member.formatted_doc, 'value': str(member.enum_value)}) members_list = self._format_members_list(enum.members, 'Members') template = self.engine.get_template("enum.html") out = template.render({"symbol": enum, "enum": enum, "members_list": members_list}) return (out, False) def prepare_page_attributes(self, page): """ Banana banana """ page.output_attrs['html']['scripts'] = OrderedSet() page.output_attrs['html']['stylesheets'] = OrderedSet() page.output_attrs['html']['extra_html'] = [] page.output_attrs['html']['extra_footer_html'] = [] if HtmlFormatter.add_anchors: page.output_attrs['html']['scripts'].add( os.path.join(HERE, 'html_assets', 'css.escape.js')) Formatter.prepare_page_attributes(self, page) def patch_page(self, page, symbol): raise NotImplementedError # pylint: disable=too-many-locals def _format_page(self, page): symbols_details = [] for symbols_type in self._ordering: symbols_list = page.typed_symbols.get(symbols_type) if not symbols_list: continue symbols_descriptions = self._format_symbol_descriptions( symbols_list) if symbols_descriptions: symbols_details.append(symbols_descriptions) template = self.engine.get_template('page.html') scripts = page.output_attrs['html']['scripts'] stylesheets = page.output_attrs['html']['stylesheets'] scripts_basenames = [os.path.basename(script) for script in scripts] stylesheets_basenames = [os.path.basename(stylesheet) for stylesheet in stylesheets] self.all_stylesheets.update(stylesheets) self.all_scripts.update(scripts) out = template.render( {'page': page, 'source_file': os.path.basename(page.source_file), 'scripts': scripts_basenames, 'stylesheets': stylesheets_basenames, 'assets_path': self._get_assets_path(), 'extra_html': page.output_attrs['html']['extra_html'], 'extra_footer_html': page.output_attrs['html']['extra_footer_html'], 'symbols_details': symbols_details}) return (out, True) def _format_prototype(self, function, is_pointer, title): if function.return_value: return_value = self._format_linked_symbol(function.return_value[0]) else: return_value = None parameters = [] for param in function.parameters: parameters.append(self._format_linked_symbol(param)) return self._format_callable_prototype(return_value, title, parameters, is_pointer) def _format_raw_code(self, code): code = cgi.escape(code) template = self.engine.get_template('raw_code.html') return template.render({'code': code}) def _format_parameter_symbol(self, parameter): return (self.__format_parameter_detail( parameter.argname, parameter.formatted_doc, extra=parameter.extension_contents), False) def _format_field_symbol(self, field): field_id = self._format_linked_symbol(field) return (self.__format_parameter_detail(field_id, field.formatted_doc), False) def _format_return_item_symbol(self, return_item): template = self.engine.get_template('return_item.html') return_item.formatted_link = self._format_linked_symbol(return_item) return (template.render({'return_item': return_item}), False) def _format_return_value_symbol(self, return_value): template = self.engine.get_template('multi_return_value.html') if return_value[0] is None: return_value = return_value[1:] return template.render({'return_items': return_value}) def _format_callable(self, callable_, callable_type, title, is_pointer=False): template = self.engine.get_template('callable.html') parameters = [p.detailed_description for p in callable_.parameters if p.detailed_description is not None] prototype = self._format_prototype(callable_, is_pointer, title) return_value_detail = self._format_return_value_symbol( callable_.return_value) tags = {} if callable_.comment: tags = dict(callable_.comment.tags) tags.pop('returns', None) tags.pop('topic', None) out = template.render({'prototype': prototype, 'symbol': callable_, 'return_value': return_value_detail, 'parameters': parameters, 'callable_type': callable_type, 'tags': tags, 'extra': callable_.extension_contents}) return (out, False) def _format_signal_symbol(self, signal): title = "%s_callback" % re.sub('-', '_', signal.link.title) return self._format_callable(signal, "signal", title) def _format_vfunction_symbol(self, vmethod): return self._format_callable(vmethod, "virtual method", vmethod.link.title) def _format_property_symbol(self, prop): type_link = self._format_linked_symbol(prop.prop_type) template = self.engine.get_template('property_prototype.html') prototype = template.render({'property_name': prop.link.title, 'property_type': type_link}) template = self.engine.get_template('property.html') res = template.render({'symbol': prop, 'prototype': prototype, 'property': prop, 'extra': prop.extension_contents}) return (res, False) def _format_hierarchy(self, klass): hierarchy = [] children = [] for _ in klass.hierarchy: hierarchy.append(self._format_linked_symbol(_)) for _ in klass.children.itervalues(): children.append(self._format_linked_symbol(_)) if hierarchy or children: template = self.engine.get_template("hierarchy.html") hierarchy = template.render({'hierarchy': hierarchy, 'children': children, 'klass': klass}) return hierarchy def _format_class_symbol(self, klass): hierarchy = self._format_hierarchy(klass) template = self.engine.get_template('class.html') return (template.render({'symbol': klass, 'klass': klass, 'hierarchy': hierarchy}), False) def _format_members_list(self, members, member_designation): template = self.engine.get_template('member_list.html') return template.render({'members': members, 'member_designation': member_designation}) def _format_function(self, function): return self._format_callable(function, "method", function.link.title) def _format_callback(self, callback): return self._format_callable(callback, "callback", callback.link.title, is_pointer=True) def _format_function_macro(self, function_macro): template = self.engine.get_template('callable.html') prototype = self._format_raw_code(function_macro.original_text) parameters = [p.detailed_description for p in function_macro.parameters if p.detailed_description is not None] return_value_detail = self._format_return_value_symbol( function_macro.return_value) out = template.render({'prototype': prototype, 'symbol': function_macro, 'return_value': return_value_detail, 'parameters': parameters, 'callable_type': "function macro", 'flags': None, 'tags': {}, 'extra': function_macro.extension_contents}) return (out, False) def _format_alias(self, alias): template = self.engine.get_template('alias.html') aliased_type = self._format_linked_symbol(alias.aliased_type) return (template.render({'symbol': alias, 'alias': alias, 'aliased_type': aliased_type}), False) def _format_constant(self, constant): template = self.engine.get_template('constant.html') definition = self._format_raw_code(constant.original_text) out = template.render({'symbol': constant, 'definition': definition, 'constant': constant}) return (out, False) def _format_symbol(self, symbol): format_function = self._symbol_formatters.get(type(symbol)) if format_function: return format_function(symbol) return (None, False) def _format_object_hierarchy_symbol(self, symbol): dot_graph = _create_hierarchy_graph(symbol.hierarchy) tmp_file = tempfile.NamedTemporaryFile(suffix='.svg', delete=False) dot_graph.draw(tmp_file, prog='dot', format='svg', args="-Grankdir=LR") tmp_file.close() with open(tmp_file.name, 'r') as _: contents = _.read() os.unlink(_.name) pagename = 'object_hierarchy.html' template = self.engine.get_template(pagename) res = template.render({'graph': contents, 'assets_path': self._get_assets_path()}) return (res, False) def _get_extra_files(self): res = [] if HtmlFormatter.theme_path: theme_files = os.listdir(HtmlFormatter.theme_path) for file_ in theme_files: if file_ == 'templates': pass src = os.path.join(HtmlFormatter.theme_path, file_) dest = os.path.basename(src) res.append((src, dest)) for script_path in self.all_scripts: dest = os.path.join('js', os.path.basename(script_path)) res.append((script_path, dest)) for stylesheet_path in self.all_stylesheets: dest = os.path.join('css', os.path.basename(stylesheet_path)) res.append((stylesheet_path, dest)) return res @staticmethod def add_arguments(parser): """Banana banana """ group = parser.add_argument_group( 'Html formatter', 'html formatter options') group.add_argument("--html-theme", action="store", dest="html_theme", help="html theme to use", default='default') group.add_argument("--html-add-anchors", action="store_true", dest="html_add_anchors", help="Add anchors to html headers", default='default') @staticmethod def parse_config(doc_repo, config): """Banana banana """ html_theme = config.get('html_theme', 'default') if html_theme == 'default': default_theme = os.path.join(HERE, '..', 'default_theme-%s' % THEME_VERSION) html_theme = os.path.abspath(default_theme) else: html_theme = config.get_path('html_theme') HtmlFormatter.theme_path = html_theme HtmlFormatter.add_anchors = bool(config.get("html_add_anchors"))
def __init__(self): HtmlFormatter.__init__(self, []) self._docstring_formatter = GtkDocStringFormatter()