[yelp/41-settings-revamp] Make search results go thru XSLT too



commit 02bb34ef43035a9a6cd6e51ad139478fa7a50b1d
Author: Shaun McCance <shaunm gnome org>
Date:   Thu Jul 29 14:02:51 2021 -0400

    Make search results go thru XSLT too
    
    One step color to removing color computation and complex HTML
    formatting from C.

 .gitignore                  |   1 +
 data/xslt/links2html.xsl.in |  32 +++--
 libyelp/yelp-document.c     | 279 +++++++++++++++++++++-----------------------
 libyelp/yelp-transform.c    |   8 ++
 libyelp/yelp-transform.h    |   2 +
 libyelp/yelp-view.c         |  24 ++--
 6 files changed, 178 insertions(+), 168 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ea86d02e..dca49027 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,7 @@ yelp
 /data/dtd/catalog
 /data/xslt/db2html.xsl
 /data/xslt/info2html.xsl
+/data/xslt/links2html.xsl
 /data/xslt/mal2html.xsl
 /data/xslt/man2html.xsl
 /data/xslt/yelp-common.xsl
diff --git a/data/xslt/links2html.xsl.in b/data/xslt/links2html.xsl.in
index e5b8c1d2..eed32407 100644
--- a/data/xslt/links2html.xsl.in
+++ b/data/xslt/links2html.xsl.in
@@ -55,28 +55,44 @@
     <xsl:with-param name="right" select="$right"/>
   </xsl:call-template>
   <xsl:text>
-.ex-yelp-panel-icon {
-  display: flex;
-}
   </xsl:text>
 </xsl:template>
 
+<xsl:template mode="html.header.mode" match="links">
+  <xsl:if test="@docref and @doctitle">
+    <div class="trails" role="navigation">
+      <div class="trail">
+        <a class="trail" href="{@docref}">
+          <xsl:value-of select="@doctitle"/>
+        </a>
+        <xsl:text>&#x00A0; » </xsl:text>
+      </div>
+    </div>
+  </xsl:if>
+</xsl:template>
+
 <xsl:template mode="html.body.mode" match="links">
   <div class="hgroup pagewide">
     <h1><span class="title"><xsl:value-of select="title"/></span></h1>
   </div>
+  <xsl:variable name="hasicons" select="count(link/thumb/@src) > 0"/>
   <div class="region">
     <div class="contents pagewide">
+      <xsl:for-each select="p">
+        <p><xsl:value-of select="."/></p>
+      </xsl:for-each>
       <div class="links-divs">
         <xsl:for-each select="link">
           <div class="linkdiv">
             <a class="linkdiv" href="{@href}" title="{title}">
               <span style="display:flex;">
-                <span class="thumb" style="min-width:48px;padding-right:10px;">
-                  <xsl:if test="thumb/@src != ''">
-                    <img src="{thumb/@src}" width="48" height="48"/>
-                  </xsl:if>
-                </span>
+                <xsl:if test="$hasicons">
+                  <span class="thumb" style="min-width:48px;padding-right:10px;">
+                    <xsl:if test="thumb/@src != ''">
+                      <img src="{thumb/@src}" width="48" height="48"/>
+                    </xsl:if>
+                  </span>
+                </xsl:if>
                 <span>
                   <span class="title">
                     <xsl:value-of select="title"/>
diff --git a/libyelp/yelp-document.c b/libyelp/yelp-document.c
index 346c411d..cfac7291 100644
--- a/libyelp/yelp-document.c
+++ b/libyelp/yelp-document.c
@@ -25,6 +25,7 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <libxml/parser.h>
 
 #include "yelp-debug.h"
 #include "yelp-document.h"
@@ -37,6 +38,9 @@
 #include "yelp-settings.h"
 #include "yelp-simple-document.h"
 #include "yelp-storage.h"
+#include "yelp-transform.h"
+
+#define LINKS_STYLESHEET DATADIR"/yelp/xslt/links2html.xsl"
 
 enum {
     PROP_0,
@@ -822,18 +826,116 @@ yelp_document_set_page_icon (YelpDocument *document,
     g_mutex_unlock (&document->priv->mutex);
 }
 
+
+static void
+search_transform_chunk_ready (YelpTransform   *transform,
+                              gchar           *chunk_id,
+                              YelpDocument    *document)
+{
+    gchar *content;
+    content = yelp_transform_take_chunk (transform, chunk_id);
+    yelp_document_give_contents (document,
+                                 chunk_id,
+                                 content,
+                                 "application/xhtml+xml");
+    yelp_document_signal (document,
+                          chunk_id,
+                          YELP_DOCUMENT_SIGNAL_CONTENTS,
+                          NULL);
+}
+
+
+static void
+search_transform_finished (YelpTransform   *transform,
+                           YelpDocument    *document)
+{
+    xmlFreeDoc (yelp_transform_get_xmldoc (transform));
+    g_object_unref (transform);
+}
+
+
 static gboolean
 document_indexed (YelpDocument *document)
 {
     g_mutex_lock (&document->priv->mutex);
+
     while (document->priv->reqs_search != NULL) {
+        xmlDocPtr resultsdoc;
+        xmlNodePtr rootnode;
+        gchar *term, *text;
+        GVariant *value;
+        GVariantIter *iter;
+        YelpTransform *transform;
+        gchar **params = NULL;
         Request *request = (Request *) document->priv->reqs_search->data;
-        request->idle_funcs++;
-        g_idle_add ((GSourceFunc) request_idle_info, request);
-        g_idle_add ((GSourceFunc) request_idle_contents, request);
+
+        resultsdoc = xmlNewDoc (BAD_CAST "1.0");
+        rootnode = xmlNewDocNode (resultsdoc, NULL, BAD_CAST "links", NULL);
+        xmlDocSetRootElement (resultsdoc, rootnode);
+        xmlSetProp (rootnode, BAD_CAST "id", BAD_CAST request->page_id);
+
+        xmlSetProp (rootnode, BAD_CAST "docref", BAD_CAST request->page_id);
+
+        text = yelp_storage_get_root_title (yelp_storage_get_default (),
+                                            document->priv->doc_uri);
+        if (text) {
+            xmlSetProp (rootnode, BAD_CAST "docref", BAD_CAST "xref:");
+            xmlSetProp (rootnode, BAD_CAST "doctitle", BAD_CAST text);
+            g_free (text);
+        }
+
+        term = g_uri_unescape_string (request->page_id + 7, "");
+        text = g_strdup_printf (_("Search results for “%s”"), term);
+        xmlNewTextChild (rootnode, NULL, BAD_CAST "title", BAD_CAST text);
+        g_free (text);
+
+        value = yelp_storage_search (yelp_storage_get_default (),
+                                     document->priv->doc_uri,
+                                     term);
+        iter = g_variant_iter_new (value);
+        if (g_variant_iter_n_children (iter) == 0) {
+            xmlNewTextChild (rootnode, NULL, BAD_CAST "p",
+                             BAD_CAST _("No matching help pages found."));
+        }
+        else {
+            gchar *url, *title, *desc, *icon; /* do not free */
+            while (g_variant_iter_loop (iter, "(&s&s&s&s)", &url, &title, &desc, &icon)) {
+                xmlNodePtr linknode;
+                gchar *xref_uri = NULL;
+
+                if (g_str_has_prefix (url, document->priv->doc_uri)) {
+                    gchar *urloffset = url + strlen(document->priv->doc_uri) + 1; /* do not free */
+                    if (urloffset[0] == '?')
+                        urloffset += 1; /* handle oddity of old ghelp URIs */
+                    xref_uri = g_strdup_printf ("xref:%s", urloffset);
+                }
+                linknode = xmlNewChild (rootnode, NULL, BAD_CAST "link", NULL);
+                xmlSetProp (linknode, BAD_CAST "href", BAD_CAST xref_uri);
+                xmlNewTextChild (linknode, NULL, BAD_CAST "title", BAD_CAST title);
+                xmlNewTextChild (linknode, NULL, BAD_CAST "desc", BAD_CAST desc);
+                g_free (xref_uri);
+            }
+        }
+        g_variant_iter_free (iter);
+        g_variant_unref (value);
+        g_free (term);
+
+        params = yelp_settings_get_all_params (yelp_settings_get_default (), 0, NULL);
+        transform = yelp_transform_new (LINKS_STYLESHEET);
+        g_signal_connect (transform, "chunk-ready",
+                          (GCallback) search_transform_chunk_ready,
+                          document);
+        g_signal_connect (transform, "finished",
+                          (GCallback) search_transform_finished,
+                          document);
+        yelp_transform_start (transform, resultsdoc, NULL,
+                              (const gchar * const *) params);
+        g_strfreev (params);
+
         document->priv->reqs_search = g_slist_delete_link (document->priv->reqs_search,
                                                            document->priv->reqs_search);
     }
+
     g_mutex_unlock (&document->priv->mutex);
 
     return FALSE;
@@ -852,7 +954,13 @@ yelp_document_request_page (YelpDocument         *document,
     g_return_val_if_fail (YELP_IS_DOCUMENT (document), FALSE);
     g_return_val_if_fail (YELP_DOCUMENT_GET_CLASS (document)->request_page != NULL, FALSE);
 
-    debug_print (DB_FUNCTION, "entering\n");
+    if (page_id && g_str_has_prefix (page_id, "search="))
+        return document_request_page (document,
+                                      page_id,
+                                      cancellable,
+                                      callback,
+                                      user_data,
+                                      notify);
 
     return YELP_DOCUMENT_GET_CLASS (document)->request_page (document,
                                                             page_id,
@@ -905,8 +1013,6 @@ document_request_page (YelpDocument         *document,
             g_idle_add ((GSourceFunc) document_indexed, document);
         else
             yelp_document_index (document);
-        g_mutex_unlock (&document->priv->mutex);
-        return TRUE;
     }
 
     hash_slist_insert (document->priv->reqs_by_page_id,
@@ -914,7 +1020,11 @@ document_request_page (YelpDocument         *document,
                       request);
 
     document->priv->reqs_all = g_slist_prepend (document->priv->reqs_all, request);
-    document->priv->reqs_pending = g_slist_prepend (document->priv->reqs_pending, request);
+    if (page_id && g_str_has_prefix (page_id, "search=")) {
+    }
+    else {
+        document->priv->reqs_pending = g_slist_prepend (document->priv->reqs_pending, request);
+    }
 
     if (hash_lookup (document->priv->titles, request->page_id)) {
        request->idle_funcs++;
@@ -976,6 +1086,9 @@ yelp_document_read_contents (YelpDocument *document,
     g_return_val_if_fail (YELP_IS_DOCUMENT (document), NULL);
     g_return_val_if_fail (YELP_DOCUMENT_GET_CLASS (document)->read_contents != NULL, NULL);
 
+    if (page_id != NULL && g_str_has_prefix (page_id, "search="))
+        return document_read_contents (document, page_id);
+
     return YELP_DOCUMENT_GET_CLASS (document)->read_contents (document, page_id);
 }
 
@@ -983,143 +1096,14 @@ static const gchar *
 document_read_contents (YelpDocument *document,
                        const gchar  *page_id)
 {
-    gchar *real, *str, **colors;
+    gchar *real, *str; /* do not free real */
 
     g_mutex_lock (&document->priv->mutex);
 
-    real = hash_lookup (document->priv->page_ids, page_id);
-
-    if (page_id != NULL && g_str_has_prefix (page_id, "search=")) {
-        gchar *tmp, *tmp2, *txt;
-        GVariant *value;
-        GVariantIter *iter;
-        gchar *url, *title, *desc, *icon; /* do not free */
-        gchar *index_title;
-        GString *ret = g_string_new ("<html xmlns=\"http://www.w3.org/1999/xhtml\";><head><style 
type='text/css'>");
-
-        colors = yelp_settings_get_colors (yelp_settings_get_default ());
-        g_string_append_printf (ret,
-                                "html { height: 100%%; } "
-                                "body { margin: 0; padding: 0;"
-                                " background-color: %s; color: %s;"
-                                " direction: %s; } "
-                                "div.header { margin-bottom: 1em; } "
-                                "div.trails { "
-                                " margin: 0; padding: 0.2em 12px 0 12px;"
-                                " background-color: %s;"
-                                " border-bottom: solid 1px %s; } "
-                                "div.trail { text-indent: -1em;"
-                                " margin: 0 1em 0.2em 1em; padding: 0; color: %s; } "
-                                "div.body { margin: 0 12px 0 12px; padding: 0 0 12px 0; max-width: 60em; } "
-                                "div, p { margin: 1em 0 0 0; padding: 0; } "
-                                "div:first-child, p:first-child { margin-top: 0; } "
-                                "h1 { margin: 0; padding: 0; color: %s; font-size: 1.44em; } "
-                                "a { color: %s; text-decoration: none; } "
-                                "a.linkdiv { display: block; } "
-                                "div.linkdiv { margin: 0; padding: 0.5em; }"
-                                "a:hover div.linkdiv {"
-                                " outline: solid 1px %s;"
-                                " background: -webkit-gradient(linear, left top, left 80, from(%s), to(%s)); 
} "
-                                "div.title { margin-bottom: 0.2em; font-weight: bold; } "
-                                "div.desc { margin: 0; color: %s; } "
-                                "</style></head><body><div class='header'>",
-                                colors[YELP_SETTINGS_COLOR_BASE],
-                                colors[YELP_SETTINGS_COLOR_TEXT],
-                                (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL ? "rtl" : "ltr"),
-                                colors[YELP_SETTINGS_COLOR_GRAY_BASE],
-                                colors[YELP_SETTINGS_COLOR_GRAY_BORDER],
-                                colors[YELP_SETTINGS_COLOR_TEXT_LIGHT],
-                                colors[YELP_SETTINGS_COLOR_TEXT_LIGHT],
-                                colors[YELP_SETTINGS_COLOR_LINK],
-                                colors[YELP_SETTINGS_COLOR_BLUE_BASE],
-                                colors[YELP_SETTINGS_COLOR_BLUE_BASE],
-                                colors[YELP_SETTINGS_COLOR_BASE],
-                                colors[YELP_SETTINGS_COLOR_TEXT_LIGHT]
-                                );
-
-        index_title = yelp_storage_get_root_title (yelp_storage_get_default (),
-                                                   document->priv->doc_uri);
-        if (index_title != NULL) {
-            tmp = g_markup_printf_escaped ("<div class='trails'><div class='trail'>"
-                                           "<a href='xref:'>%s</a>&#x00A0;%s "
-                                           "</div></div>",
-                                           index_title,
-                                           (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL ? "«" : 
"»")
-                                           );
-            g_string_append (ret, tmp);
-            g_free (tmp);
-        }
-
-        g_string_append (ret, "</div><div class='body'>");
-        g_strfreev (colors);
-
-        str = hash_lookup (document->priv->contents, real);
-        if (str) {
-            str_ref (str);
-            g_mutex_unlock (&document->priv->mutex);
-            return (const gchar *) str;
-        }
-
-        txt = g_uri_unescape_string (page_id + 7, NULL);
-        tmp2 = g_strdup_printf (_("Search results for “%s”"), txt);
-        tmp = g_markup_printf_escaped ("<h1>%s</h1>", tmp2);
-        g_string_append (ret, tmp);
-        g_free (tmp2);
-        g_free (tmp);
-
-        value = yelp_storage_search (yelp_storage_get_default (),
-                                     document->priv->doc_uri,
-                                     txt);
-        iter = g_variant_iter_new (value);
-        if (g_variant_iter_n_children (iter) == 0) {
-            if (index_title != NULL) {
-                gchar *t = g_strdup_printf (_("No matching help pages found in “%s”."), index_title);
-                tmp = g_markup_printf_escaped ("<p>%s</p>", t);
-                g_free (t);
-            }
-            else {
-                tmp = g_markup_printf_escaped ("<p>%s</p>",
-                                               _("No matching help pages found."));
-            }
-            g_string_append (ret, tmp);
-            g_free (tmp);
-        }
-        else {
-            while (g_variant_iter_loop (iter, "(&s&s&s&s)", &url, &title, &desc, &icon)) {
-                gchar *xref_uri = NULL;
-
-                if (g_str_has_prefix (url, document->priv->doc_uri)) {
-                    gchar *urloffset = url + strlen(document->priv->doc_uri) + 1; /* do not free */
-                    if (urloffset[0] == '?')
-                        urloffset += 1; /* handle oddity of old ghelp URIs */
-                    xref_uri = g_strdup_printf ("xref:%s", urloffset);
-                }
-
-                tmp = g_markup_printf_escaped ("<div><a class='linkdiv' href='%s'><div class='linkdiv'>"
-                                               "<div class='title'>%s</div>"
-                                               "<div class='desc'>%s</div>"
-                                               "</div></a></div>",
-                                               xref_uri && xref_uri[0] != '\0' ? xref_uri : url,
-                                               title, desc);
-                g_string_append (ret, tmp);
-                g_free (xref_uri);
-                g_free (tmp);
-            }
-        }
-        g_variant_iter_free (iter);
-        g_variant_unref (value);
-
-        if (index_title != NULL)
-            g_free (index_title);
-        g_free (txt);
-        g_string_append (ret, "</div></body></html>");
-
-        hash_replace (document->priv->contents, page_id, g_string_free (ret, FALSE));
-        str = hash_lookup (document->priv->contents, page_id);
-        str_ref (str);
-        g_mutex_unlock (&document->priv->mutex);
-        return (const gchar *) str;
-    }
+    if (page_id != NULL && g_str_has_prefix (page_id, "search="))
+        real = (gchar *) page_id;
+    else
+        real = hash_lookup (document->priv->page_ids, page_id);
 
     str = hash_lookup (document->priv->contents, real);
     if (str)
@@ -1155,9 +1139,6 @@ yelp_document_give_contents (YelpDocument *document,
 {
     g_return_if_fail (YELP_IS_DOCUMENT (document));
 
-    debug_print (DB_FUNCTION, "entering\n");
-    debug_print (DB_ARG, "    page_id = \"%s\"\n", page_id);
-
     g_mutex_lock (&document->priv->mutex);
 
     hash_replace (document->priv->contents,
@@ -1185,13 +1166,13 @@ static gchar *
 document_get_mime_type (YelpDocument *document,
                        const gchar  *page_id)
 {
-    gchar *real, *ret = NULL;
-
-    if (page_id != NULL && g_str_has_prefix (page_id, "search="))
-      return g_strdup ("application/xhtml+xml");
+    gchar *real, *ret = NULL; /* do not free real */
 
     g_mutex_lock (&document->priv->mutex);
-    real = hash_lookup (document->priv->page_ids, page_id);
+    if (page_id != NULL && g_str_has_prefix (page_id, "search="))
+        real = (gchar *) page_id;
+    else
+        real = hash_lookup (document->priv->page_ids, page_id);
     if (real) {
        ret = hash_lookup (document->priv->mime_types, real);
        if (ret)
diff --git a/libyelp/yelp-transform.c b/libyelp/yelp-transform.c
index 0107db9a..e74eb463 100644
--- a/libyelp/yelp-transform.c
+++ b/libyelp/yelp-transform.c
@@ -273,6 +273,14 @@ yelp_transform_set_property (GObject      *object,
     }
 }
 
+
+xmlDocPtr
+yelp_transform_get_xmldoc (YelpTransform *transform)
+{
+    YelpTransformPrivate *priv = yelp_transform_get_instance_private (transform);
+    return priv->input;
+}
+
 /******************************************************************************/
 
 YelpTransform *
diff --git a/libyelp/yelp-transform.h b/libyelp/yelp-transform.h
index 8e71b59d..c62b5aad 100644
--- a/libyelp/yelp-transform.h
+++ b/libyelp/yelp-transform.h
@@ -53,4 +53,6 @@ gchar *          yelp_transform_take_chunk     (YelpTransform       *transform,
 void             yelp_transform_cancel         (YelpTransform       *transform);
 GError *         yelp_transform_get_error      (YelpTransform       *transform);
 
+xmlDocPtr        yelp_transform_get_xmldoc     (YelpTransform       *transform);
+
 #endif /* __YELP_TRANSFORM_H__ */
diff --git a/libyelp/yelp-view.c b/libyelp/yelp-view.c
index 1f10000c..9b2e5fb2 100644
--- a/libyelp/yelp-view.c
+++ b/libyelp/yelp-view.c
@@ -780,17 +780,19 @@ document_callback (YelpDocument       *document,
 
     contents = yelp_document_read_contents (document, data->page_id);
 
-    content_length = strlen (contents);
-
-    stream = g_memory_input_stream_new_from_data (g_strdup (contents), content_length, g_free);
-    yelp_document_finish_read (document, contents);
-
-    webkit_uri_scheme_request_finish (data->request,
-                                      stream,
-                                      content_length,
-                                      mime_type);
-    g_free (mime_type);
-    g_object_unref (stream);
+    if (contents) {
+        content_length = strlen (contents);
+
+        stream = g_memory_input_stream_new_from_data (g_strdup (contents), content_length, g_free);
+        yelp_document_finish_read (document, contents);
+
+        webkit_uri_scheme_request_finish (data->request,
+                                          stream,
+                                          content_length,
+                                          mime_type);
+        g_free (mime_type);
+        g_object_unref (stream);
+    }
 }
 
 static void


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