[gnome-software/155-allow-some-markup-in-release-notes-in-appdata] gs-appstream: Support more markup in the description text



commit 1312cc4286029ea172ef2d401a86b30a9718ef44
Author: Milan Crha <mcrha redhat com>
Date:   Thu Nov 4 09:49:55 2021 +0100

    gs-appstream: Support more markup in the description text
    
    Get to what the AppStream standard supports at the moment:
    https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-description
    
    Plus add the 'b' tag for the bold text.

 lib/gs-appstream.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 59 insertions(+), 9 deletions(-)
---
diff --git a/lib/gs-appstream.c b/lib/gs-appstream.c
index e0b9cc8c5..9867b426f 100644
--- a/lib/gs-appstream.c
+++ b/lib/gs-appstream.c
@@ -61,33 +61,83 @@ node_set_to_next (XbNode **node)
        *node = g_steal_pointer (&next_node);
 }
 
+/* Returns escaped text */
+static gchar *
+gs_appstream_format_description_text (XbNode *node)
+{
+       g_autoptr(GString) str = g_string_new (NULL);
+       const gchar *node_text;
+
+       if (node == NULL)
+               return NULL;
+
+       node_text = xb_node_get_text (node);
+       if (node_text != NULL && *node_text != '\0') {
+               g_autofree gchar *escaped = g_markup_escape_text (node_text, -1);
+               g_string_append (str, escaped);
+       }
+
+       for (g_autoptr(XbNode) n = xb_node_get_child (node); n != NULL; node_set_to_next (&n)) {
+               const gchar *start_elem = "", *end_elem = "";
+               g_autofree gchar *text = NULL;
+               if (g_strcmp0 (xb_node_get_element (n), "b") == 0) {
+                       start_elem = "<b>";
+                       end_elem = "</b>";
+               } else if (g_strcmp0 (xb_node_get_element (n), "em") == 0 ||
+                          g_strcmp0 (xb_node_get_element (n), "i") == 0) {
+                       start_elem = "<i>";
+                       end_elem = "</i>";
+               } else if (g_strcmp0 (xb_node_get_element (n), "code") == 0 ||
+                          g_strcmp0 (xb_node_get_element (n), "tt") == 0) {
+                       start_elem = "<tt>";
+                       end_elem = "</tt>";
+               }
+
+               /* These can be nested */
+               text = gs_appstream_format_description_text (n);
+               if (text != NULL) {
+                       g_string_append_printf (str, "%s%s%s", start_elem, text, end_elem);
+               }
+
+               node_text = xb_node_get_tail (n);
+               if (node_text != NULL && *node_text != '\0') {
+                       g_autofree gchar *escaped = g_markup_escape_text (node_text, -1);
+                       g_string_append (str, escaped);
+               }
+       }
+
+       if (str->len == 0)
+               return NULL;
+
+       return g_string_free (g_steal_pointer (&str), FALSE);
+}
+
 static gchar *
 gs_appstream_format_description (XbNode *root, GError **error)
 {
        g_autoptr(GString) str = g_string_new (NULL);
 
        for (g_autoptr(XbNode) n = xb_node_get_child (root); n != NULL; node_set_to_next (&n)) {
-               /* support <p>, <ul>, <ol> and <li>, ignore all else */
+               /* support <p>, <em>, <code>, <ul>, <ol> and <li>, ignore all else */
                if (g_strcmp0 (xb_node_get_element (n), "p") == 0) {
-                       const gchar *node_text = xb_node_get_text (n);
-
+                       g_autofree gchar *escaped = gs_appstream_format_description_text (n);
                        /* Treat a self-closing paragraph (`<p/>`) as
                         * nonexistent. This is consistent with Firefox. */
-                       if (node_text != NULL)
-                               g_string_append_printf (str, "%s\n\n", node_text);
+                       if (escaped != NULL)
+                               g_string_append_printf (str, "%s\n\n", escaped);
                } else if (g_strcmp0 (xb_node_get_element (n), "ul") == 0) {
                        g_autoptr(GPtrArray) children = xb_node_get_children (n);
 
                        for (guint i = 0; i < children->len; i++) {
                                XbNode *nc = g_ptr_array_index (children, i);
                                if (g_strcmp0 (xb_node_get_element (nc), "li") == 0) {
-                                       const gchar *node_text = xb_node_get_text (nc);
+                                       g_autofree gchar *escaped = gs_appstream_format_description_text (nc);
 
                                        /* Treat a self-closing `<li/>` as an empty
                                         * list element (equivalent to `<li></li>`).
                                         * This is consistent with Firefox. */
                                        g_string_append_printf (str, " • %s\n",
-                                                               (node_text != NULL) ? node_text : "");
+                                                               (escaped != NULL) ? escaped : "");
                                }
                        }
                        g_string_append (str, "\n");
@@ -96,12 +146,12 @@ gs_appstream_format_description (XbNode *root, GError **error)
                        for (guint i = 0; i < children->len; i++) {
                                XbNode *nc = g_ptr_array_index (children, i);
                                if (g_strcmp0 (xb_node_get_element (nc), "li") == 0) {
-                                       const gchar *node_text = xb_node_get_text (nc);
+                                       g_autofree gchar *escaped = gs_appstream_format_description_text (nc);
 
                                        /* Treat self-closing elements as with `<ul>` above. */
                                        g_string_append_printf (str, " %u. %s\n",
                                                                i + 1,
-                                                               (node_text != NULL) ? node_text : "");
+                                                               (escaped != NULL) ? escaped : "");
                                }
                        }
                        g_string_append (str, "\n");


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