[gnome-software] Make links clickable in the ChangeLog descriptions



commit cc92915653d072db2b375f7ff00a218240e3dfd1
Author: Richard Hughes <richard hughsie com>
Date:   Thu Nov 14 14:09:30 2013 +0000

    Make links clickable in the ChangeLog descriptions
    
    Resovles: https://bugzilla.gnome.org/show_bug.cgi?id=711846

 src/gs-app-widget.c |    3 +-
 src/gs-markdown.c   |   87 ++++++++++++++++++++++++++++++++++++++++++++++-----
 src/gs-markdown.h   |    2 +
 src/gs-self-test.c  |   10 ++++++
 4 files changed, 93 insertions(+), 9 deletions(-)
---
diff --git a/src/gs-app-widget.c b/src/gs-app-widget.c
index 4eade63..57659b6 100644
--- a/src/gs-app-widget.c
+++ b/src/gs-app-widget.c
@@ -75,7 +75,8 @@ gs_app_widget_get_description (GsAppWidget *app_widget)
                if (tmp != NULL) {
                        markdown = gs_markdown_new ();
                        gs_markdown_set_smart_quoting (markdown, TRUE);
-                       gs_markdown_set_autocode (markdown, TRUE);
+                       gs_markdown_set_autocode (markdown, FALSE);
+                       gs_markdown_set_autolinkify (markdown, FALSE);
                        gs_markdown_set_output_kind (markdown,
                                                     GS_MARKDOWN_OUTPUT_PANGO);
                        escaped = gs_markdown_parse (markdown, tmp);
diff --git a/src/gs-markdown.c b/src/gs-markdown.c
index 570af88..ff0d569 100644
--- a/src/gs-markdown.c
+++ b/src/gs-markdown.c
@@ -82,6 +82,7 @@ typedef struct {
        gboolean                 smart_quoting;
        gboolean                 escape;
        gboolean                 autocode;
+       gboolean                 autolinkify;
        GString                 *pending;
        GString                 *processed;
 } GsMarkdownPrivate;
@@ -509,14 +510,6 @@ gs_markdown_word_is_code (const gchar *text)
        if (g_str_has_prefix (text, "#"))
                return TRUE;
 
-       /* uri's */
-       if (g_str_has_prefix (text, "http://";))
-               return TRUE;
-       if (g_str_has_prefix (text, "https://";))
-               return TRUE;
-       if (g_str_has_prefix (text, "ftp://";))
-               return TRUE;
-
        /* patch files */
        if (g_strrstr (text, ".patch") != NULL)
                return TRUE;
@@ -578,6 +571,59 @@ out:
 }
 
 /**
+ * gs_markdown_word_is_url:
+ **/
+static gboolean
+gs_markdown_word_is_url (const gchar *text)
+{
+       if (g_str_has_prefix (text, "http://";))
+               return TRUE;
+       if (g_str_has_prefix (text, "https://";))
+               return TRUE;
+       if (g_str_has_prefix (text, "ftp://";))
+               return TRUE;
+       return FALSE;
+}
+
+/**
+ * gs_markdown_word_auto_format_urls:
+ **/
+static gchar *
+gs_markdown_word_auto_format_urls (const gchar *text)
+{
+       guint i;
+       gchar *temp;
+       gchar **words;
+       gboolean ret = FALSE;
+
+       /* split sentence up with space */
+       words = g_strsplit (text, " ", -1);
+
+       /* search each word */
+       for (i=0; words[i] != NULL; i++) {
+               if (gs_markdown_word_is_url (words[i])) {
+                       temp = g_strdup_printf ("<a href=\"%s\">%s</a>",
+                                               words[i], words[i]);
+                       g_free (words[i]);
+                       words[i] = temp;
+                       ret = TRUE;
+               }
+       }
+
+       /* no replacements, so just return a copy */
+       if (!ret) {
+               temp = g_strdup (text);
+               goto out;
+       }
+
+       /* join the array back into a string */
+       temp = g_strjoinv (" ", words);
+out:
+       g_strfreev (words);
+       return temp;
+}
+
+/**
  * gs_markdown_flush_pending:
  **/
 static void
@@ -600,6 +646,7 @@ gs_markdown_flush_pending (GsMarkdown *self)
        if (!priv->escape && priv->output == GS_MARKDOWN_OUTPUT_PANGO) {
                g_strdelimit (copy, "<", '(');
                g_strdelimit (copy, ">", ')');
+               g_strdelimit (copy, "&", '+');
        }
 
        /* check words for code */
@@ -618,6 +665,16 @@ gs_markdown_flush_pending (GsMarkdown *self)
                copy = temp;
        }
 
+       /* check words for URLS */
+       if (priv->autolinkify && //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+           priv->output == GS_MARKDOWN_OUTPUT_PANGO &&
+           (priv->mode == GS_MARKDOWN_MODE_PARA ||
+            priv->mode == GS_MARKDOWN_MODE_BULLETT)) {
+               temp = gs_markdown_word_auto_format_urls (copy);
+               g_free (copy);
+               copy = temp;
+       }
+
        /* do formatting */
        temp = gs_markdown_to_text_line_format (self, copy);
        if (priv->mode == GS_MARKDOWN_MODE_BULLETT) {
@@ -774,6 +831,7 @@ gs_markdown_set_output_kind (GsMarkdown *self, GsMarkdownOutputKind output)
                priv->tags.bullet_end = "";
                priv->tags.rule = "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n";
                priv->escape = TRUE;
+               priv->autolinkify = TRUE;
                break;
        case GS_MARKDOWN_OUTPUT_HTML:
                /* XHTML */
@@ -791,6 +849,7 @@ gs_markdown_set_output_kind (GsMarkdown *self, GsMarkdownOutputKind output)
                priv->tags.bullet_end = "</li>";
                priv->tags.rule = "<hr>";
                priv->escape = TRUE;
+               priv->autolinkify = TRUE;
                break;
        case GS_MARKDOWN_OUTPUT_TEXT:
                /* plain text */
@@ -808,6 +867,7 @@ gs_markdown_set_output_kind (GsMarkdown *self, GsMarkdownOutputKind output)
                priv->tags.bullet_end = "";
                priv->tags.rule = " ----- \n";
                priv->escape = FALSE;
+               priv->autolinkify = FALSE;
                break;
        default:
                g_warning ("unknown output enum");
@@ -860,6 +920,17 @@ gs_markdown_set_autocode (GsMarkdown *self, gboolean autocode)
 }
 
 /**
+ * gs_markdown_set_autolinkify:
+ **/
+void
+gs_markdown_set_autolinkify (GsMarkdown *self, gboolean autolinkify)
+{
+       GsMarkdownPrivate *priv = gs_markdown_get_instance_private (self);
+       g_return_if_fail (GS_IS_MARKDOWN (self));
+       priv->autolinkify = autolinkify;
+}
+
+/**
  * gs_markdown_parse:
  **/
 gchar *
diff --git a/src/gs-markdown.h b/src/gs-markdown.h
index fdbb533..e2bf19a 100644
--- a/src/gs-markdown.h
+++ b/src/gs-markdown.h
@@ -59,6 +59,8 @@ void           gs_markdown_set_escape                 (GsMarkdown             *self,
                                                         gboolean                escape);
 void            gs_markdown_set_autocode               (GsMarkdown             *self,
                                                         gboolean                autocode);
+void            gs_markdown_set_autolinkify            (GsMarkdown             *self,
+                                                        gboolean                autolinkify);
 gchar          *gs_markdown_parse                      (GsMarkdown             *self,
                                                         const gchar            *text);
 
diff --git a/src/gs-self-test.c b/src/gs-self-test.c
index b830645..75f2ed8 100644
--- a/src/gs-self-test.c
+++ b/src/gs-self-test.c
@@ -170,6 +170,16 @@ gs_markdown_func (void)
        g_assert_cmpstr (text, ==, markdown_expected);
        g_free (text);
 
+       /* markdown (URLs) */
+       markdown = "this is the http://www.hughsie.com/ coolest site";
+       markdown_expected =
+                  "this is the "
+                  "<a href=\"http://www.hughsie.com/\";>http://www.hughsie.com/</a>"
+                  " coolest site";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
        /* markdown (free text) */
        gs_markdown_set_escape (md, FALSE);
        text = gs_markdown_parse (md, "This isn't a present");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]