]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
gir-importer: markdown: resolve internal links
authorFlorian Brosch <flo.brosch@gmail.com>
Mon, 25 Aug 2014 19:58:09 +0000 (21:58 +0200)
committerFlorian Brosch <flo.brosch@gmail.com>
Fri, 29 Aug 2014 13:52:54 +0000 (15:52 +0200)
14 files changed:
src/doclets/gtkdoc/commentconverter.vala
src/libvaladoc/Makefile.am
src/libvaladoc/content/inlinecontent.vala
src/libvaladoc/content/link.vala
src/libvaladoc/content/symbollink.vala
src/libvaladoc/documentation/documentationparser.vala
src/libvaladoc/documentation/girmetadata.vala
src/libvaladoc/documentation/gtkdocmarkdownparser.vala
src/libvaladoc/gtkdocrenderer.vala
src/libvaladoc/html/htmlmarkupwriter.vala
src/libvaladoc/html/htmlrenderer.vala
src/libvaladoc/importer/girdocumentationimporter.vala
src/libvaladoc/importer/internalidregistrar.vala [new file with mode: 0644]
src/libvaladoc/taglets/tagletlink.vala

index 91ab7591cbd6cf538d9b3a2977841a879264dc7a..cdf85ea6a0d5ddaffa39eb987b2adeb177d98cb4 100644 (file)
@@ -92,7 +92,7 @@ public class Gtkdoc.CommentConverter : ContentVisitor {
                        current_builder.append (link.name);
                }
        }
-  
+
        public override void visit_link (Link link) {
                current_builder.append_printf ("<ulink url=\"%s\">", link.url);
                link.accept_children (this);
@@ -104,15 +104,15 @@ public class Gtkdoc.CommentConverter : ContentVisitor {
                        // If the symbol is a method and it doesn't have a constructor, fall back to linking to the class
                        if (sl.symbol is Method && ((Method) sl.symbol).is_constructor &&
                            ((Method) sl.symbol).parent is Class && ((Class) ((Method) sl.symbol).parent).is_abstract) {
-                               current_builder.append (get_docbook_link (((Method) sl.symbol).parent, is_dbus) ?? sl.label);
+                               current_builder.append (get_docbook_link (((Method) sl.symbol).parent, is_dbus) ?? sl.given_symbol_name);
                        } else {
-                               current_builder.append (get_docbook_link (sl.symbol, is_dbus) ?? sl.label);
+                               current_builder.append (get_docbook_link (sl.symbol, is_dbus) ?? sl.given_symbol_name);
                        }
                } else {
-                       current_builder.append (sl.label);
+                       current_builder.append (sl.given_symbol_name);
                }
        }
-  
+
        public override void visit_list (Content.List list) {
                string tag = "orderedlist";
                switch (list.bullet) {
index 84cebd817f7c02cadfb9c7e2182ca2a9553a54ba..a4870eeb5cc27f921b447ce46143d09b58c31819 100644 (file)
@@ -60,6 +60,7 @@ libvaladoc_la_VALASOURCES = \
        importer/valadocdocumentationimporter.vala \
        importer/valadocdocumentationimporterscanner.vala \
        importer/girdocumentationimporter.vala \
+       importer/internalidregistrar.vala \
        api/symbolaccessibility.vala \
        api/sourcecomment.vala \
        api/girsourcecomment.vala \
index aca48c20c479c717e927d149d5fde27a3d9ff314..f67ee4e1af5e1f69e410617723edbf60816009a2 100644 (file)
@@ -64,5 +64,12 @@ public abstract class Valadoc.Content.InlineContent : ContentElement {
 
                return true;
        }
+
+       internal void replace_node (Inline old, Inline replacement) {
+               int index = _content.index_of (old);
+               assert (index >= 0);
+
+               _content.set (index, replacement);
+       }
 }
 
index 6f3bd709a1bf31e81f3220445c11e2310329a672..2dad00a665236c1575a95ef35da4b85dcc754ea4 100644 (file)
@@ -1,7 +1,7 @@
 /* link.vala
  *
  * Copyright (C) 2008-2009 Didier Villevalois
- * Copyright (C) 2008-2012 Florian Brosch
+ * Copyright (C) 2008-2014 Florian Brosch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,10 +26,19 @@ using Gee;
 
 public class Valadoc.Content.Link : InlineContent, Inline {
        public string url {
-               get;
                set;
+               get;
+       }
+
+       /**
+        * Used by importers to transform internal URLs
+        */
+       public Importer.InternalIdRegistrar id_registrar {
+               internal set;
+               get;
        }
 
+
        internal Link () {
                base ();
        }
@@ -40,8 +49,45 @@ public class Valadoc.Content.Link : InlineContent, Inline {
        public override void check (Api.Tree api_root, Api.Node container, string file_path,
                                                                ErrorReporter reporter, Settings settings)
        {
-               base.check (api_root, container, file_path, reporter, settings);
+       
+               // Internal gktdoc-id? (gir-importer)
+               if (id_registrar != null) {
+                       Api.Node? node = id_registrar.map_symbol_id (url);
+                       if (node != null) {
+                               InlineContent _parent = parent as InlineContent;
+                               assert (_parent != null);
+
+                               SymbolLink replacement = new SymbolLink (node);
+                               replacement.content.add_all (content);
+
+                               replacement.check (api_root, container, file_path, reporter, settings);
+                               _parent.replace_node (this, replacement);
+                               return ;
+                       }               
+
+
+                       string _url = id_registrar.map_url_id (url);
+                       if (_url == null) {
+                               string node_segment = (container is Api.Package)? "" : container.get_full_name () + ": ";
+                               reporter.simple_warning ("%s: %s[[: warning: unknown imported internal id `%s'", file_path, node_segment, url);
+
+                               InlineContent _parent = parent as InlineContent;
+                               assert (_parent != null);
+
+                               Run replacement = new Run (Run.Style.ITALIC);
+                               replacement.content.add_all (content);
+                               replacement.check (api_root, container, file_path, reporter, settings);
+
+                               _parent.replace_node (this, replacement);
+                               return ;
+                       }
+
+                       url = _url;
+               }
+
+
                //TODO: check url
+               base.check (api_root, container, file_path, reporter, settings);
        }
 
        public override void accept (ContentVisitor visitor) {
@@ -54,6 +100,7 @@ public class Valadoc.Content.Link : InlineContent, Inline {
 
        public override ContentElement copy (ContentElement? new_parent = null) {
                Link link = new Link ();
+               link.id_registrar = id_registrar;
                link.parent = new_parent;
                link.url = url;
 
index 0f49b74302d292b49d6f20f05544f84a2883b2db..70e5284958497aa52f5253cec8d84dfab6830460 100644 (file)
@@ -1,7 +1,7 @@
 /* symbollink.vala
  *
  * Copyright (C) 2008-2009 Didier Villevalois
- * Copyright (C) 2008-2012 Florian Brosch
+ * Copyright (C) 2008-2014 Florian Brosch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 using Gee;
 
 
-public class Valadoc.Content.SymbolLink : ContentElement, Inline {
+public class Valadoc.Content.SymbolLink : InlineContent, Inline {
        public Api.Node symbol {
                get;
                set;
        }
 
-       public string label {
+       public string given_symbol_name {
                get;
                set;
        }
 
-       internal SymbolLink (Api.Node? symbol = null, string? label = null) {
+       internal SymbolLink (Api.Node? symbol = null, string? given_symbol_name = null) {
                base ();
                _symbol = symbol;
-               _label = label;
+               _given_symbol_name = given_symbol_name;
        }
 
        public override void configure (Settings settings, ResourceLocator locator) {
@@ -58,8 +58,14 @@ public class Valadoc.Content.SymbolLink : ContentElement, Inline {
        }
 
        public override ContentElement copy (ContentElement? new_parent = null) {
-               SymbolLink link = new SymbolLink (symbol, label);
+               SymbolLink link = new SymbolLink (symbol, _given_symbol_name);
                link.parent = new_parent;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (link) as Inline;
+                       link.content.add (copy);
+               }
+
                return link;
        }
 }
index 3dde0b886dfdfa0e6d05f1fb8de6493315b7e6b7..4ca6aef2b6ee511478819676f728909fe0f3ddfd 100644 (file)
@@ -27,7 +27,9 @@ using Gee;
 
 
 public class Valadoc.DocumentationParser : Object, ResourceLocator {
-       private HashMap<Api.SourceFile, GirMetaData> metadata = new HashMap<Api.SourceFile, GirMetaData> ();
+       private HashMap<Api.SourceFile, GirMetaData> metadata;
+       private Importer.InternalIdRegistrar id_registrar;
+
 
        public DocumentationParser (Settings settings, ErrorReporter reporter,
                                                                Api.Tree tree, ModuleLoader modules)
@@ -50,6 +52,10 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
                gtkdoc_parser = new Gtkdoc.Parser (settings, reporter, tree, modules);
                gtkdoc_markdown_parser = new Gtkdoc.MarkdownParser (settings, reporter, tree, modules);
 
+
+               metadata = new HashMap<Api.SourceFile, GirMetaData> ();
+               id_registrar = new Importer.InternalIdRegistrar ();
+
                init_valadoc_rules ();
        }
 
@@ -79,7 +85,7 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
                                Comment doc_comment = gtkdoc_parser.parse (element, gir_comment, metadata);
                                return doc_comment;
                        } else {
-                               Comment doc_comment = gtkdoc_markdown_parser.parse (element, gir_comment, metadata);
+                               Comment doc_comment = gtkdoc_markdown_parser.parse (element, gir_comment, metadata, id_registrar);
                                return doc_comment;
                        }
                } else {
@@ -166,6 +172,10 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
                }
 
                metadata = new GirMetaData (gir_comment.file.relative_path, _settings.metadata_directories, _reporter);
+               if (metadata.index_sgml != null) {
+                       id_registrar.read_index_sgml_file (metadata.index_sgml, _reporter);
+               }
+
                this.metadata.set (gir_comment.file, metadata);
                return metadata;
        }
index 41e2be8622ec2cc8ccda54085a616e154305b323..1a9909712a2d78bb6e08dedb81f77b8418e819a9 100644 (file)
@@ -1,6 +1,6 @@
 /* girmetadata.vala
  *
- * Copyright (C) 2012 Florian Brosch
+ * Copyright (C) 2012-2014 Florian Brosch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -20,6 +20,9 @@
  *     Brosch Florian <flo.brosch@gmail.com>
  */
 
+using Gee;
+
+
 /**
  * Metadata reader for GIR files
  */
@@ -27,7 +30,9 @@ public class Valadoc.GirMetaData : Object {
        private string? metadata_path = null;
        private string? resource_dir = null;
 
+
        public bool is_docbook { private set; get; default = false; }
+       public string index_sgml { private set; get; default = null; }
 
 
        /**
@@ -89,6 +94,10 @@ public class Valadoc.GirMetaData : Object {
                                this.is_docbook = key_file.get_boolean ("General", "is_docbook");
                                break;
 
+                       case "index_sgml":
+                               this.index_sgml = key_file.get_string ("General", "index_sgml");
+                               break;
+
                        default:
                                reporter.simple_warning ("%s: warning: Unknown key 'General.%s'", metadata_path, key);
                                break;
@@ -134,6 +143,9 @@ public class Valadoc.GirMetaData : Object {
                } catch (KeyFileError e) {
                        reporter.simple_error ("%s: error: %s", metadata_path, e.message);
                }
+
+
+               // Load internal link lut:
        }
 }
 
index 721572d1dcf1abf4d70c23c29caa0e97bd133a59..53dfe18aeab974437ddb32b5947bab789438bc2e 100644 (file)
@@ -40,6 +40,7 @@ public class Valadoc.Gtkdoc.MarkdownParser : Object, ResourceLocator {
        private Valadoc.Token preserved_token = null;
        private Regex regex_source_lang;
 
+       private Importer.InternalIdRegistrar id_registrar;
        private GirMetaData metadata;
        private Api.GirSourceComment gir_comment;
        private Api.Node element;
@@ -253,6 +254,7 @@ public class Valadoc.Gtkdoc.MarkdownParser : Object, ResourceLocator {
                                                                .set_reduce (() => {
                                                                        Link url = _factory.create_link ();
                                                                        url.url = pop_preserved_link ();
+                                                                       url.id_registrar = id_registrar;
 
                                                                        Run label = (Run) peek ();
                                                                        url.content.add_all (label.content);
@@ -517,8 +519,8 @@ public class Valadoc.Gtkdoc.MarkdownParser : Object, ResourceLocator {
                        }),
                        run,
                        Rule.option ({
-                               Valadoc.TokenType.MARKDOWN_HEADLINE_HASH.action (() => {
-                                       // TODO
+                               Valadoc.TokenType.MARKDOWN_HEADLINE_HASH.action ((token) => {
+                                       id_registrar.register_symbol (token.value, element);
                                })
                        }),
                        Valadoc.TokenType.MARKDOWN_HEADLINE_END
@@ -618,12 +620,12 @@ public class Valadoc.Gtkdoc.MarkdownParser : Object, ResourceLocator {
                comment.content.insert (1, note);
        }
 
-       public Comment? parse (Api.Node element, Api.GirSourceComment gir_comment, GirMetaData metadata, string? this_name = null) {
+       public Comment? parse (Api.Node element, Api.GirSourceComment gir_comment, GirMetaData metadata, Importer.InternalIdRegistrar id_registrar, string? this_name = null) {
                this.metadata = metadata;
+               this.id_registrar = id_registrar;
                this.gir_comment = gir_comment;
                this.element = element;
 
-
                // main:
                Comment? cmnt = _parse (gir_comment);
                if (cmnt != null) {
@@ -673,7 +675,8 @@ public class Valadoc.Gtkdoc.MarkdownParser : Object, ResourceLocator {
 
                this.metadata = null;
                this.gir_comment = null;
-               this.element = element;
+               this.id_registrar = null;
+               this.element = null;
 
                return cmnt;
        }
index 69ade76b4674db3b9af94931473e4e078044374b..877d7c5c9ad4d185dbf1f481d28b14867231ea34 100644 (file)
@@ -184,8 +184,20 @@ public class Valadoc.GtkdocRenderer : ContentRenderer {
        }
 
        public override void visit_symbol_link (SymbolLink element) {
+               if (element.content.size > 0) {
+                       writer.text ("\"");
+                       element.accept_children (this);
+                       writer.text ("\" (");
+                       visit_symbol_link (element);
+                       writer.text (")");
+               } else {
+                       visit_symbol_link (element);
+               }
+       }
+
+       public void write_symbol_link (SymbolLink element) {
                if (element.symbol == null) {
-                       writer.text (element.label);
+                       writer.text (element.given_symbol_name);
                } else {
                        write_docbook_link (element.symbol);
                }
index 3c2f0cfb82b15fdb3c3a00ead2e01955fb5c2c97..113f0c6f1af6387d7f19fea56255a570a83c6e25 100644 (file)
@@ -1,6 +1,6 @@
 /* markupwriter.vala
  *
- * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ * Copyright (C) 2008-2014 Florian Brosch, Didier Villevalois
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
index 294a9777730c64b18758eee37cc94482ee329ebc..84ba3f901b730a2f44791c7cb32d0a669a50a681 100644 (file)
@@ -1,6 +1,6 @@
 /* htmlrenderer.vala
  *
- * Copyright (C) 2008-20012 Florian Brosch, Didier Villevalois
+ * Copyright (C) 2008-20014 Florian Brosch, Didier Villevalois
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -62,26 +62,45 @@ public class Valadoc.Html.HtmlRenderer : ContentRenderer {
                return linker.get_relative_link (_container, symbol, settings);
        }
 
-       private void write_unresolved_symbol_link (string label) {
-               writer.start_tag ("code");
-               writer.text (label);
-               writer.end_tag ("code");
+       private void write_unresolved_symbol_link (string given_symbol_name, InlineContent? label_owner = null) {
+               if (label_owner == null || label_owner.content.size == 0) {
+                       writer.start_tag ("code");
+                       writer.text (given_symbol_name);
+                       writer.end_tag ("code");
+               } else {
+                       writer.start_tag ("i");
+                       label_owner.accept_children (this);
+                       writer.end_tag ("i");
+               }
        }
 
-       private void write_resolved_symbol_link (Api.Node symbol, string? given_label) {
-               var label = (given_label == null || given_label == "") ? symbol.get_full_name () : given_label;
-               if (symbol == _container || symbol == _owner) {
-                       writer.start_tag ("span", {"css", cssresolver.resolve (symbol)})
-                               .text (label)
-                               .end_tag ("span");
+       private void write_resolved_symbol_link (Api.Node symbol, string? given_symbol_name, InlineContent? label_owner = null) {
+               var symbol_name = (given_symbol_name == null || given_symbol_name == "") ? symbol.get_full_name () : given_symbol_name;
+               string href = (symbol == _container || symbol == _owner)? null : get_url (symbol);
+               string css_class = cssresolver.resolve (symbol);
+               string end_tag_name;
+
+
+               // Start Tag:
+               if (href != null) {
+                       writer.start_tag ("a", {"href", href, "class", css_class});
+                       end_tag_name = "a";
                } else {
-                       var url = get_url (symbol);
-                       if (url == null) {
-                               write_unresolved_symbol_link (label);
-                       } else {
-                               writer.link (url, label, cssresolver.resolve (symbol));
-                       }
+                       writer.start_tag ("span", {"class", css_class});
+                       end_tag_name = "span";
                }
+
+
+               // Content:
+               if (label_owner != null && label_owner.content.size > 0) {
+                       label_owner.accept_children (this);
+               } else {
+                       writer.text (symbol_name);
+               }
+
+
+               // End Tag:
+               writer.end_tag (end_tag_name);
        }
 
        private delegate void Write ();
@@ -325,9 +344,9 @@ public class Valadoc.Html.HtmlRenderer : ContentRenderer {
 
        public override void visit_symbol_link (SymbolLink element) {
                if (element.symbol == null) {
-                       write_unresolved_symbol_link (element.label);
+                       write_unresolved_symbol_link (element.given_symbol_name, element);
                } else {
-                       write_resolved_symbol_link (element.symbol, element.label);
+                       write_resolved_symbol_link (element.symbol, element.given_symbol_name, element);
                }
        }
 
index e4793f82e8940c821fcc1474befc7d065716f867..4186c27e7ea3d821f8cc8f6cbd51661936a3ccaa 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008-2010  Jürg Billeter
  * Copyright (C) 2011       Luca Bruno
- * Copyright (C) 2011-2012  Florian Brosch
+ * Copyright (C) 2011-2014  Florian Brosch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/src/libvaladoc/importer/internalidregistrar.vala b/src/libvaladoc/importer/internalidregistrar.vala
new file mode 100644 (file)
index 0000000..a9ece01
--- /dev/null
@@ -0,0 +1,88 @@
+/* gtkdocindexsgmlreader.vala
+ *
+ * Copyright (C) 2014  Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *  Florian Brosch <flo.brosch@gmail.com>
+ */
+
+using Valadoc;
+using Gee;
+
+
+public class Valadoc.Importer.InternalIdRegistrar {
+       private HashMap<string, Api.Node> symbol_map;
+       private HashMap<string, string> map;
+
+
+       public InternalIdRegistrar () {
+               map = new HashMap<string, string> ();
+               symbol_map = new HashMap<string, Api.Node> ();
+       }
+
+       
+       public void register_symbol (string id, Api.Node symbol) {
+               this.symbol_map.set (id, symbol);
+       }
+
+       public string? map_url_id (string id) {
+               return map.get (id);
+       }
+
+       public Api.Node? map_symbol_id (string id) {
+               return symbol_map.get (id);
+       }
+
+
+       public void read_index_sgml_file (string filename, string? index_sgml_online, ErrorReporter reporter) {
+               MarkupSourceLocation begin;
+               MarkupSourceLocation end;
+               MarkupTokenType token;
+
+               string base_path = index_sgml_online ?? realpath (filename);
+               var reader = new MarkupReader (filename, reporter);
+
+               while ((token = reader.read_token (out begin, out end)) != MarkupTokenType.EOF) {
+                       if (token == MarkupTokenType.START_ELEMENT && reader.name == "ONLINE") {
+                               if (index_sgml_online == null) {
+                                       base_path = reader.get_attribute ("href");
+                                       if (base_path == null) {
+                                               reporter.error (filename, begin.line, begin.column, end.column, reader.get_line_content (begin.line), "missing attribute `href' in <ONLINE>");
+                                       }
+                               }
+                       } else if (token == MarkupTokenType.START_ELEMENT && reader.name == "ANCHOR") {
+                               string id = reader.get_attribute ("id");
+                               if (id == null) {
+                                       reporter.error (filename, begin.line, begin.column, end.column, reader.get_line_content (begin.line), "missing attribute `id' in <ANCHOR>");
+                               }
+
+                               string href = reader.get_attribute ("href");
+                               if (href == null) {
+                                       reporter.error (filename, begin.line, begin.column, end.column, reader.get_line_content (begin.line), "missing attribute `href' in <ANCHOR>");
+                               } else if (index_sgml_online != null) {
+                                       href = Path.get_basename (href);
+                               }
+
+                               map.set (id, Path.build_path ("/", base_path, href));
+                       } else {
+                               reporter.error (filename, begin.line, begin.column, end.column, reader.get_line_content (begin.line), "expected element of <ONLINE> or <ANCHOR>");
+                       }
+               }
+       }
+}
+
+
index 82a41baef14729a455655510bd7585a8ca8002dc..990fe26e2f308f31d39bddf0b1f4849f84db8a4f 100644 (file)
@@ -1,7 +1,7 @@
 /* taglet.vala
  *
  * Copyright (C) 2008-2009 Didier Villevalois
- * Copyright (C) 2008-2012 Florian Brosch
+ * Copyright (C) 2008-2014 Florian Brosch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -127,12 +127,12 @@ public class Valadoc.Taglets.Link : InlineTaglet {
        public override ContentElement produce_content () {
                var link = new Content.SymbolLink ();
                link.symbol = _symbol;
-               link.label = symbol_name;
+               link.given_symbol_name = symbol_name;
 
                Content.Inline content;
                switch (_context) {
                case SymbolContext.FINISH:
-                       link.label += ".end";
+                       link.given_symbol_name += ".end";
                        content = link;
                        break;