From 0aeaf6e39890699cdedeace43378f681b243528d Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 6 Jun 2015 17:10:52 -0700 Subject: docwriter: Option to select output format For generating other output formats such as DevDocs-ready HTML, we add an output format option (-f). The default output format is "mallard" which leaves the existing behaviour unchanged. We can fold the existing --write-sections-file option into the new output format option, as a new "sections" format. --- giscanner/docmain.py | 3 +++ giscanner/docwriter.py | 1 + 2 files changed, 4 insertions(+) diff --git a/giscanner/docmain.py b/giscanner/docmain.py index 966b33c2..c91cce95 100644 --- a/giscanner/docmain.py +++ b/giscanner/docmain.py @@ -61,6 +61,9 @@ def doc_main(args): args = parser.parse_args(args[1:]) if not args.output: raise SystemExit("missing output parameter") + if args.format not in FORMATS: + raise SystemExit("Unknown output format %s (supported: %s)" % + (args.format, ", ".join(FORMATS))) if 'UNINSTALLED_INTROSPECTION_SRCDIR' in os.environ: top_srcdir = os.environ['UNINSTALLED_INTROSPECTION_SRCDIR'] diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index d9c2ed57..a59cc7f2 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -910,6 +910,7 @@ class DocWriter(object): self._formatter = formatter_class(self._transformer) self._language = self._formatter.language + self._output_format = output_format self._lookup = self._get_template_lookup() -- cgit v1.2.1 From aad9d83e58c7ca3e6a4df983c7124664b1985b03 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Tue, 1 Dec 2015 23:00:53 -0800 Subject: transformer: Strip whitespace from filter commands On OS X, the output of sed as reported back to Python has a newline at the end. It seems like a good idea to strip whitespace from the symbol and identifier filter commands anyhow, so strip() the result. https://bugzilla.gnome.org/show_bug.cgi?id=752468 --- giscanner/transformer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/giscanner/transformer.py b/giscanner/transformer.py index 1a27aa3c..c3187e82 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -262,6 +262,7 @@ currently-scanned namespace is first.""" stderr=subprocess.PIPE) _name = name proc_name, err = proc.communicate(name.encode()) + proc_name = proc_name.strip() if proc.returncode: raise ValueError('filter: %r exited: %d with error: %s' % (self._symbol_filter_cmd, proc.returncode, err)) -- cgit v1.2.1 From c66bc4042cc72e7b65b4126e44bff5f174b054b8 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Tue, 10 Mar 2015 15:58:19 +0100 Subject: docwriter: Add support for plural type references. --- giscanner/docwriter.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index a59cc7f2..7f8c5485 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -266,11 +266,17 @@ class DocFormatter(object): return self.format_xref(signal) def _process_type_name(self, node, match, props): - type_ = self._resolve_type(props['type_name']) + ident = props['type_name'] + type_ = self._resolve_type(ident) + plural = False if type_ is None: - return match + singularized = ident.rstrip("s") # Try to remove plural + type_ = self._resolve_type(singularized) + plural = True + if type_ is None: + return match - return self.format_xref(type_) + return self.format_xref(type_, pluralize=plural) def _process_enum_value(self, node, match, props): member_name = props['member_name'] @@ -352,28 +358,36 @@ class DocFormatter(object): else: return make_page_id(node) - def format_xref(self, node, **attrdict): + def format_xref(self, node, pluralize=False, **attrdict): if node is None or not hasattr(node, 'namespace'): attrs = [('xref', 'index')] + list(sorted(attrdict.items())) return xmlwriter.build_xml_tag('link', attrs) elif isinstance(node, ast.Member): # Enum/BitField members are linked to the main enum page. - return self.format_xref(node.parent, **attrdict) + '.' + node.name + return self.format_xref(node.parent, pluralize=pluralize, **attrdict) + '.' + node.name elif node.namespace is self._transformer.namespace: - return self.format_internal_xref(node, attrdict) + return self.format_internal_xref(node, attrdict, pluralize=pluralize) else: - return self.format_external_xref(node, attrdict) + return self.format_external_xref(node, attrdict, pluralize=pluralize) - def format_internal_xref(self, node, attrdict): + def format_internal_xref(self, node, attrdict, pluralize=False): attrs = [('xref', make_page_id(node))] + list(sorted(attrdict.items())) - return xmlwriter.build_xml_tag('link', attrs) + if not pluralize: + return xmlwriter.build_xml_tag('link', attrs) + else: + return xmlwriter.build_xml_tag('link', attrs, make_page_id(node) + + "s") - def format_external_xref(self, node, attrdict): + def format_external_xref(self, node, attrdict, pluralize=False): ns = node.namespace attrs = [('href', '../%s-%s/%s.html' % (ns.name, str(ns.version), make_page_id(node)))] attrs += list(sorted(attrdict.items())) - return xmlwriter.build_xml_tag('link', attrs, self.format_page_name(node)) + if not pluralize: + return xmlwriter.build_xml_tag('link', attrs, self.format_page_name(node)) + else: + return xmlwriter.build_xml_tag('link', attrs, + self.format_page_name(node) + "s") def field_is_writable(self, field): return True -- cgit v1.2.1 From 19c03a46b14f379cfd4ad93e34133312b754efea Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Tue, 10 Mar 2015 15:47:50 +0100 Subject: docwriter: parse markdown for code blocks. This also removes some "parsing" code for paragraphs, which is best handled by the actual scanner. + Also fixes some pep8 issues. https://bugzilla.gnome.org/show_bug.cgi?id=745298 --- giscanner/docwriter.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index 7f8c5485..2c3920fe 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -36,6 +36,30 @@ from mako.lookup import TemplateLookup from . import ast, xmlwriter from .utils import to_underscores +# Freely inspired from +# https://github.com/GNOME/yelp-xsl/blob/master/js/syntax.html +language_mimes = { + "bash-script": "application/x-shellscript", + "shell": "application/x-shellscript", + "csharp": "text/x-csharp", + "css": "text/css", + "diff": "text/xpatch", + "html": "text/html", + "java": "text/x-java", + "javascript": "application/javascript", + "lisp": "text/x-scheme", + "lua": "text-x-lua", + "c": "text/x-csrc", + "c++": "text/x-c++src", + "pascal": "text/x-pascal", + "perl": "application/x-perl", + "php": "application/x-php", + "python": "text/x-python", + "ruby": "application/x-ruby", + "sql": "text/x-sql", + "yaml": "application/x-yaml", +} + def make_page_id(node, recursive=False): if isinstance(node, ast.Namespace): @@ -164,8 +188,14 @@ class TemplatedScanner(object): class DocstringScanner(TemplatedScanner): def __init__(self): specs = [ + ('new_paragraph', r'\n\n'), + ('new_line', r'\n'), ('!alpha', r'[a-zA-Z0-9_]+'), ('!alpha_dash', r'[a-zA-Z0-9_-]+'), + ('code_start_with_language', + r'\|\[\>\"\s*\-\-\>'), + ('code_start', r'\|\['), + ('code_end', r'\]\|'), ('property', r'#<>:(<>)'), ('signal', r'#<>::(<>)'), ('type_name', r'#(<>)'), @@ -181,6 +211,10 @@ class DocFormatter(object): def __init__(self, transformer): self._transformer = transformer self._scanner = DocstringScanner() + # If we are processing a code block as defined by + # https://wiki.gnome.org/Projects/GTK%2B/DocumentationSyntax/Markdown + # we won't insert paragraphs and will respect new lines. + self._processing_code = False def escape(self, text): return saxutils.escape(text) @@ -203,11 +237,9 @@ class DocFormatter(object): if doc is None: return '' - result = '' - for para in doc.split('\n\n'): - result += '

' - result += self.format_inline(node, para) - result += '

' + result = '

' + result += self.format_inline(node, doc) + result += '

' return result def _resolve_type(self, ident): @@ -307,6 +339,29 @@ class DocFormatter(object): return self.format_xref(func) + def _process_code_start(self, node, match, props): + self._processing_code = True + return "

" + + def _process_code_start_with_language(self, node, match, props): + mime = language_mimes[props["language_name"].lower()] + self._processing_code = True + if not mime: + return "

" + return '

' + + def _process_code_end(self, node, match, props): + self._processing_code = False + return "

" + + def _process_new_line(self, node, match, props): + return '\n' + + def _process_new_paragraph(self, node, match, props): + if self._processing_code: + return '\n\n' + return "

" + def _process_token(self, node, tok): kind, match, props = tok @@ -318,6 +373,11 @@ class DocFormatter(object): 'enum_value': self._process_enum_value, 'parameter': self._process_parameter, 'function_call': self._process_function_call, + 'code_start': self._process_code_start, + 'code_start_with_language': self._process_code_start_with_language, + 'code_end': self._process_code_end, + 'new_line': self._process_new_line, + 'new_paragraph': self._process_new_paragraph, } return dispatch[kind](node, match, props) -- cgit v1.2.1 From 7f67146d8254464f396b289ed41c8954d61fe03d Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 15 Nov 2015 21:46:12 -0500 Subject: doctool: Output formatter for DevDocs In order to generate HTML output that DevDocs can easily scrape and display, we add a new output format to g-ir-doc-tool (--format=devdocs). It works similarly to the Mallard output format, but generates very simple HTML instead. We add a new set of Mako templates to generate this output. --- Makefile-giscanner.am | 17 ++- configure.ac | 13 +- giscanner/docmain.py | 2 +- giscanner/doctemplates/devdocs/Gjs/_method.tmpl | 48 +++++++ giscanner/doctemplates/devdocs/Gjs/_methods.tmpl | 4 + .../doctemplates/devdocs/Gjs/_properties.tmpl | 34 +++++ giscanner/doctemplates/devdocs/Gjs/_signals.tmpl | 20 +++ .../doctemplates/devdocs/Gjs/_staticmethods.tmpl | 4 + giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl | 6 + giscanner/doctemplates/devdocs/Gjs/base.tmpl | 15 +++ giscanner/doctemplates/devdocs/Gjs/callback.tmpl | 3 + giscanner/doctemplates/devdocs/Gjs/class.tmpl | 1 + giscanner/doctemplates/devdocs/Gjs/default.tmpl | 6 + giscanner/doctemplates/devdocs/Gjs/enum.tmpl | 16 +++ giscanner/doctemplates/devdocs/Gjs/function.tmpl | 1 + giscanner/doctemplates/devdocs/Gjs/interface.tmpl | 1 + giscanner/doctemplates/devdocs/Gjs/namespace.tmpl | 14 ++ giscanner/docwriter.py | 145 +++++++++++++++++++++ giscanner/mdextensions.py | 14 ++ 19 files changed, 359 insertions(+), 5 deletions(-) create mode 100644 giscanner/doctemplates/devdocs/Gjs/_method.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/_methods.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/_properties.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/_signals.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/_staticmethods.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/base.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/callback.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/class.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/default.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/enum.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/function.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/interface.tmpl create mode 100644 giscanner/doctemplates/devdocs/Gjs/namespace.tmpl create mode 100644 giscanner/mdextensions.py diff --git a/Makefile-giscanner.am b/Makefile-giscanner.am index 4f08934c..c51cbf23 100644 --- a/Makefile-giscanner.am +++ b/Makefile-giscanner.am @@ -47,6 +47,7 @@ pkgpyexec_PYTHON = \ giscanner/introspectablepass.py \ giscanner/libtoolimporter.py \ giscanner/maintransformer.py \ + giscanner/mdextensions.py \ giscanner/message.py \ giscanner/msvccompiler.py \ giscanner/pkgconfig.py \ @@ -105,7 +106,21 @@ nobase_dist_template_DATA = \ giscanner/doctemplates/mallard/Gjs/property.tmpl \ giscanner/doctemplates/mallard/Gjs/record.tmpl \ giscanner/doctemplates/mallard/Gjs/signal.tmpl \ - giscanner/doctemplates/mallard/Gjs/vfunc.tmpl + giscanner/doctemplates/mallard/Gjs/vfunc.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_method.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_methods.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_properties.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_signals.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_staticmethods.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl \ + giscanner/doctemplates/devdocs/Gjs/base.tmpl \ + giscanner/doctemplates/devdocs/Gjs/callback.tmpl \ + giscanner/doctemplates/devdocs/Gjs/class.tmpl \ + giscanner/doctemplates/devdocs/Gjs/default.tmpl \ + giscanner/doctemplates/devdocs/Gjs/enum.tmpl \ + giscanner/doctemplates/devdocs/Gjs/function.tmpl \ + giscanner/doctemplates/devdocs/Gjs/interface.tmpl \ + giscanner/doctemplates/devdocs/Gjs/namespace.tmpl _giscanner_la_CFLAGS = \ $(PYTHON_INCLUDES) \ diff --git a/configure.ac b/configure.ac index 29bddde3..e8c23523 100644 --- a/configure.ac +++ b/configure.ac @@ -276,13 +276,20 @@ dnl an external dependency AC_ARG_ENABLE(doctool,[ --disable-doctool disable g-ir-doc-tool ],,enable_doctool=auto) AS_IF([ test x$enable_doctool != xno], [ AM_CHECK_PYMOD(mako,,have_python_mako=yes,have_python_mako=no) + AM_CHECK_PYMOD(markdown,,have_python_markdown=yes,have_python_markdown=no) ]) -AS_IF([ test x$enable_doctool = xauto && test x$have_python_mako = xyes ], +AS_IF([ test x$enable_doctool = xauto && + test x$have_python_mako = xyes && + test x$have_python_markdown = xyes ], [ enable_doctool=yes ], - [ test x$enable_doctool = xauto && test x$have_python_mako = xno ], + [ test x$enable_doctool = xauto && + (test x$have_python_mako = xno || + test x$have_python_markdown = xno) ], [ enable_doctool=no ], [ test x$enable_doctool = xyes && test x$have_python_mako = xno ], - [ AC_MSG_ERROR([Python mako module not found]) ]) + [ AC_MSG_ERROR([Python mako module not found]) ], + [ test x$enable_doctool = xyes && test x$have_python_markdown = xno ], + [ AC_MSG_ERROR([Python markdown module not found]) ]) AM_CONDITIONAL(BUILD_DOCTOOL, test x$enable_doctool != xno) # Glib documentation diff --git a/giscanner/docmain.py b/giscanner/docmain.py index c91cce95..0120022b 100644 --- a/giscanner/docmain.py +++ b/giscanner/docmain.py @@ -32,7 +32,7 @@ from .docwriter import DocWriter from .sectionparser import generate_sections_file, write_sections_file from .transformer import Transformer -FORMATS = ('mallard', 'sections') +FORMATS = ['devdocs', 'mallard', 'sections'] def doc_main(args): diff --git a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl new file mode 100644 index 00000000..0374ba40 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl @@ -0,0 +1,48 @@ +<%def name="describe_parameters(m, static=False, virtual=False)"> +

+ % if static: +
Type:
+
Static
+ % elif virtual: +
Type:
+
Virtual
+ % endif + % if m.parameters: +
Parameters:
+
+
    + % for p in m.parameters: +
  • + ${p.argname} + (${formatter.format_type(p.type)}) + % if p.doc: + — ${formatter.format_inline(m, p.doc)} + % endif +
  • + % endfor +
+
+ % endif + % if m.retval.type != ast.TYPE_NONE: +
Returns:
+
+ (${formatter.format_type(m.retval.type)}) + % if m.retval.doc: + ${formatter.format_inline(m, m.retval.doc)} + % endif +
+ % endif +
+ + +<%def name="method(m, static=False, virtual=False)"> + <% invocation = ", ".join(map(lambda p: p.argname, m.parameters)) %> +

+ + ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) +

+ ${describe_parameters(m, static, virtual)} + ${formatter.format(m, m.doc)} + diff --git a/giscanner/doctemplates/devdocs/Gjs/_methods.tmpl b/giscanner/doctemplates/devdocs/Gjs/_methods.tmpl new file mode 100644 index 00000000..e876cd68 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_methods.tmpl @@ -0,0 +1,4 @@ +<%namespace name="method" file="_method.tmpl"/> +% for m in getattr(node, 'methods', []): + ${method.method(m)} +% endfor diff --git a/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl new file mode 100644 index 00000000..ef9913aa --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl @@ -0,0 +1,34 @@ +<%! + def dash_to_underscore(string): + return '_'.join(string.split('-')) + + def dash_to_camel(string): + words = string.split('-') + return ''.join([words[0]] + [word.title() for word in words[1:]]) +%> +% if getattr(node, 'properties', []): +

Property Details

+ % for p in node.properties: +

+ ${p.name | dash_to_underscore} +

+
+ % if p.name.lower() != p.name: +
Names
+
+ ${p.name}, ${p.name | dash_to_underscore}, + ${p.name | dash_to_camel} +
+ % endif +
Type
+
${formatter.format_type(p.type)}
+ ##
Default value
+ ##
Not currently stored in GIR
+
Flags
+
${formatter.format_property_flags(p)}
+
+ % if p.doc: + ${formatter.format(node, p.doc)} + % endif + % endfor +% endif diff --git a/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl new file mode 100644 index 00000000..4065df83 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl @@ -0,0 +1,20 @@ +<%namespace name="method" file="_method.tmpl"/> +% if getattr(node, 'signals', []): +

Signal Details

+ % for s in node.signals: +

+ + ${s.name}(${formatter.format_in_parameters(s)}) +

+
+
Flags
+
${formatter.format_signal_flags(s)}
+ ${method.describe_parameters(s)} +
+ % if s.doc: + ${formatter.format(node, s.doc)} + % endif + % endfor +% endif diff --git a/giscanner/doctemplates/devdocs/Gjs/_staticmethods.tmpl b/giscanner/doctemplates/devdocs/Gjs/_staticmethods.tmpl new file mode 100644 index 00000000..dcd542e1 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_staticmethods.tmpl @@ -0,0 +1,4 @@ +<%namespace name="method" file="_method.tmpl"/> +% for m in getattr(node, 'static_methods', []) + getattr(node, 'constructors', []): + ${method.method(m, static=True)} +% endfor diff --git a/giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl b/giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl new file mode 100644 index 00000000..2966ede4 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_vfuncs.tmpl @@ -0,0 +1,6 @@ +<%namespace name="method" file="_method.tmpl"/> +% if getattr(node, 'virtual_methods', []): + % for m in node.virtual_methods: + ${method.method(m, virtual=True)} + % endfor +% endif diff --git a/giscanner/doctemplates/devdocs/Gjs/base.tmpl b/giscanner/doctemplates/devdocs/Gjs/base.tmpl new file mode 100644 index 00000000..95800da8 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/base.tmpl @@ -0,0 +1,15 @@ + + +
+

${formatter.format_page_name(node)}

+

Details

+ ${formatter.format(node, node.doc)} + <%include file="_staticmethods.tmpl"/> + <%include file="_methods.tmpl"/> + <%include file="_vfuncs.tmpl"/> + <%include file="_signals.tmpl"/> + <%include file="_properties.tmpl"/> + ${self.body()} +
+ + diff --git a/giscanner/doctemplates/devdocs/Gjs/callback.tmpl b/giscanner/doctemplates/devdocs/Gjs/callback.tmpl new file mode 100644 index 00000000..2795ee3c --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/callback.tmpl @@ -0,0 +1,3 @@ +<%namespace name="method" file="_method.tmpl"/> +<%inherit file="base.tmpl"/> +${method.describe_parameters(node)} diff --git a/giscanner/doctemplates/devdocs/Gjs/class.tmpl b/giscanner/doctemplates/devdocs/Gjs/class.tmpl new file mode 100644 index 00000000..9d2b5238 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/class.tmpl @@ -0,0 +1 @@ +<%inherit file="base.tmpl"/> diff --git a/giscanner/doctemplates/devdocs/Gjs/default.tmpl b/giscanner/doctemplates/devdocs/Gjs/default.tmpl new file mode 100644 index 00000000..5130fadc --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/default.tmpl @@ -0,0 +1,6 @@ +<%inherit file="base.tmpl"/> +% if isinstance(node, ast.Constant): + + const ${formatter.format_page_name(node)} = ${node.value}; + +% endif diff --git a/giscanner/doctemplates/devdocs/Gjs/enum.tmpl b/giscanner/doctemplates/devdocs/Gjs/enum.tmpl new file mode 100644 index 00000000..a66cbefa --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/enum.tmpl @@ -0,0 +1,16 @@ +<%inherit file="base.tmpl"/> +
    +% for m in node.members: +
  • + + + ${m.name.upper()} + + = ${m.value} + + % if m.doc: + — ${formatter.format_inline(node, m.doc)} + % endif +
  • +% endfor +
diff --git a/giscanner/doctemplates/devdocs/Gjs/function.tmpl b/giscanner/doctemplates/devdocs/Gjs/function.tmpl new file mode 100644 index 00000000..9d2b5238 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/function.tmpl @@ -0,0 +1 @@ +<%inherit file="base.tmpl"/> diff --git a/giscanner/doctemplates/devdocs/Gjs/interface.tmpl b/giscanner/doctemplates/devdocs/Gjs/interface.tmpl new file mode 100644 index 00000000..9d2b5238 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/interface.tmpl @@ -0,0 +1 @@ +<%inherit file="base.tmpl"/> diff --git a/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl b/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl new file mode 100644 index 00000000..5a90634a --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl @@ -0,0 +1,14 @@ + + +
+

${node.name}

+
+
    + % for n in node.values(): + % if formatter.should_render_node(n): +
  • ${formatter.format_inline(n, formatter.format_xref(n))}
  • + % endif + % endfor +
+ + diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index 2c3920fe..f26ed5b1 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -32,9 +32,11 @@ import tempfile from xml.sax import saxutils from mako.lookup import TemplateLookup +import markdown from . import ast, xmlwriter from .utils import to_underscores +from .mdextensions import InlineMarkdown # Freely inspired from # https://github.com/GNOME/yelp-xsl/blob/master/js/syntax.html @@ -468,6 +470,20 @@ class DocFormatter(object): return " / ".join(flags) + def format_signal_flags(self, signal): + flags = [] + if signal.action: + flags.append("Action") + if signal.detailed: + flags.append("Detailed") + if signal.no_hooks: + flags.append("No Hooks") + if signal.no_recurse: + flags.append("No Recurse") + if signal.when: + flags.append("Run " + signal.when.capitalize()) + return " / ".join(flags) + def to_underscores(self, node): if isinstance(node, ast.Property): return node.name.replace('-', '_') @@ -963,7 +979,135 @@ class DocFormatterGjs(DocFormatterIntrospectableBase): return ', '.join(('%s: %s' % (p.argname, self.format_type(p.type))) for p in construct_params) + +class DevDocsFormatterGjs(DocFormatterGjs): + def _is_static_method(self, node): + if not hasattr(node.parent, "static_methods"): + return False + return node in node.parent.static_methods + + def should_render_node(self, node): + # For DevDocs, we only want to render the top-level nodes. + if isinstance(node, (ast.Compound, ast.Boxed)): + self.resolve_gboxed_constructor(node) + + if not super(DevDocsFormatterGjs, self).should_render_node(node): + return False + + if isinstance(node, ast.Function) and not node.is_method and \ + not node.is_constructor and not self._is_static_method(node): + return True # module-level function + toplevel_types = [ast.Alias, ast.Bitfield, ast.Boxed, ast.Callback, + ast.Class, ast.Constant, ast.Enum, ast.Interface, ast.Namespace, + ast.Record, ast.Union] + for ast_type in toplevel_types: + if isinstance(node, ast_type): + return True + + return False + + def format_fundamental_type(self, name): + # Don't specify the C type after Number as the Mallard docs do; it's + # confusing to GJS newbies. + if name in ["gint8", "guint8", "gint16", "guint16", "gint32", "guint32", + "gchar", "guchar", "gshort", "gint", "guint", "gfloat", + "gdouble", "gsize", "gssize", "gintptr", "guintptr", + "glong", "gulong", "gint64", "guint64", "long double", + "long long", "unsigned long long"]: + return "Number" # gsize and up cannot fully be represented in GJS + if name in ["none", "gpointer"]: + return "void" + if name in ["utf8", "gunichar", "filename"]: + return "String" + if name == "gboolean": + return "Boolean" + if name == "GType": + return "GObject.Type" + if name == "GVariant": + return "GLib.Variant" + return name + + def format(self, node, doc): + if doc is None: + return '' + + cleaned_up_gtkdoc = super(DevDocsFormatterGjs, self).format_inline(node, doc) + return markdown.markdown(cleaned_up_gtkdoc) + + def format_function_name(self, func): + name = func.name + if func.shadows: + name = func.shadows + + if isinstance(func, ast.VFunction): + return 'vfunc_' + name + return name + + def format_page_name(self, node): + if isinstance(node, ast.Function) and node.parent is not None: + return node.parent.name + "." + self.format_function_name(node) + return super(DevDocsFormatterGjs, self).format_page_name(node) + + def _write_xref_markdown(self, target, anchor=None, display_name=None, pluralize=False): + if display_name is None: + display_name = target + link = target + ".html" + if anchor is not None: + link += "#" + anchor + return "[{}]({}){}".format(display_name, link, 's' if pluralize else '') + + def make_anchor(self, node): + style_class = get_node_kind(node) + return "{}-{}".format(style_class, self.to_underscores(node)) + + def _process_parameter(self, node, match, props): + # Display the instance parameter as "this" instead of whatever name it + # has in C. + if hasattr(node, 'instance_parameter') and \ + node.instance_parameter is not None and \ + props['param_name'] == node.instance_parameter.argname: + return 'this' + return super(DevDocsFormatterGjs, self)._process_parameter(node, match, props) + + def format_xref(self, node, pluralize=False, **attrdict): + if node is None or not hasattr(node, 'namespace'): + return self._write_xref_markdown('index') + if node.namespace is self._transformer.namespace: + return self.format_internal_xref(node, attrdict, pluralize=pluralize) + return self.format_external_xref(node, attrdict, pluralize=pluralize) + + def format_internal_xref(self, node, attrdict, pluralize=False): + if not self.should_render_node(node): + # Non-toplevel nodes are linked to the main page. + page = make_page_id(node.parent) + return self._write_xref_markdown(page, self.make_anchor(node), + page + "." + node.name, + pluralize=pluralize) + return self._write_xref_markdown(make_page_id(node), pluralize=pluralize) + + def format_external_xref(self, node, attrdict, pluralize=False): + ns = node.namespace + if not self.should_render_node(node): + target = '../%s-%s/%s' % (ns.name, str(ns.version), make_page_id(node.parent)) + return self._write_xref_markdown(target, self.make_anchor(node), + self.format_page_name(node.parent), + pluralize=pluralize) + target = '../%s-%s/%s' % (ns.name, str(ns.version), make_page_id(node)) + return self._write_xref_markdown(target, None, + self.format_page_name(node), + pluralize=pluralize) + + def format_inline(self, node, para): + cleaned_up_gtkdoc = super(DevDocsFormatterGjs, self).format_inline(node, para) + return markdown.markdown(cleaned_up_gtkdoc, extensions=[InlineMarkdown()]) + + def format_in_parameters(self, node): + return ', '.join(p.argname for p in self.get_in_parameters(node)) + LANGUAGES = { + "devdocs": { + "gjs": DevDocsFormatterGjs, + }, "mallard": { "c": DocFormatterC, "python": DocFormatterPython, @@ -1043,6 +1187,7 @@ class DocWriter(object): node=node, page_id=page_id, page_kind=page_kind, + get_node_kind=get_node_kind, formatter=self._formatter, ast=ast) diff --git a/giscanner/mdextensions.py b/giscanner/mdextensions.py new file mode 100644 index 00000000..97be4ed1 --- /dev/null +++ b/giscanner/mdextensions.py @@ -0,0 +1,14 @@ +from markdown.extensions import Extension +from markdown.treeprocessors import Treeprocessor +from markdown.util import etree + + +class RemoveOuterP(Treeprocessor): + def run(self, root): + if len(root) == 1 and root[0].tag == "p": + root[0].tag = "span" + + +class InlineMarkdown(Extension): + def extendMarkdown(self, md, md_globals): + md.treeprocessors.add("remove_outer_p", RemoveOuterP(md), "_end") -- cgit v1.2.1 From 9719dd21669084b6ccaaef07899db8416e235a74 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 21 Nov 2015 21:02:02 -0800 Subject: devdocs: Render a summary at the top of each page This summary, heavily inspired by the one from pgi-docs, is useful when browsing the page rather than searching for a specific term. It's also similar to the summary at the top of gtk-doc pages. --- Makefile-giscanner.am | 1 + giscanner/doctemplates/devdocs/Gjs/_index.tmpl | 156 +++++++++++++++++++++++++ giscanner/doctemplates/devdocs/Gjs/base.tmpl | 1 + giscanner/docwriter.py | 19 ++- 4 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 giscanner/doctemplates/devdocs/Gjs/_index.tmpl diff --git a/Makefile-giscanner.am b/Makefile-giscanner.am index c51cbf23..4336a140 100644 --- a/Makefile-giscanner.am +++ b/Makefile-giscanner.am @@ -107,6 +107,7 @@ nobase_dist_template_DATA = \ giscanner/doctemplates/mallard/Gjs/record.tmpl \ giscanner/doctemplates/mallard/Gjs/signal.tmpl \ giscanner/doctemplates/mallard/Gjs/vfunc.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_index.tmpl \ giscanner/doctemplates/devdocs/Gjs/_method.tmpl \ giscanner/doctemplates/devdocs/Gjs/_methods.tmpl \ giscanner/doctemplates/devdocs/Gjs/_properties.tmpl \ diff --git a/giscanner/doctemplates/devdocs/Gjs/_index.tmpl b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl new file mode 100644 index 00000000..8d45e871 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl @@ -0,0 +1,156 @@ +<% + ancestors = [] + if isinstance(node, ast.Class): + ancestors = formatter.get_inheritable_types(node) + + def get_ancestor_counts(*kinds): + counts = {} + for a in ancestors: + count = sum([len(getattr(a, kind, [])) for kind in kinds]) + if count: + counts[a] = count + return counts + + def should_render(*kinds): + has_nonempty = any([getattr(node, kind, []) for kind in kinds]) + return has_nonempty or get_ancestor_counts(*kinds) +%> + +<%def name="inherited(*kinds)"> + <% counts = get_ancestor_counts(*kinds) %> + % if counts: + <% + links = ', '.join(['{} ({})'.format(formatter.format_xref(a), count) + for a, count in counts.items()]) + %> + ${formatter.format(node, '**Inherited:** ' + links)} + % endif + + +% if should_render('static_methods', 'constructors', 'methods'): +

Methods

+ ${inherited('static_methods', 'constructors', 'methods')} + <% + static_methods = getattr(node, 'static_methods', []) + getattr(node, 'constructors', []) + methods = static_methods + getattr(node, 'methods', []) + %> + % if methods: + + + % for m in methods: + + % if m in static_methods: + + % else: + + % endif + + + % endfor + +
static + + ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) +
+ % endif +% endif + +% if should_render('virtual_methods'): +

Virtual methods

+ ${inherited('virtual_methods')} + % if getattr(node, 'virtual_methods', []): + + + % for m in node.virtual_methods: + + + + % endfor + +
+ + ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) +
+ % endif +% endif + +% if should_render('properties'): +

Properties

+ ${inherited('properties')} + % if getattr(node, 'properties', []): + + + + + + + + + + % for p in node.properties: + + + + + + % endfor + +
NameTypeFlags
${p.name}${formatter.format_type(p.type)}${formatter.format_property_flags(p, abbrev=True)}
+ % endif +% endif + +% if should_render('signals'): +

Signals

+ ${inherited('signals')} + % if getattr(node, 'signals', []): + + + % for s in node.signals: + + + + % endfor + +
+ ${s.name}(${formatter.format_in_parameters(s)}) +
+ % endif +% endif + +% if should_render('fields'): +

Fields

+ ${inherited('fields')} + % if getattr(node, 'fields', []): + + + + + + + + + + + % for f in node.fields: + + + + + ## Fields almost never warrant a detailed entry, we'll just make this + ## the entry to be indexed by DevDocs + + + % endfor + +
NameTypeAccessDescription
${f.name}${formatter.format_type(f.type)}${formatter.format_property_flags(f, abbrev=True)} + % if f.doc: + ${formatter.format_inline(node, f.doc)} + % endif +
+ % endif +% endif diff --git a/giscanner/doctemplates/devdocs/Gjs/base.tmpl b/giscanner/doctemplates/devdocs/Gjs/base.tmpl index 95800da8..91ffa105 100644 --- a/giscanner/doctemplates/devdocs/Gjs/base.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/base.tmpl @@ -2,6 +2,7 @@

${formatter.format_page_name(node)}

+ <%include file="_index.tmpl"/>

Details

${formatter.format(node, node.doc)} <%include file="_staticmethods.tmpl"/> diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index f26ed5b1..cba8a5d8 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -454,7 +454,7 @@ class DocFormatter(object): def field_is_writable(self, field): return True - def format_property_flags(self, property_, construct_only=False): + def format_property_flags(self, property_, construct_only=False, abbrev=False): flags = [] if property_.readable and not construct_only: @@ -468,6 +468,9 @@ class DocFormatter(object): if property_.construct_only: flags.append("Construct Only") + if abbrev: + return "/".join([''.join([word[0] for word in flag.lower().split()]) + for flag in flags]) return " / ".join(flags) def format_signal_flags(self, signal): @@ -512,6 +515,20 @@ class DocFormatter(object): parent_chain.reverse() return parent_chain + def get_inheritable_types(self, node): + """Return an ast.Node object for each type (ast.Class and ast.Interface + types) from which an ast.Class @node might inherit methods, properties, + and signals.""" + + assert isinstance(node, ast.Class) + + parent_chain = self.get_class_hierarchy(node) + types = [] + for p in parent_chain: + types += [self._transformer.lookup_typenode(t) for t in p.interfaces] + types += [t for t in parent_chain if t is not node] + return types + def format_prerequisites(self, node): assert isinstance(node, ast.Interface) -- cgit v1.2.1 From c7014b82d930d10e2dc88cd2ab9eb880f78e69c1 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 21 Nov 2015 21:50:20 -0800 Subject: docwriter: Use
 for code blocks

Code blocks, i.e. |[ ]|, were converted into  elements, but 
would be more appropriate.

In addition, add four spaces to the start of each line in a 
 element
so that Markdown will recognize it as code and not mangle it. As explained
in a FIXME comment, a better solution would be to reimplement
DocstringScanner using Markdown extensions so that such confusion becomes
impossible.
---
 giscanner/docwriter.py | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py
index cba8a5d8..d17e8700 100644
--- a/giscanner/docwriter.py
+++ b/giscanner/docwriter.py
@@ -341,27 +341,41 @@ class DocFormatter(object):
 
         return self.format_xref(func)
 
+    # FIXME: the four spaces after newlines in the following functions are to
+    # keep Markdown happy. We pass the documentation string first through this
+    # templated scanner, which converts |[ ]| to 
. Then in the case
+    # of DevDocs output, we pass the resulting string through Markdown; but
+    # Markdown will not respect the 
 element and will treat the code as
+    # markup, converting asterisks into  etc. Putting four spaces at the
+    # start of each line makes Markdown recognize the code as code without
+    # affecting the normal HTML output too much.
+    #
+    # A better solution would be to replace DocstringScanner by Markdown
+    # entirely, implementing the custom markup with Markdown extensions.
+
     def _process_code_start(self, node, match, props):
         self._processing_code = True
-        return "

" + return '

\n    '
 
     def _process_code_start_with_language(self, node, match, props):
         mime = language_mimes[props["language_name"].lower()]
         self._processing_code = True
         if not mime:
-            return "

" - return '

' + return '

\n    '
+        return '

\n    '
 
     def _process_code_end(self, node, match, props):
         self._processing_code = False
-        return "

" + return '\n

' def _process_new_line(self, node, match, props): + if self._processing_code: + return '\n ' return '\n' def _process_new_paragraph(self, node, match, props): if self._processing_code: - return '\n\n' + return '\n\n ' return "

" def _process_token(self, node, tok): -- cgit v1.2.1 From 2635fb9fa3e223ae299a4306acf9dc85c6745637 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 12 Dec 2015 18:13:56 -0800 Subject: devdocs: Don't render private fields Skip private fields such as "priv" and "parent_instance". Unfortunately not all private structure and parent instance fields are marked private, and not all of them are named "priv" or "parent_instance". This also includes fields that are contained within anonymous unions. --- giscanner/doctemplates/devdocs/Gjs/_index.tmpl | 26 +++++++++++++++++---- giscanner/docwriter.py | 31 ++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/giscanner/doctemplates/devdocs/Gjs/_index.tmpl b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl index 8d45e871..6f5e9729 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_index.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl @@ -3,16 +3,34 @@ if isinstance(node, ast.Class): ancestors = formatter.get_inheritable_types(node) + fields = getattr(node, 'fields', []) + extra_fields = [getattr(f.anonymous_node, 'fields', []) for f in fields + if f.anonymous_node is not None] + extra_fields = [field for sublist in extra_fields for field in sublist] + non_private_fields = [f for f in fields + extra_fields + if not formatter.is_private_field(node, f)] + def get_ancestor_counts(*kinds): counts = {} for a in ancestors: - count = sum([len(getattr(a, kind, [])) for kind in kinds]) + count = 0 + for kind in kinds: + if kind == 'fields': + count += len(non_private_fields) + else: + count += len(getattr(a, kind, [])) if count: counts[a] = count return counts def should_render(*kinds): - has_nonempty = any([getattr(node, kind, []) for kind in kinds]) + has_nonempty = False + for kind in kinds: + if kind == 'fields': + if non_private_fields: + has_nonempty = True + elif getattr(node, kind, []): + has_nonempty = True return has_nonempty or get_ancestor_counts(*kinds) %> @@ -125,7 +143,7 @@ % if should_render('fields'):

Fields

${inherited('fields')} - % if getattr(node, 'fields', []): + % if non_private_fields: @@ -136,7 +154,7 @@ - % for f in node.fields: + % for f in non_private_fields: diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index d17e8700..e1d3149e 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -543,6 +543,37 @@ class DocFormatter(object): types += [t for t in parent_chain if t is not node] return types + def is_private_field(self, node, f): + """Returns whether @f is a private field of @node (including a heuristic + that tries to determine whether the field is the parent instance field + or a private pointer but not marked as such.)""" + + if f.private: + return True + if f.anonymous_node: + return True + if f.name == 'g_type_instance': + return True # this field on GObject is not exposed + + field_typenode = self._transformer.lookup_typenode(f.type) + if not field_typenode: + return False + + if getattr(field_typenode, 'disguised', False): + return True # guess that it's a pointer to a private struct + # this also catches fields of type GdkAtom, since that is disguised + # as well. Not sure whether that's correct or not. + + if not isinstance(node, ast.Class): + return False # parent instance heuristics only apply to classes + + if node.parent_type: + parent_typenode = self._transformer.lookup_typenode(node.parent_type) + if field_typenode == parent_typenode: + return True # guess that it's a parent instance field + + return False + def format_prerequisites(self, node): assert isinstance(node, ast.Interface) -- cgit v1.2.1 From 89d655237f9c08a9a83565b2efafe212df41f508 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 6 Dec 2015 18:03:15 -0800 Subject: devdocs: Generate versioning notes For GIR nodes with version annotations, such as "Since:", "Deprecated:", and "Stability:", we generate stability notes at the top of each node's documentation. These notes are given the CSS class "versioning-note" so that we can format them nicely in DevDocs. --- Makefile-giscanner.am | 1 + giscanner/doctemplates/devdocs/Gjs/_doc.tmpl | 25 ++++++++++++++++++++++ giscanner/doctemplates/devdocs/Gjs/_method.tmpl | 4 +++- .../doctemplates/devdocs/Gjs/_properties.tmpl | 3 ++- giscanner/doctemplates/devdocs/Gjs/_signals.tmpl | 5 ++--- giscanner/doctemplates/devdocs/Gjs/base.tmpl | 3 ++- giscanner/docwriter.py | 2 ++ 7 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 giscanner/doctemplates/devdocs/Gjs/_doc.tmpl diff --git a/Makefile-giscanner.am b/Makefile-giscanner.am index 4336a140..2879ab20 100644 --- a/Makefile-giscanner.am +++ b/Makefile-giscanner.am @@ -107,6 +107,7 @@ nobase_dist_template_DATA = \ giscanner/doctemplates/mallard/Gjs/record.tmpl \ giscanner/doctemplates/mallard/Gjs/signal.tmpl \ giscanner/doctemplates/mallard/Gjs/vfunc.tmpl \ + giscanner/doctemplates/devdocs/Gjs/_doc.tmpl \ giscanner/doctemplates/devdocs/Gjs/_index.tmpl \ giscanner/doctemplates/devdocs/Gjs/_method.tmpl \ giscanner/doctemplates/devdocs/Gjs/_methods.tmpl \ diff --git a/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl new file mode 100644 index 00000000..0e132b44 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl @@ -0,0 +1,25 @@ +<%def name="format_documentation(node)"> + % if node.version: +

+ New in version ${node.version}. + ${formatter.format_inline(node, node.version_doc)} +

+ % endif + % if node.deprecated: +

+ Deprecated since ${node.deprecated}. + ${formatter.format_inline(node, node.deprecated_doc)} +

+ % endif + % if node.stability: + ## Not sure what this looks like in the wild +

+ Stability: ${node.stability}. + ${formatter.format_inline(node, node.stability_doc)} +

+ % endif + + % if node.doc: + ${formatter.format(node, node.doc)} + % endif + diff --git a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl index 0374ba40..3e4d596e 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl @@ -1,3 +1,5 @@ +<%namespace name="doc" file="_doc.tmpl"/> + <%def name="describe_parameters(m, static=False, virtual=False)">
% if static: @@ -44,5 +46,5 @@ -->(${formatter.format_in_parameters(m)}) ${describe_parameters(m, static, virtual)} - ${formatter.format(m, m.doc)} + ${doc.format_documentation(m)} diff --git a/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl index ef9913aa..876beb83 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl @@ -1,3 +1,4 @@ +<%namespace name="doc" file="_doc.tmpl"/> <%! def dash_to_underscore(string): return '_'.join(string.split('-')) @@ -28,7 +29,7 @@
${formatter.format_property_flags(p)}
% if p.doc: - ${formatter.format(node, p.doc)} + ${doc.format_documentation(p)} % endif % endfor % endif diff --git a/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl index 4065df83..073d73f2 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl @@ -1,3 +1,4 @@ +<%namespace name="doc" file="_doc.tmpl"/> <%namespace name="method" file="_method.tmpl"/> % if getattr(node, 'signals', []):

Signal Details

@@ -13,8 +14,6 @@
${formatter.format_signal_flags(s)}
${method.describe_parameters(s)} - % if s.doc: - ${formatter.format(node, s.doc)} - % endif + ${doc.format_documentation(s)} % endfor % endif diff --git a/giscanner/doctemplates/devdocs/Gjs/base.tmpl b/giscanner/doctemplates/devdocs/Gjs/base.tmpl index 91ffa105..f35bc4c7 100644 --- a/giscanner/doctemplates/devdocs/Gjs/base.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/base.tmpl @@ -1,10 +1,11 @@ +<%namespace name="doc" file="_doc.tmpl"/>

${formatter.format_page_name(node)}

<%include file="_index.tmpl"/>

Details

- ${formatter.format(node, node.doc)} + ${doc.format_documentation(node)} <%include file="_staticmethods.tmpl"/> <%include file="_methods.tmpl"/> <%include file="_vfuncs.tmpl"/> diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index e1d3149e..0d55936c 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -1160,6 +1160,8 @@ class DevDocsFormatterGjs(DocFormatterGjs): pluralize=pluralize) def format_inline(self, node, para): + if para is None: + return '' cleaned_up_gtkdoc = super(DevDocsFormatterGjs, self).format_inline(node, para) return markdown.markdown(cleaned_up_gtkdoc, extensions=[InlineMarkdown()]) -- cgit v1.2.1 From 83a986e6be0742561187ee69affc158968442f75 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Mon, 7 Dec 2015 00:13:39 -0800 Subject: devdocs: Add deprecated CSS class where needed This adds a def in _doc.tmpl that expands to "deprecated" if the node is deprecated, and to nothing otherwise. We use it to give the deprecated CSS class to particular elements. The presence of the class on a symbol's main entry will inform DevDocs that the symbol is deprecated, though it won't be formatted in a particular way. The presence of the class on an index entry will cause the index entry to be struck out, so that it's visually obvious in the index when a symbol is deprecated. --- giscanner/doctemplates/devdocs/Gjs/_doc.tmpl | 6 ++++ giscanner/doctemplates/devdocs/Gjs/_index.tmpl | 39 +++++++++++++--------- giscanner/doctemplates/devdocs/Gjs/_method.tmpl | 3 +- .../doctemplates/devdocs/Gjs/_properties.tmpl | 3 +- giscanner/doctemplates/devdocs/Gjs/_signals.tmpl | 3 +- giscanner/doctemplates/devdocs/Gjs/base.tmpl | 4 ++- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl index 0e132b44..b8a2d7a6 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl @@ -23,3 +23,9 @@ ${formatter.format(node, node.doc)} % endif + +<%def name="deprecated_class(node)"> + % if node.deprecated: + deprecated + % endif + diff --git a/giscanner/doctemplates/devdocs/Gjs/_index.tmpl b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl index 6f5e9729..f9847cdc 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_index.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl @@ -1,3 +1,5 @@ +<%namespace name="doc" file="_doc.tmpl"/> + <% ancestors = [] if isinstance(node, ast.Class): @@ -45,6 +47,15 @@ % endif +<%def name="format_function_cell(m)"> +
+ + % if should_render('static_methods', 'constructors', 'methods'):

Methods

${inherited('static_methods', 'constructors', 'methods')} @@ -53,7 +64,7 @@ methods = static_methods + getattr(node, 'methods', []) %> % if methods: -
${f.name} ${formatter.format_type(f.type)} + + ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) +
+
% for m in methods: @@ -62,12 +73,7 @@ % else: % endif - + ${format_function_cell(m)} % endfor @@ -83,12 +89,7 @@ % for m in node.virtual_methods: - + ${format_function_cell(m)} % endfor @@ -111,7 +112,9 @@ % for p in node.properties: - + @@ -129,7 +132,7 @@ % for s in node.signals: - @@ -156,7 +159,11 @@ % for f in non_private_fields: - + ## Fields almost never warrant a detailed entry, we'll just make this diff --git a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl index 3e4d596e..71569946 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl @@ -40,7 +40,8 @@ <%def name="method(m, static=False, virtual=False)"> <% invocation = ", ".join(map(lambda p: p.argname, m.parameters)) %>

- + ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) diff --git a/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl index 876beb83..b67d75ae 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl @@ -10,7 +10,8 @@ % if getattr(node, 'properties', []):

Property Details

% for p in node.properties: -

+

${p.name | dash_to_underscore}

diff --git a/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl index 073d73f2..7b39d5fc 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl @@ -4,7 +4,8 @@

Signal Details

% for s in node.signals:

- + ${s.name}(${formatter.format_in_parameters(s)}) diff --git a/giscanner/doctemplates/devdocs/Gjs/base.tmpl b/giscanner/doctemplates/devdocs/Gjs/base.tmpl index f35bc4c7..3ca46a3e 100644 --- a/giscanner/doctemplates/devdocs/Gjs/base.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/base.tmpl @@ -2,7 +2,9 @@
-

${formatter.format_page_name(node)}

+

+ ${formatter.format_page_name(node)} +

<%include file="_index.tmpl"/>

Details

${doc.format_documentation(node)} -- cgit v1.2.1 From dbcc0f8af23ccd385a1edd888034e79c47908520 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Mon, 7 Dec 2015 00:16:07 -0800 Subject: docwriter: Handle moved_to in underscore function This function was failing on g_iconv() which has a blank name in the GIR file (its name instead coming from the moved-to attribute.) --- giscanner/docwriter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index 0d55936c..35ba6f1c 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -506,6 +506,8 @@ class DocFormatter(object): return node.name.replace('-', '_') elif node.name: return to_underscores(node.name) + elif isinstance(node, ast.Function) and node.moved_to: + return to_underscores(node.moved_to) elif isinstance(node, ast.Callback): return 'callback' elif isinstance(node, ast.Union): -- cgit v1.2.1 From 26560766ce3505ef4f5b09b41f13895346133f3a Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Mon, 7 Dec 2015 01:03:56 -0800 Subject: devdocs: Format the values of constants We change the style of documentation pages for constants, so that their values are displayed in a
/
pair. We add a new method to the formatter family, format_value() which should print the representation of a constant's value in the target language; much like repr() in Python. --- giscanner/doctemplates/devdocs/Gjs/default.tmpl | 10 +++++++--- giscanner/docwriter.py | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/giscanner/doctemplates/devdocs/Gjs/default.tmpl b/giscanner/doctemplates/devdocs/Gjs/default.tmpl index 5130fadc..0c0fdf6c 100644 --- a/giscanner/doctemplates/devdocs/Gjs/default.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/default.tmpl @@ -1,6 +1,10 @@ <%inherit file="base.tmpl"/> % if isinstance(node, ast.Constant): - - const ${formatter.format_page_name(node)} = ${node.value}; - +
+
Value
+
+ ${formatter.format_value(node)} +
+
% endif diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index 35ba6f1c..a0052d87 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -418,6 +418,9 @@ class DocFormatter(object): def format_type(self, type_, link=False): raise NotImplementedError + def format_value(self, node): + raise NotImplementedError + def format_page_name(self, node): if isinstance(node, ast.Namespace): return node.name @@ -1091,6 +1094,14 @@ class DevDocsFormatterGjs(DocFormatterGjs): return "GLib.Variant" return name + def format_value(self, node): + # Constants only have fundamental types? + type_ = node.value_type.target_fundamental + if type_ in ["utf8", "gunichar", "filename"]: + return repr(node.value) + # escapes quotes in the string; ought to be the same in Javascript + return node.value + def format(self, node, doc): if doc is None: return '' -- cgit v1.2.1 From b7ee86ab4833f428e27429a75b2955c6b21159b1 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 12 Dec 2015 11:08:25 -0800 Subject: devdocs: Describe bare functions Pages for bare functions (not in a class) were missing descriptions of their arguments and return values. --- giscanner/doctemplates/devdocs/Gjs/function.tmpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/giscanner/doctemplates/devdocs/Gjs/function.tmpl b/giscanner/doctemplates/devdocs/Gjs/function.tmpl index 9d2b5238..2795ee3c 100644 --- a/giscanner/doctemplates/devdocs/Gjs/function.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/function.tmpl @@ -1 +1,3 @@ +<%namespace name="method" file="_method.tmpl"/> <%inherit file="base.tmpl"/> +${method.describe_parameters(node)} -- cgit v1.2.1 From 9e31e0618171f4a3683281706e167759365db1f3 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 12 Dec 2015 16:12:41 -0800 Subject: devdocs: Match DevDocs' slug names Because of some Ruby naming rules in DevDocs, other GIR modules will have their documentation in ../namespace10/ instead of ../NameSpace-1.0/, so change format_external_xref() to match this. --- giscanner/docwriter.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index a0052d87..f5389cd9 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -1162,12 +1162,13 @@ class DevDocsFormatterGjs(DocFormatterGjs): def format_external_xref(self, node, attrdict, pluralize=False): ns = node.namespace + slug = ns.name.lower() + str(ns.version).replace('.', '') if not self.should_render_node(node): - target = '../%s-%s/%s' % (ns.name, str(ns.version), make_page_id(node.parent)) + target = '../%s/%s' % (slug, make_page_id(node.parent)) return self._write_xref_markdown(target, self.make_anchor(node), self.format_page_name(node.parent), pluralize=pluralize) - target = '../%s-%s/%s' % (ns.name, str(ns.version), make_page_id(node)) + target = '../%s/%s' % (slug, make_page_id(node)) return self._write_xref_markdown(target, None, self.format_page_name(node), pluralize=pluralize) -- cgit v1.2.1 From 916c626a4e17f356eaa5b73b9e67aaaab310e212 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 12 Dec 2015 16:14:07 -0800 Subject: devdocs: Mark links to other GIRs as such DevDocs will try to normalize links relative to the current documentation if it can, and strips ../ off the front, so e.g. a link on the gio20/gio.file page to ../gobject20/gobject.object will end up resolving to http:///gio20/gobject20/gobject.object, which doesn't exist. We clearly mark links to other GIRs with a gir:// URL scheme that DevDocs won't process automatically, and then fill in the links ourselves in the DevDocs scraper. --- giscanner/docwriter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index f5389cd9..d79b3fc7 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -1164,11 +1164,11 @@ class DevDocsFormatterGjs(DocFormatterGjs): ns = node.namespace slug = ns.name.lower() + str(ns.version).replace('.', '') if not self.should_render_node(node): - target = '../%s/%s' % (slug, make_page_id(node.parent)) + target = 'gir:///%s/%s' % (slug, make_page_id(node.parent)) return self._write_xref_markdown(target, self.make_anchor(node), self.format_page_name(node.parent), pluralize=pluralize) - target = '../%s/%s' % (slug, make_page_id(node)) + target = 'gir:///%s/%s' % (slug, make_page_id(node)) return self._write_xref_markdown(target, None, self.format_page_name(node), pluralize=pluralize) -- cgit v1.2.1 From cd7b575d7a2c0cb1e31221be03dc447280d7999c Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 13 Dec 2015 21:58:27 -0800 Subject: devdocs: Add extra CSS class to default.tmpl We add an extra CSS class to default.tmpl to indicate what kind of AST node is represented here (e.g., ast.Constant). This should properly belong in get_node_kind() in docwriter.py, but adding extra kinds there would affect the way that all the other documentation output formats are generated. --- giscanner/doctemplates/devdocs/Gjs/base.tmpl | 4 +++- giscanner/doctemplates/devdocs/Gjs/default.tmpl | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/giscanner/doctemplates/devdocs/Gjs/base.tmpl b/giscanner/doctemplates/devdocs/Gjs/base.tmpl index 3ca46a3e..913fa0cc 100644 --- a/giscanner/doctemplates/devdocs/Gjs/base.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/base.tmpl @@ -2,7 +2,7 @@
-

+

${formatter.format_page_name(node)}

<%include file="_index.tmpl"/> @@ -17,3 +17,5 @@
+ +<%def name="extra_class()"/> diff --git a/giscanner/doctemplates/devdocs/Gjs/default.tmpl b/giscanner/doctemplates/devdocs/Gjs/default.tmpl index 0c0fdf6c..2341ef4d 100644 --- a/giscanner/doctemplates/devdocs/Gjs/default.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/default.tmpl @@ -8,3 +8,11 @@

% endif + +## This should belong in get_node_kind(), but we don't want to change the way +## all the other templates work. +<%def name="extra_class()"> + % if isinstance(node, ast.Constant): + constant + % endif + -- cgit v1.2.1 From 88957d28a02117f8768ebd6d71fc2cc5e5cc7e06 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 13 Dec 2015 21:59:49 -0800 Subject: devdocs: Describe aliases more thoroughly For aliases we add a description of what Javascript type they map to. --- giscanner/doctemplates/devdocs/Gjs/default.tmpl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/giscanner/doctemplates/devdocs/Gjs/default.tmpl b/giscanner/doctemplates/devdocs/Gjs/default.tmpl index 2341ef4d..4b08adff 100644 --- a/giscanner/doctemplates/devdocs/Gjs/default.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/default.tmpl @@ -8,11 +8,27 @@ % endif +% if isinstance(node, ast.Alias): +
+
Equivalent Type
+
+ + % if node.target.target_fundamental: + ${formatter.format_fundamental_type(node.target.target_fundamental)} + % else: + ${node.target.target_giname} + % endif + +
+
+% endif ## This should belong in get_node_kind(), but we don't want to change the way ## all the other templates work. <%def name="extra_class()"> % if isinstance(node, ast.Constant): constant + % elif isinstance(node, ast.Alias): + alias % endif -- cgit v1.2.1 From d1ca314d0b5f6ad44825514cc1e41917735a31f3 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 13 Dec 2015 22:34:34 -0800 Subject: devdocs: Fix links to enum members Links to enum members, e.g. GLib.MyEnum.FOO, were previously formatted as GLib.MyEnum.foo, so we add this special case for nodes that are ast.Members. --- giscanner/docwriter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index d79b3fc7..e5a025ba 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -1155,8 +1155,11 @@ class DevDocsFormatterGjs(DocFormatterGjs): if not self.should_render_node(node): # Non-toplevel nodes are linked to the main page. page = make_page_id(node.parent) + name = node.name + if isinstance(node, ast.Member): + name = name.upper() return self._write_xref_markdown(page, self.make_anchor(node), - page + "." + node.name, + page + "." + name, pluralize=pluralize) return self._write_xref_markdown(make_page_id(node), pluralize=pluralize) -- cgit v1.2.1 From 0a9b0d8c8d7e89f7ff639f5bc8ff3ffdc6abccb7 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 13 Dec 2015 22:35:52 -0800 Subject: devdocs: Format in and out parameters correctly Previously the functions template did not properly use formatter.get_in_parameters() and formatter.get_out_parameters(), so we had inaccurate function arguments in the documentation. In particular, I originally didn't take functions with multiple return values into account. --- giscanner/doctemplates/devdocs/Gjs/_method.tmpl | 27 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl index 71569946..59e9ab8b 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl @@ -9,11 +9,15 @@
Type:
Virtual
% endif - % if m.parameters: + <% + in_params = formatter.get_in_parameters(m) + out_params = formatter.get_out_parameters(m) + %> + % if in_params:
Parameters:
    - % for p in m.parameters: + % for p in in_params:
  • ${p.argname} (${formatter.format_type(p.type)}) @@ -25,13 +29,22 @@
% endif - % if m.retval.type != ast.TYPE_NONE: + % if out_params:
Returns:
- (${formatter.format_type(m.retval.type)}) - % if m.retval.doc: - ${formatter.format_inline(m, m.retval.doc)} - % endif +
    + % for p in out_params: +
  • + % if len(out_params) > 1: + ${p.argname} + % endif + (${formatter.format_type(p.type)}) + % if p.doc: + — ${formatter.format_inline(m, p.doc)} + % endif +
  • + % endfor +
% endif -- cgit v1.2.1 From d69aad5810fb35a4b38796f9378787bc08a9a981 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 13 Dec 2015 22:49:50 -0800 Subject: devdocs: Mention when a function throws an error This uses the "throws" annotation in the generated docs, adding a "Throws exception: Yes" if the annotation is present. --- giscanner/doctemplates/devdocs/Gjs/_method.tmpl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl index 59e9ab8b..6619eb9e 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl @@ -47,6 +47,10 @@ % endif + % if m.throws: +
Throws exception:
+
Yes
+ % endif -- cgit v1.2.1 From 9d0c3e1551b1f92935efb02a15df4f6e54b537fd Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Wed, 3 Feb 2016 10:11:33 -0800 Subject: devdocs: Distinguish between versioning notes Previously, Since:, Deprecated:, and Stability: annotations were all given the same CSS class. In order to style them differently, we give them different classes. --- giscanner/doctemplates/devdocs/Gjs/_doc.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl index b8a2d7a6..d645df17 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl @@ -1,19 +1,19 @@ <%def name="format_documentation(node)"> % if node.version: -

+

New in version ${node.version}. ${formatter.format_inline(node, node.version_doc)}

% endif % if node.deprecated: -

+

Deprecated since ${node.deprecated}. ${formatter.format_inline(node, node.deprecated_doc)}

% endif % if node.stability: ## Not sure what this looks like in the wild -

+

Stability: ${node.stability}. ${formatter.format_inline(node, node.stability_doc)}

-- cgit v1.2.1 From fc39530d66d921331ced5a0b6607e9106c8d1647 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Tue, 9 Feb 2016 22:24:15 -0800 Subject: docwriter: Handle invalid nodes better Cogl-2.0.gir has the following entry: ... ... ... The prefix is not picked up correctly and so we get a member without a name, which crashes the docwriter in to_underscore(). Change that function to handle this case by giving it a dummy "anonymous member" name. --- giscanner/docwriter.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index e5a025ba..754787e3 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -28,6 +28,7 @@ from __future__ import unicode_literals import os import re +import sys import tempfile from xml.sax import saxutils @@ -1131,6 +1132,15 @@ class DevDocsFormatterGjs(DocFormatterGjs): link += "#" + anchor return "[{}]({}){}".format(display_name, link, 's' if pluralize else '') + def to_underscores(self, node): + try: + return super(DevDocsFormatterGjs, self).to_underscores(node) + except Exception as e: + if e.message == 'invalid node': + print('warning: invalid node in', node.parent.name, + file=sys.stderr) + return node.parent.name + '_invalid_node' + def make_anchor(self, node): style_class = get_node_kind(node) return "{}-{}".format(style_class, self.to_underscores(node)) -- cgit v1.2.1 From 13635f61c8c22d33832f3e88a0d1d728a7c748b3 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 7 May 2017 20:26:36 -0700 Subject: docwriter: Handle unknown language MIME types Add "plain" -> "text/plain" to the mapping since "plain" is used several times in the GTK documentation. But also, fix the code that falls back to no syntax highlighting for an unknown language - it did not check for KeyError. --- giscanner/docwriter.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index 754787e3..6b14f72b 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -57,6 +57,7 @@ language_mimes = { "pascal": "text/x-pascal", "perl": "application/x-perl", "php": "application/x-php", + "plain": "text/plain", "python": "text/x-python", "ruby": "application/x-ruby", "sql": "text/x-sql", @@ -359,11 +360,12 @@ class DocFormatter(object): return '

\n    '
 
     def _process_code_start_with_language(self, node, match, props):
-        mime = language_mimes[props["language_name"].lower()]
         self._processing_code = True
-        if not mime:
+        try:
+            mime = language_mimes[props["language_name"].lower()]
+            return '

\n    '
+        except KeyError:
             return '

\n    '
-        return '

\n    '
 
     def _process_code_end(self, node, match, props):
         self._processing_code = False
-- 
cgit v1.2.1


From 78a238d75272453814f002d5b6255ea905f23771 Mon Sep 17 00:00:00 2001
From: makepost 
Date: Sun, 17 Dec 2017 18:27:09 +0200
Subject: docwriter: Gdk.Atom as String

Reflect new string/GdkAtom marshalling that improves clipboard support: https://gitlab.gnome.org/GNOME/gjs/merge_requests/29
---
 giscanner/docwriter.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py
index 6b14f72b..38102bf8 100644
--- a/giscanner/docwriter.py
+++ b/giscanner/docwriter.py
@@ -881,6 +881,8 @@ class DocFormatterGjs(DocFormatterIntrospectableBase):
             return "void"
         elif type_.target_giname is not None:
             giname = type_.target_giname
+            if giname == 'Gdk.Atom':
+                return 'String'
             if giname in ('GLib.ByteArray', 'GLib.Bytes'):
                 return 'ByteArray'
             if giname == 'GObject.Value':
-- 
cgit v1.2.1


From f0434e06d4e201be7740a5b4d3c33e26183e8d8e Mon Sep 17 00:00:00 2001
From: rockon999 
Date: Mon, 6 Aug 2018 02:55:14 -0500
Subject: Convert FORMATS to tuple.

---
 giscanner/docmain.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/giscanner/docmain.py b/giscanner/docmain.py
index 0120022b..f184014b 100644
--- a/giscanner/docmain.py
+++ b/giscanner/docmain.py
@@ -32,7 +32,7 @@ from .docwriter import DocWriter
 from .sectionparser import generate_sections_file, write_sections_file
 from .transformer import Transformer
 
-FORMATS = ['devdocs', 'mallard', 'sections']
+FORMATS = ('devdocs', 'mallard', 'sections')
 
 
 def doc_main(args):
-- 
cgit v1.2.1


From 5e6266e576d94ad298202c493d045c57cfe4f87f Mon Sep 17 00:00:00 2001
From: rockon999 
Date: Tue, 29 May 2018 20:23:41 -0400
Subject: Only output introspectable methods.

---
 giscanner/doctemplates/devdocs/Gjs/_doc.tmpl        |  6 ++++++
 giscanner/doctemplates/devdocs/Gjs/_index.tmpl      | 10 ++++++++++
 giscanner/doctemplates/devdocs/Gjs/_method.tmpl     | 21 ++++++++++++---------
 giscanner/doctemplates/devdocs/Gjs/_properties.tmpl |  2 ++
 giscanner/doctemplates/devdocs/Gjs/_signals.tmpl    |  2 ++
 giscanner/doctemplates/devdocs/Gjs/method.tmpl      |  1 +
 6 files changed, 33 insertions(+), 9 deletions(-)
 create mode 100644 giscanner/doctemplates/devdocs/Gjs/method.tmpl

diff --git a/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl
index d645df17..dbdb8259 100644
--- a/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl
+++ b/giscanner/doctemplates/devdocs/Gjs/_doc.tmpl
@@ -29,3 +29,9 @@
     deprecated
   % endif
 
+
+<%def name="introspectable(node)">
+  % if getattr(node, "introspectable", True):
+    ${caller.body()}
+  % endif
+
diff --git a/giscanner/doctemplates/devdocs/Gjs/_index.tmpl b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl
index f9847cdc..f3d588ae 100644
--- a/giscanner/doctemplates/devdocs/Gjs/_index.tmpl
+++ b/giscanner/doctemplates/devdocs/Gjs/_index.tmpl
@@ -67,6 +67,7 @@
     

- - ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) -
- - ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) -
${p.name} + ${p.name} + ${formatter.format_type(p.type)} ${formatter.format_property_flags(p, abbrev=True)}
+ ${s.name}(${formatter.format_in_parameters(s)})
${f.name} + + ${f.name} + + ${formatter.format_type(f.type)} ${formatter.format_property_flags(f, abbrev=True)}
% for m in methods: + <%doc:introspectable node="${m}"> % if m in static_methods: @@ -75,6 +76,7 @@ % endif ${format_function_cell(m)} + % endfor
static
@@ -88,9 +90,11 @@ % for m in node.virtual_methods: + <%doc:introspectable node="${m}"> ${format_function_cell(m)} + % endfor
@@ -111,6 +115,7 @@ % for p in node.properties: + <%doc:introspectable node="${p}"> ${p.name} @@ -118,6 +123,7 @@ ${formatter.format_type(p.type)} ${formatter.format_property_flags(p, abbrev=True)} + % endfor @@ -131,12 +137,14 @@ % for s in node.signals: + <%doc:introspectable node="${s}"> + % endfor
${s.name}(${formatter.format_in_parameters(s)})
@@ -158,6 +166,7 @@ % for f in non_private_fields: + <%doc:introspectable node="${f}"> @@ -174,6 +183,7 @@ % endif + % endfor diff --git a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl index 6619eb9e..57520465 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_method.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_method.tmpl @@ -55,14 +55,17 @@ <%def name="method(m, static=False, virtual=False)"> - <% invocation = ", ".join(map(lambda p: p.argname, m.parameters)) %> -

- + <% invocation = ", ".join(map(lambda p: p.argname, m.parameters)) %> + +

+ - ${formatter.format_function_name(m)}(${formatter.format_in_parameters(m)}) -

- ${describe_parameters(m, static, virtual)} - ${doc.format_documentation(m)} + ${formatter.format_function_name(m)}
(${formatter.format_in_parameters(m)}) +

+ ${describe_parameters(m, static, virtual)} + ${doc.format_documentation(m)} + diff --git a/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl index b67d75ae..a7054727 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_properties.tmpl @@ -10,6 +10,7 @@ % if getattr(node, 'properties', []):

Property Details

% for p in node.properties: + <%doc:introspectable node="${p}">

${p.name | dash_to_underscore} @@ -32,5 +33,6 @@ % if p.doc: ${doc.format_documentation(p)} % endif + % endfor % endif diff --git a/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl index 7b39d5fc..cda46bd5 100644 --- a/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/_signals.tmpl @@ -3,6 +3,7 @@ % if getattr(node, 'signals', []):

Signal Details

% for s in node.signals: + <%doc:introspectable node="${s}">

@@ -16,5 +17,6 @@ ${method.describe_parameters(s)} ${doc.format_documentation(s)} + % endfor % endif diff --git a/giscanner/doctemplates/devdocs/Gjs/method.tmpl b/giscanner/doctemplates/devdocs/Gjs/method.tmpl new file mode 100644 index 00000000..2c997c09 --- /dev/null +++ b/giscanner/doctemplates/devdocs/Gjs/method.tmpl @@ -0,0 +1 @@ +<%inherit file="function.tmpl"/> \ No newline at end of file -- cgit v1.2.1 From c67fbbf6b3c61748f4daf425a7cae475dbbb0bdd Mon Sep 17 00:00:00 2001 From: rockon999 Date: Mon, 6 Aug 2018 21:04:43 -0500 Subject: Sort index files by type. --- giscanner/doctemplates/devdocs/Gjs/namespace.tmpl | 57 ++++++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl b/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl index 5a90634a..8f5a4e7e 100644 --- a/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl +++ b/giscanner/doctemplates/devdocs/Gjs/namespace.tmpl @@ -1,14 +1,57 @@ +<%def name="get_types(n, types)"> + <% nodes = [] %> + % for a in n.values(): + % if isinstance(a, types): + % if formatter.should_render_node(a): + <% nodes.append(a) %> + % endif + % endif + % endfor + <% return nodes %> + + +<%def name="render_list(nodes)"> +
    + % for a in nodes: +
  • ${formatter.format_inline(a, formatter.format_xref(a))}
  • + % endfor +
+ +

${node.name}

-
    - % for n in node.values(): - % if formatter.should_render_node(n): -
  • ${formatter.format_inline(n, formatter.format_xref(n))}
  • - % endif - % endfor -
+ + <% nodes = get_types(node, (ast.Class, ast.Interface)) %> + % if len(nodes) > 0: +

Classes

+ ${render_list(nodes)} + % endif + + <% nodes = get_types(node, (ast.Enum)) %> + % if len(nodes) > 0: +

Enums

+ ${render_list(nodes)} + % endif + + <% nodes = get_types(node, (ast.Function)) %> + % if len(nodes) > 0: +

Functions

+ ${render_list(nodes)} + % endif + + <% nodes = get_types(node, (ast.Constant)) %> + % if len(nodes) > 0: +

Constants

+ ${render_list(nodes)} + % endif + + <% nodes = get_types(node, (ast.Property)) %> + % if len(nodes) > 0: +

Properties

+ ${render_list(nodes)} + % endif -- cgit v1.2.1 From c8eb3be09ec2bda9494e2e62791f3fb6fe222dd9 Mon Sep 17 00:00:00 2001 From: rockon999 Date: Wed, 8 Aug 2018 14:10:53 -0500 Subject: Improve markdown compatibility of docwriter. --- giscanner/docwriter.py | 93 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index 38102bf8..590fd891 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -34,6 +34,7 @@ import tempfile from xml.sax import saxutils from mako.lookup import TemplateLookup import markdown +from markdown.extensions.headerid import HeaderIdExtension from . import ast, xmlwriter from .utils import to_underscores @@ -64,7 +65,6 @@ language_mimes = { "yaml": "application/x-yaml", } - def make_page_id(node, recursive=False): if isinstance(node, ast.Namespace): if recursive: @@ -192,14 +192,17 @@ class TemplatedScanner(object): class DocstringScanner(TemplatedScanner): def __init__(self): specs = [ - ('new_paragraph', r'\n\n'), - ('new_line', r'\n'), ('!alpha', r'[a-zA-Z0-9_]+'), ('!alpha_dash', r'[a-zA-Z0-9_-]+'), ('code_start_with_language', - r'\|\[\>\"\s*\-\-\>'), + r'\|\[\>\"\s*\-\-\>'), ('code_start', r'\|\['), ('code_end', r'\]\|'), + ('html_code_start', r''), + ('html_code_end', r'
'), + ('markdown_code_toggle', r'\`'), + ('markdown_attr_start', r'\{'), + ('markdown_attr_end', r'\}'), ('property', r'#<>:(<>)'), ('signal', r'#<>::(<>)'), ('type_name', r'#(<>)'), @@ -219,9 +222,13 @@ class DocFormatter(object): # https://wiki.gnome.org/Projects/GTK%2B/DocumentationSyntax/Markdown # we won't insert paragraphs and will respect new lines. self._processing_code = False + self._processing_attr = False def escape(self, text): return saxutils.escape(text) + + def unescape(self, text): + return saxutils.unescape(text) def should_render_node(self, node): if getattr(node, "private", False): @@ -275,6 +282,8 @@ class DocFormatter(object): raise KeyError("Could not find %s" % (name, )) def _process_other(self, node, match, props): + if self._processing_code: + return match return self.escape(match) def _process_property(self, node, match, props): @@ -302,6 +311,9 @@ class DocFormatter(object): return self.format_xref(signal) def _process_type_name(self, node, match, props): + if self._processing_attr: + return match + ident = props['type_name'] type_ = self._resolve_type(ident) plural = False @@ -354,31 +366,66 @@ class DocFormatter(object): # # A better solution would be to replace DocstringScanner by Markdown # entirely, implementing the custom markup with Markdown extensions. + # + # UPDATE: As a temporary fix for code blocks we will convert directly to ``` syntax. + # + # NOTES: + # _process_markdown_code_toggle: + # Whenever we encounter ` we need to toggle whether we are escaping text as text inside + # inline code blocks is unescaped + # _process_markdown_attr_(start|end): + # Whenever we encounter { or } we must stop parsing type names as curly braces are used for + # attributes in GIR files in addition to type declarations. + # _process_html_code_(start|end): + # Whenever we encounter an HTML block we must stop escaping text. + # + # TODO: Convert to markdown extensions. + + def _process_markdown_code_toggle(self, node, match, props): + self._processing_code = not self._processing_code + return match + + def _process_markdown_attr_start(self, node, match, props): + if not self._processing_code: + self._processing_attr = True + return match + + def _process_markdown_attr_end(self, node, match, props): + if not self._processing_code: + self._processing_attr = False + return match + + def _process_html_code_start(self, node, match, props): + self._processing_code = True + return match + + def _process_html_code_end(self, node, match, props): + self._processing_code = False + return match def _process_code_start(self, node, match, props): self._processing_code = True - return '

\n    '
+        return '

\n```\n' def _process_code_start_with_language(self, node, match, props): self._processing_code = True try: - mime = language_mimes[props["language_name"].lower()] - return '

\n    '
+            return '

\n```' + props["language_name"].lower() + '\n' except KeyError: - return '

\n    '
+            return '

\n```\n' def _process_code_end(self, node, match, props): self._processing_code = False - return '\n

' + return '\n```\n

' def _process_new_line(self, node, match, props): if self._processing_code: - return '\n ' + return '\n' return '\n' def _process_new_paragraph(self, node, match, props): if self._processing_code: - return '\n\n ' + return '\n\n' return "

" def _process_token(self, node, tok): @@ -395,6 +442,11 @@ class DocFormatter(object): 'code_start': self._process_code_start, 'code_start_with_language': self._process_code_start_with_language, 'code_end': self._process_code_end, + 'html_code_start': self._process_html_code_start, + 'html_code_end': self._process_html_code_end, + 'markdown_code_toggle': self._process_markdown_code_toggle, + 'markdown_attr_start': self._process_markdown_attr_start, + 'markdown_attr_end': self._process_markdown_attr_end, 'new_line': self._process_new_line, 'new_paragraph': self._process_new_paragraph, } @@ -1053,6 +1105,9 @@ class DocFormatterGjs(DocFormatterIntrospectableBase): class DevDocsFormatterGjs(DocFormatterGjs): + output_format = "devdocs" + output_extension = ".html" + def _is_static_method(self, node): if not hasattr(node.parent, "static_methods"): return False @@ -1112,7 +1167,13 @@ class DevDocsFormatterGjs(DocFormatterGjs): return '' cleaned_up_gtkdoc = super(DevDocsFormatterGjs, self).format_inline(node, doc) - return markdown.markdown(cleaned_up_gtkdoc) + return markdown.markdown(cleaned_up_gtkdoc, extensions=[ + InlineMarkdown(), + 'markdown.extensions.fenced_code', + 'markdown.extensions.nl2br', + 'markdown.extensions.attr_list', + HeaderIdExtension(forceid=False) + ]) def format_function_name(self, func): name = func.name @@ -1194,7 +1255,13 @@ class DevDocsFormatterGjs(DocFormatterGjs): if para is None: return '' cleaned_up_gtkdoc = super(DevDocsFormatterGjs, self).format_inline(node, para) - return markdown.markdown(cleaned_up_gtkdoc, extensions=[InlineMarkdown()]) + return markdown.markdown(cleaned_up_gtkdoc, extensions=[ + InlineMarkdown(), + 'markdown.extensions.fenced_code', + 'markdown.extensions.nl2br', + 'markdown.extensions.attr_list', + HeaderIdExtension(forceid=False) + ]) def format_in_parameters(self, node): return ', '.join(p.argname for p in self.get_in_parameters(node)) -- cgit v1.2.1 From 48d348ac822234d898119d8a2118c2bb07145dd1 Mon Sep 17 00:00:00 2001 From: rockon999 Date: Mon, 13 Aug 2018 23:56:53 -0500 Subject: Fix format/format_inline distinction. - Fix autopep8 errors. --- giscanner/docwriter.py | 14 +++++++------- giscanner/mdextensions.py | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index 590fd891..d49446a0 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -65,6 +65,7 @@ language_mimes = { "yaml": "application/x-yaml", } + def make_page_id(node, recursive=False): if isinstance(node, ast.Namespace): if recursive: @@ -226,7 +227,7 @@ class DocFormatter(object): def escape(self, text): return saxutils.escape(text) - + def unescape(self, text): return saxutils.unescape(text) @@ -368,7 +369,7 @@ class DocFormatter(object): # entirely, implementing the custom markup with Markdown extensions. # # UPDATE: As a temporary fix for code blocks we will convert directly to ``` syntax. - # + # # NOTES: # _process_markdown_code_toggle: # Whenever we encounter ` we need to toggle whether we are escaping text as text inside @@ -384,12 +385,12 @@ class DocFormatter(object): def _process_markdown_code_toggle(self, node, match, props): self._processing_code = not self._processing_code return match - + def _process_markdown_attr_start(self, node, match, props): if not self._processing_code: self._processing_attr = True return match - + def _process_markdown_attr_end(self, node, match, props): if not self._processing_code: self._processing_attr = False @@ -398,7 +399,7 @@ class DocFormatter(object): def _process_html_code_start(self, node, match, props): self._processing_code = True return match - + def _process_html_code_end(self, node, match, props): self._processing_code = False return match @@ -1107,7 +1108,7 @@ class DocFormatterGjs(DocFormatterIntrospectableBase): class DevDocsFormatterGjs(DocFormatterGjs): output_format = "devdocs" output_extension = ".html" - + def _is_static_method(self, node): if not hasattr(node.parent, "static_methods"): return False @@ -1168,7 +1169,6 @@ class DevDocsFormatterGjs(DocFormatterGjs): cleaned_up_gtkdoc = super(DevDocsFormatterGjs, self).format_inline(node, doc) return markdown.markdown(cleaned_up_gtkdoc, extensions=[ - InlineMarkdown(), 'markdown.extensions.fenced_code', 'markdown.extensions.nl2br', 'markdown.extensions.attr_list', diff --git a/giscanner/mdextensions.py b/giscanner/mdextensions.py index 97be4ed1..16af4fc3 100644 --- a/giscanner/mdextensions.py +++ b/giscanner/mdextensions.py @@ -1,6 +1,5 @@ from markdown.extensions import Extension from markdown.treeprocessors import Treeprocessor -from markdown.util import etree class RemoveOuterP(Treeprocessor): -- cgit v1.2.1