diff options
author | Richard Hughes <richard@hughsie.com> | 2016-03-03 13:14:26 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2016-03-03 13:37:52 +0000 |
commit | 45406dd91959729e0f8935cf864f70f291801489 (patch) | |
tree | d45fd6af8630bec78c4e987573e85ab2386b540e | |
parent | ecb45f77ca3e553c00c861d3d659838dc298c507 (diff) | |
download | appstream-glib-45406dd91959729e0f8935cf864f70f291801489.tar.gz |
Split out as-markup into a new source file
as-utils.c was getting much too big anyway. No API changes.
-rw-r--r-- | docs/api/appstream-glib-docs.sgml | 1 | ||||
-rw-r--r-- | libappstream-glib/Makefile.am | 4 | ||||
-rw-r--r-- | libappstream-glib/appstream-glib.h | 1 | ||||
-rw-r--r-- | libappstream-glib/as-markup.c | 423 | ||||
-rw-r--r-- | libappstream-glib/as-markup.h | 86 | ||||
-rw-r--r-- | libappstream-glib/as-node.c | 1 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 1 | ||||
-rw-r--r-- | libappstream-glib/as-utils.c | 385 | ||||
-rw-r--r-- | libappstream-glib/as-utils.h | 49 |
9 files changed, 517 insertions, 434 deletions
diff --git a/docs/api/appstream-glib-docs.sgml b/docs/api/appstream-glib-docs.sgml index 53ab92e..5e37183 100644 --- a/docs/api/appstream-glib-docs.sgml +++ b/docs/api/appstream-glib-docs.sgml @@ -38,6 +38,7 @@ <xi:include href="xml/as-checksum.xml"/> <xi:include href="xml/as-icon.xml"/> <xi:include href="xml/as-image.xml"/> + <xi:include href="xml/as-markup.xml"/> <xi:include href="xml/as-release.xml"/> <xi:include href="xml/as-provide.xml"/> <xi:include href="xml/as-screenshot.xml"/> diff --git a/libappstream-glib/Makefile.am b/libappstream-glib/Makefile.am index e36bb3e..d987d14 100644 --- a/libappstream-glib/Makefile.am +++ b/libappstream-glib/Makefile.am @@ -76,6 +76,7 @@ libappstream_glib_include_HEADERS = \ as-icon.h \ as-image.h \ as-inf.h \ + as-markup.h \ as-node.h \ as-problem.h \ as-profile.h \ @@ -106,6 +107,7 @@ libappstream_glib_la_SOURCES = \ as-image-private.h \ as-inf.c \ as-inf.h \ + as-markup.c \ as-monitor.c \ as-monitor.h \ as-node.c \ @@ -196,6 +198,8 @@ introspection_sources = \ as-image.h \ as-inf.c \ as-inf.h \ + as-markup.c \ + as-markup.h \ as-node.c \ as-node.h \ as-problem.c \ diff --git a/libappstream-glib/appstream-glib.h b/libappstream-glib/appstream-glib.h index 26f2bea..90fef4c 100644 --- a/libappstream-glib/appstream-glib.h +++ b/libappstream-glib/appstream-glib.h @@ -32,6 +32,7 @@ #include <as-icon.h> #include <as-image.h> #include <as-inf.h> +#include <as-markup.h> #include <as-node.h> #include <as-problem.h> #include <as-profile.h> diff --git a/libappstream-glib/as-markup.c b/libappstream-glib/as-markup.c new file mode 100644 index 0000000..3a4c381 --- /dev/null +++ b/libappstream-glib/as-markup.c @@ -0,0 +1,423 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * 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 + */ + +/** + * SECTION:as-markup + * @short_description: Functions for managing AppStream description markup + * @include: appstream-glib.h + * @stability: Stable + * + * These functions are used internally to libappstream-glib, and some may be + * useful to user-applications. + */ + +#include "config.h" + +#include <string.h> + +#include "as-markup.h" +#include "as-node.h" +#include "as-utils.h" + +/** + * as_markup_import_simple: + */ +static gchar * +as_markup_import_simple (const gchar *text, GError **error) +{ + GString *str; + guint i; + g_auto(GStrv) lines = NULL; + + /* empty */ + if (text == NULL || text[0] == '\0') + return NULL; + + /* just assume paragraphs */ + str = g_string_new ("<p>"); + lines = g_strsplit (text, "\n", -1); + for (i = 0; lines[i] != NULL; i++) { + g_autofree gchar *markup = NULL; + if (lines[i][0] == '\0') { + if (g_str_has_suffix (str->str, " ")) + g_string_truncate (str, str->len - 1); + g_string_append (str, "</p><p>"); + continue; + } + markup = g_markup_escape_text (lines[i], -1); + g_string_append (str, markup); + g_string_append (str, " "); + } + if (g_str_has_suffix (str->str, " ")) + g_string_truncate (str, str->len - 1); + g_string_append (str, "</p>"); + return g_string_free (str, FALSE); +} + +/** + * as_markup_import: + * @text: the text to import. + * @format: the #AsMarkupConvertFormat, e.g. %AS_MARKUP_CONVERT_FORMAT_SIMPLE + * @error: A #GError or %NULL + * + * Imports text and converts to AppStream markup. + * + * Returns: (transfer full): appstream markup, or %NULL in event of an error + * + * Since: 0.5.11 + */ +gchar * +as_markup_import (const gchar *text, AsMarkupConvertFormat format, GError **error) +{ + if (format == AS_MARKUP_CONVERT_FORMAT_SIMPLE) + return as_markup_import_simple (text, error); + g_set_error_literal (error, + AS_UTILS_ERROR, + AS_UTILS_ERROR_INVALID_TYPE, + "unknown comnversion kind"); + return NULL; +} + +/** + * as_markup_strsplit_words: + * @text: the text to split. + * @line_len: the maximum length of the output line + * + * Splits up a long line into an array of smaller strings, each being no longer + * than @line_len. Words are not split. + * + * Returns: (transfer full): lines, or %NULL in event of an error + * + * Since: 0.3.5 + **/ +gchar ** +as_markup_strsplit_words (const gchar *text, guint line_len) +{ + GPtrArray *lines; + guint i; + g_autoptr(GString) curline = NULL; + g_auto(GStrv) tokens = NULL; + + /* sanity check */ + if (text == NULL || text[0] == '\0') + return NULL; + if (line_len == 0) + return NULL; + + lines = g_ptr_array_new (); + curline = g_string_new (""); + + /* tokenize the string */ + tokens = g_strsplit (text, " ", -1); + for (i = 0; tokens[i] != NULL; i++) { + + /* current line plus new token is okay */ + if (curline->len + strlen (tokens[i]) < line_len) { + g_string_append_printf (curline, "%s ", tokens[i]); + continue; + } + + /* too long, so remove space, add newline and dump */ + if (curline->len > 0) + g_string_truncate (curline, curline->len - 1); + g_string_append (curline, "\n"); + g_ptr_array_add (lines, g_strdup (curline->str)); + g_string_truncate (curline, 0); + g_string_append_printf (curline, "%s ", tokens[i]); + + } + + /* any incomplete line? */ + if (curline->len > 0) { + g_string_truncate (curline, curline->len - 1); + g_string_append (curline, "\n"); + g_ptr_array_add (lines, g_strdup (curline->str)); + } + + g_ptr_array_add (lines, NULL); + return (gchar **) g_ptr_array_free (lines, FALSE); +} + +/** + * as_markup_render_para: + **/ +static void +as_markup_render_para (GString *str, AsMarkupConvertFormat format, const gchar *data) +{ + guint i; + g_autofree gchar *tmp = NULL; + g_auto(GStrv) spl = NULL; + + if (str->len > 0) + g_string_append (str, "\n"); + switch (format) { + case AS_MARKUP_CONVERT_FORMAT_SIMPLE: + g_string_append_printf (str, "%s\n", data); + break; + case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: + tmp = g_markup_escape_text (data, -1); + g_string_append_printf (str, "<p>%s</p>", tmp); + break; + case AS_MARKUP_CONVERT_FORMAT_MARKDOWN: + /* break to 80 chars */ + spl = as_markup_strsplit_words (data, 80); + for (i = 0; spl[i] != NULL; i++) + g_string_append (str, spl[i]); + break; + default: + break; + } +} + +/** + * as_markup_render_li: + **/ +static void +as_markup_render_li (GString *str, AsMarkupConvertFormat format, const gchar *data) +{ + guint i; + g_autofree gchar *tmp = NULL; + g_auto(GStrv) spl = NULL; + + switch (format) { + case AS_MARKUP_CONVERT_FORMAT_SIMPLE: + g_string_append_printf (str, " • %s\n", data); + break; + case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: + tmp = g_markup_escape_text (data, -1); + g_string_append_printf (str, "<li>%s</li>", tmp); + break; + case AS_MARKUP_CONVERT_FORMAT_MARKDOWN: + /* break to 80 chars, leaving room for the dot/indent */ + spl = as_markup_strsplit_words (data, 80 - 3); + g_string_append_printf (str, " * %s", spl[0]); + for (i = 1; spl[i] != NULL; i++) + g_string_append_printf (str, " %s", spl[i]); + break; + default: + break; + } +} + +/** + * as_markup_render_ol_start: + **/ +static void +as_markup_render_ol_start (GString *str, AsMarkupConvertFormat format) +{ + switch (format) { + case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: + g_string_append (str, "<ol>"); + break; + default: + break; + } +} + +/** + * as_markup_render_ol_end: + **/ +static void +as_markup_render_ol_end (GString *str, AsMarkupConvertFormat format) +{ + switch (format) { + case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: + g_string_append (str, "</ol>"); + break; + default: + break; + } +} + +/** + * as_markup_validate: + * @markup: the text to validate + * @error: A #GError or %NULL + * + * Validates some markup. + * + * Returns: %TRUE if the appstream description was valid + * + * Since: 0.5.1 + **/ +gboolean +as_markup_validate (const gchar *markup, GError **error) +{ + g_autofree gchar *tmp = NULL; + tmp = as_markup_convert (markup, AS_MARKUP_CONVERT_FORMAT_NULL, error); + return tmp != NULL; +} + +/** + * as_markup_convert_full: + * @markup: the text to copy. + * @format: the #AsMarkupConvertFormat, e.g. %AS_MARKUP_CONVERT_FORMAT_MARKDOWN + * @flags: the #AsMarkupConvertFlag, e.g. %AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS + * @error: A #GError or %NULL + * + * Converts an XML description into a printable form. + * + * Returns: (transfer full): a newly allocated %NULL terminated string + * + * Since: 0.3.5 + **/ +gchar * +as_markup_convert_full (const gchar *markup, + AsMarkupConvertFormat format, + AsMarkupConvertFlag flags, + GError **error) +{ + GNode *tmp; + GNode *tmp_c; + const gchar *tag; + const gchar *tag_c; + g_autoptr(AsNode) root = NULL; + g_autoptr(GError) error_local = NULL; + g_autoptr(GString) str = NULL; + + /* is this actually markup */ + if (g_strstr_len (markup, -1, "<") == NULL) + return g_strdup (markup); + + /* load */ + root = as_node_from_xml (markup, AS_NODE_FROM_XML_FLAG_NONE, &error_local); + if (root == NULL) { + + /* truncate to the last tag and try again */ + if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS) { + gchar *found; + g_autofree gchar *markup_new = NULL; + markup_new = g_strdup (markup); + found = g_strrstr (markup_new, "<"); + g_assert (found != NULL); + *found = '\0'; + return as_markup_convert_full (markup_new, format, flags, error); + } + + /* just return error */ + g_propagate_error (error, error_local); + error_local = NULL; + return NULL; + } + + /* format */ + str = g_string_new (""); + for (tmp = root->children; tmp != NULL; tmp = tmp->next) { + + tag = as_node_get_name (tmp); + if (g_strcmp0 (tag, "p") == 0) { + as_markup_render_para (str, format, as_node_get_data (tmp)); + continue; + } + + /* loop on the children */ + if (g_strcmp0 (tag, "ul") == 0 || + g_strcmp0 (tag, "ol") == 0) { + as_markup_render_ol_start (str, format); + for (tmp_c = tmp->children; tmp_c != NULL; tmp_c = tmp_c->next) { + tag_c = as_node_get_name (tmp_c); + if (g_strcmp0 (tag_c, "li") == 0) { + as_markup_render_li (str, format, + as_node_get_data (tmp_c)); + continue; + } + + /* just abort the list */ + if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS) + break; + + /* only <li> is valid in lists */ + g_set_error (error, + AS_NODE_ERROR, + AS_NODE_ERROR_FAILED, + "Tag %s in %s invalid", + tag_c, tag); + return NULL; + } + as_markup_render_ol_end (str, format); + continue; + } + + /* just try again */ + if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS) + continue; + + /* only <p>, <ul> and <ol> is valid here */ + g_set_error (error, + AS_NODE_ERROR, + AS_NODE_ERROR_FAILED, + "Unknown tag '%s'", tag); + return NULL; + } + + /* success */ + switch (format) { + case AS_MARKUP_CONVERT_FORMAT_SIMPLE: + case AS_MARKUP_CONVERT_FORMAT_MARKDOWN: + if (str->len > 0) + g_string_truncate (str, str->len - 1); + break; + default: + break; + } + return g_strdup (str->str); +} + +/** + * as_markup_convert: + * @markup: the text to copy. + * @format: the #AsMarkupConvertFormat, e.g. %AS_MARKUP_CONVERT_FORMAT_MARKDOWN + * @error: A #GError or %NULL + * + * Converts an XML description into a printable form. + * + * Returns: (transfer full): a newly allocated %NULL terminated string + * + * Since: 0.3.5 + **/ +gchar * +as_markup_convert (const gchar *markup, + AsMarkupConvertFormat format, GError **error) +{ + return as_markup_convert_full (markup, format, + AS_MARKUP_CONVERT_FLAG_NONE, + error); +} + +/** + * as_markup_convert_simple: + * @markup: the text to copy. + * @error: A #GError or %NULL + * + * Converts an XML description into a printable form. + * + * Returns: (transfer full): a newly allocated %NULL terminated string + * + * Since: 0.1.0 + **/ +gchar * +as_markup_convert_simple (const gchar *markup, GError **error) +{ + return as_markup_convert_full (markup, + AS_MARKUP_CONVERT_FORMAT_SIMPLE, + AS_MARKUP_CONVERT_FLAG_NONE, + error); +} diff --git a/libappstream-glib/as-markup.h b/libappstream-glib/as-markup.h new file mode 100644 index 0000000..9bca99a --- /dev/null +++ b/libappstream-glib/as-markup.h @@ -0,0 +1,86 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * 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 + */ + +#if !defined (__APPSTREAM_GLIB_H) && !defined (AS_COMPILATION) +#error "Only <appstream-glib.h> can be included directly." +#endif + +#ifndef __AS_MARKUP_H +#define __AS_MARKUP_H + +#include <glib.h> + +G_BEGIN_DECLS + +/** + * AsMarkupConvertFormat: + * @AS_MARKUP_CONVERT_FORMAT_SIMPLE: UTF-8 text + * @AS_MARKUP_CONVERT_FORMAT_MARKDOWN: Markdown format + * @AS_MARKUP_CONVERT_FORMAT_NULL: No output + * @AS_MARKUP_CONVERT_FORMAT_APPSTREAM: AppStream (passthrough) + * @AS_MARKUP_CONVERT_FORMAT_HTML: HyperText Markup Language + * + * The format used when converting to or from AppStream descriptions. + **/ +typedef enum { + AS_MARKUP_CONVERT_FORMAT_SIMPLE, + AS_MARKUP_CONVERT_FORMAT_MARKDOWN, + AS_MARKUP_CONVERT_FORMAT_NULL, /* Since: 0.5.2 */ + AS_MARKUP_CONVERT_FORMAT_APPSTREAM, /* Since: 0.5.2 */ + AS_MARKUP_CONVERT_FORMAT_HTML, /* Since: 0.5.11 */ + /*< private >*/ + AS_MARKUP_CONVERT_FORMAT_LAST +} AsMarkupConvertFormat; + +/** + * AsMarkupConvertFlag: + * @AS_MARKUP_CONVERT_FLAG_NONE: No flags set + * @AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS: Ignore errors where possible + * + * The flags used when converting descriptions from AppStream-style. + **/ +typedef enum { + AS_MARKUP_CONVERT_FLAG_NONE = 0, + AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS = 1 << 0, + /*< private >*/ + AS_MARKUP_CONVERT_FLAG_LAST +} AsMarkupConvertFlag; + +gchar *as_markup_convert_simple (const gchar *markup, + GError **error); +gchar *as_markup_convert (const gchar *markup, + AsMarkupConvertFormat format, + GError **error); +gchar *as_markup_convert_full (const gchar *markup, + AsMarkupConvertFormat format, + AsMarkupConvertFlag flags, + GError **error); +gboolean as_markup_validate (const gchar *markup, + GError **error); +gchar **as_markup_strsplit_words (const gchar *text, + guint line_len); +gchar *as_markup_import (const gchar *text, + AsMarkupConvertFormat format, + GError **error); + +G_END_DECLS + +#endif /* __AS_MARKUP_H */ diff --git a/libappstream-glib/as-node.c b/libappstream-glib/as-node.c index 1941c98..820a9ed 100644 --- a/libappstream-glib/as-node.c +++ b/libappstream-glib/as-node.c @@ -37,6 +37,7 @@ #include <glib.h> #include <string.h> +#include "as-markup.h" #include "as-node-private.h" #include "as-utils-private.h" diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index dbc300c..43f499f 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -35,6 +35,7 @@ #include "as-icon-private.h" #include "as-image-private.h" #include "as-inf.h" +#include "as-markup.h" #include "as-monitor.h" #include "as-node-private.h" #include "as-problem.h" diff --git a/libappstream-glib/as-utils.c b/libappstream-glib/as-utils.c index d5d4a79..923ca5c 100644 --- a/libappstream-glib/as-utils.c +++ b/libappstream-glib/as-utils.c @@ -58,391 +58,6 @@ G_DEFINE_QUARK (as-utils-error-quark, as_utils_error) /** - * as_markup_import_simple: - */ -static gchar * -as_markup_import_simple (const gchar *text, GError **error) -{ - GString *str; - guint i; - g_auto(GStrv) lines = NULL; - - /* empty */ - if (text == NULL || text[0] == '\0') - return NULL; - - /* just assume paragraphs */ - str = g_string_new ("<p>"); - lines = g_strsplit (text, "\n", -1); - for (i = 0; lines[i] != NULL; i++) { - g_autofree gchar *markup = NULL; - if (lines[i][0] == '\0') { - if (g_str_has_suffix (str->str, " ")) - g_string_truncate (str, str->len - 1); - g_string_append (str, "</p><p>"); - continue; - } - markup = g_markup_escape_text (lines[i], -1); - g_string_append (str, markup); - g_string_append (str, " "); - } - if (g_str_has_suffix (str->str, " ")) - g_string_truncate (str, str->len - 1); - g_string_append (str, "</p>"); - return g_string_free (str, FALSE); -} - -/** - * as_markup_import: - * @text: the text to import. - * @format: the #AsMarkupConvertFormat, e.g. %AS_MARKUP_CONVERT_FORMAT_SIMPLE - * @error: A #GError or %NULL - * - * Imports text and converts to AppStream markup. - * - * Returns: (transfer full): appstream markup, or %NULL in event of an error - * - * Since: 0.5.11 - */ -gchar * -as_markup_import (const gchar *text, AsMarkupConvertFormat format, GError **error) -{ - if (format == AS_MARKUP_CONVERT_FORMAT_SIMPLE) - return as_markup_import_simple (text, error); - g_set_error_literal (error, - AS_UTILS_ERROR, - AS_UTILS_ERROR_INVALID_TYPE, - "unknown comnversion kind"); - return NULL; -} - -/** - * as_markup_strsplit_words: - * @text: the text to split. - * @line_len: the maximum length of the output line - * - * Splits up a long line into an array of smaller strings, each being no longer - * than @line_len. Words are not split. - * - * Returns: (transfer full): lines, or %NULL in event of an error - * - * Since: 0.3.5 - **/ -gchar ** -as_markup_strsplit_words (const gchar *text, guint line_len) -{ - GPtrArray *lines; - guint i; - g_autoptr(GString) curline = NULL; - g_auto(GStrv) tokens = NULL; - - /* sanity check */ - if (text == NULL || text[0] == '\0') - return NULL; - if (line_len == 0) - return NULL; - - lines = g_ptr_array_new (); - curline = g_string_new (""); - - /* tokenize the string */ - tokens = g_strsplit (text, " ", -1); - for (i = 0; tokens[i] != NULL; i++) { - - /* current line plus new token is okay */ - if (curline->len + strlen (tokens[i]) < line_len) { - g_string_append_printf (curline, "%s ", tokens[i]); - continue; - } - - /* too long, so remove space, add newline and dump */ - if (curline->len > 0) - g_string_truncate (curline, curline->len - 1); - g_string_append (curline, "\n"); - g_ptr_array_add (lines, g_strdup (curline->str)); - g_string_truncate (curline, 0); - g_string_append_printf (curline, "%s ", tokens[i]); - - } - - /* any incomplete line? */ - if (curline->len > 0) { - g_string_truncate (curline, curline->len - 1); - g_string_append (curline, "\n"); - g_ptr_array_add (lines, g_strdup (curline->str)); - } - - g_ptr_array_add (lines, NULL); - return (gchar **) g_ptr_array_free (lines, FALSE); -} - -/** - * as_markup_render_para: - **/ -static void -as_markup_render_para (GString *str, AsMarkupConvertFormat format, const gchar *data) -{ - guint i; - g_autofree gchar *tmp = NULL; - g_auto(GStrv) spl = NULL; - - if (str->len > 0) - g_string_append (str, "\n"); - switch (format) { - case AS_MARKUP_CONVERT_FORMAT_SIMPLE: - g_string_append_printf (str, "%s\n", data); - break; - case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: - tmp = g_markup_escape_text (data, -1); - g_string_append_printf (str, "<p>%s</p>", tmp); - break; - case AS_MARKUP_CONVERT_FORMAT_MARKDOWN: - /* break to 80 chars */ - spl = as_markup_strsplit_words (data, 80); - for (i = 0; spl[i] != NULL; i++) - g_string_append (str, spl[i]); - break; - default: - break; - } -} - -/** - * as_markup_render_li: - **/ -static void -as_markup_render_li (GString *str, AsMarkupConvertFormat format, const gchar *data) -{ - guint i; - g_autofree gchar *tmp = NULL; - g_auto(GStrv) spl = NULL; - - switch (format) { - case AS_MARKUP_CONVERT_FORMAT_SIMPLE: - g_string_append_printf (str, " • %s\n", data); - break; - case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: - tmp = g_markup_escape_text (data, -1); - g_string_append_printf (str, "<li>%s</li>", tmp); - break; - case AS_MARKUP_CONVERT_FORMAT_MARKDOWN: - /* break to 80 chars, leaving room for the dot/indent */ - spl = as_markup_strsplit_words (data, 80 - 3); - g_string_append_printf (str, " * %s", spl[0]); - for (i = 1; spl[i] != NULL; i++) - g_string_append_printf (str, " %s", spl[i]); - break; - default: - break; - } -} - -/** - * as_markup_render_ol_start: - **/ -static void -as_markup_render_ol_start (GString *str, AsMarkupConvertFormat format) -{ - switch (format) { - case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: - g_string_append (str, "<ol>"); - break; - default: - break; - } -} - -/** - * as_markup_render_ol_end: - **/ -static void -as_markup_render_ol_end (GString *str, AsMarkupConvertFormat format) -{ - switch (format) { - case AS_MARKUP_CONVERT_FORMAT_APPSTREAM: - g_string_append (str, "</ol>"); - break; - default: - break; - } -} - -/** - * as_markup_validate: - * @markup: the text to validate - * @error: A #GError or %NULL - * - * Validates some markup. - * - * Returns: %TRUE if the appstream description was valid - * - * Since: 0.5.1 - **/ -gboolean -as_markup_validate (const gchar *markup, GError **error) -{ - g_autofree gchar *tmp = NULL; - tmp = as_markup_convert (markup, AS_MARKUP_CONVERT_FORMAT_NULL, error); - return tmp != NULL; -} - -/** - * as_markup_convert_full: - * @markup: the text to copy. - * @format: the #AsMarkupConvertFormat, e.g. %AS_MARKUP_CONVERT_FORMAT_MARKDOWN - * @flags: the #AsMarkupConvertFlag, e.g. %AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS - * @error: A #GError or %NULL - * - * Converts an XML description into a printable form. - * - * Returns: (transfer full): a newly allocated %NULL terminated string - * - * Since: 0.3.5 - **/ -gchar * -as_markup_convert_full (const gchar *markup, - AsMarkupConvertFormat format, - AsMarkupConvertFlag flags, - GError **error) -{ - GNode *tmp; - GNode *tmp_c; - const gchar *tag; - const gchar *tag_c; - g_autoptr(AsNode) root = NULL; - g_autoptr(GError) error_local = NULL; - g_autoptr(GString) str = NULL; - - /* is this actually markup */ - if (g_strstr_len (markup, -1, "<") == NULL) - return g_strdup (markup); - - /* load */ - root = as_node_from_xml (markup, AS_NODE_FROM_XML_FLAG_NONE, &error_local); - if (root == NULL) { - - /* truncate to the last tag and try again */ - if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS) { - gchar *found; - g_autofree gchar *markup_new = NULL; - markup_new = g_strdup (markup); - found = g_strrstr (markup_new, "<"); - g_assert (found != NULL); - *found = '\0'; - return as_markup_convert_full (markup_new, format, flags, error); - } - - /* just return error */ - g_propagate_error (error, error_local); - error_local = NULL; - return NULL; - } - - /* format */ - str = g_string_new (""); - for (tmp = root->children; tmp != NULL; tmp = tmp->next) { - - tag = as_node_get_name (tmp); - if (g_strcmp0 (tag, "p") == 0) { - as_markup_render_para (str, format, as_node_get_data (tmp)); - continue; - } - - /* loop on the children */ - if (g_strcmp0 (tag, "ul") == 0 || - g_strcmp0 (tag, "ol") == 0) { - as_markup_render_ol_start (str, format); - for (tmp_c = tmp->children; tmp_c != NULL; tmp_c = tmp_c->next) { - tag_c = as_node_get_name (tmp_c); - if (g_strcmp0 (tag_c, "li") == 0) { - as_markup_render_li (str, format, - as_node_get_data (tmp_c)); - continue; - } - - /* just abort the list */ - if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS) - break; - - /* only <li> is valid in lists */ - g_set_error (error, - AS_NODE_ERROR, - AS_NODE_ERROR_FAILED, - "Tag %s in %s invalid", - tag_c, tag); - return NULL; - } - as_markup_render_ol_end (str, format); - continue; - } - - /* just try again */ - if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS) - continue; - - /* only <p>, <ul> and <ol> is valid here */ - g_set_error (error, - AS_NODE_ERROR, - AS_NODE_ERROR_FAILED, - "Unknown tag '%s'", tag); - return NULL; - } - - /* success */ - switch (format) { - case AS_MARKUP_CONVERT_FORMAT_SIMPLE: - case AS_MARKUP_CONVERT_FORMAT_MARKDOWN: - if (str->len > 0) - g_string_truncate (str, str->len - 1); - break; - default: - break; - } - return g_strdup (str->str); -} - -/** - * as_markup_convert: - * @markup: the text to copy. - * @format: the #AsMarkupConvertFormat, e.g. %AS_MARKUP_CONVERT_FORMAT_MARKDOWN - * @error: A #GError or %NULL - * - * Converts an XML description into a printable form. - * - * Returns: (transfer full): a newly allocated %NULL terminated string - * - * Since: 0.3.5 - **/ -gchar * -as_markup_convert (const gchar *markup, - AsMarkupConvertFormat format, GError **error) -{ - return as_markup_convert_full (markup, format, - AS_MARKUP_CONVERT_FLAG_NONE, - error); -} - -/** - * as_markup_convert_simple: - * @markup: the text to copy. - * @error: A #GError or %NULL - * - * Converts an XML description into a printable form. - * - * Returns: (transfer full): a newly allocated %NULL terminated string - * - * Since: 0.1.0 - **/ -gchar * -as_markup_convert_simple (const gchar *markup, GError **error) -{ - return as_markup_convert_full (markup, - AS_MARKUP_CONVERT_FORMAT_SIMPLE, - AS_MARKUP_CONVERT_FLAG_NONE, - error); -} - -/** * as_hash_lookup_by_locale: * @hash: a #GHashTable. * @locale: the locale, or %NULL to use the users default local. diff --git a/libappstream-glib/as-utils.h b/libappstream-glib/as-utils.h index 7c5ffda..8c0c5cf 100644 --- a/libappstream-glib/as-utils.h +++ b/libappstream-glib/as-utils.h @@ -77,38 +77,6 @@ typedef enum { } AsUtilsLocation; /** - * AsMarkupConvertFormat: - * @AS_MARKUP_CONVERT_FORMAT_SIMPLE: UTF-8 text - * @AS_MARKUP_CONVERT_FORMAT_MARKDOWN: Markdown format - * @AS_MARKUP_CONVERT_FORMAT_NULL: No output - * @AS_MARKUP_CONVERT_FORMAT_APPSTREAM: AppStream (passthrough) - * - * The format used when converting to or from AppStream descriptions. - **/ -typedef enum { - AS_MARKUP_CONVERT_FORMAT_SIMPLE, - AS_MARKUP_CONVERT_FORMAT_MARKDOWN, - AS_MARKUP_CONVERT_FORMAT_NULL, /* Since: 0.5.2 */ - AS_MARKUP_CONVERT_FORMAT_APPSTREAM, /* Since: 0.5.2 */ - /*< private >*/ - AS_MARKUP_CONVERT_FORMAT_LAST -} AsMarkupConvertFormat; - -/** - * AsMarkupConvertFlag: - * @AS_MARKUP_CONVERT_FLAG_NONE: No flags set - * @AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS: Ignore errors where possible - * - * The flags used when converting descriptions from AppStream-style. - **/ -typedef enum { - AS_MARKUP_CONVERT_FLAG_NONE = 0, - AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS = 1 << 0, - /*< private >*/ - AS_MARKUP_CONVERT_FLAG_LAST -} AsMarkupConvertFlag; - -/** * AsVersionParseFlag: * @AS_VERSION_PARSE_FLAG_NONE: No flags set * @AS_VERSION_PARSE_FLAG_USE_TRIPLET: Use Microsoft-style version numbers @@ -122,23 +90,6 @@ typedef enum { AS_VERSION_PARSE_FLAG_LAST } AsVersionParseFlag; -gchar *as_markup_convert_simple (const gchar *markup, - GError **error); -gchar *as_markup_convert (const gchar *markup, - AsMarkupConvertFormat format, - GError **error); -gchar *as_markup_convert_full (const gchar *markup, - AsMarkupConvertFormat format, - AsMarkupConvertFlag flags, - GError **error); -gboolean as_markup_validate (const gchar *markup, - GError **error); -gchar **as_markup_strsplit_words (const gchar *text, - guint line_len); -gchar *as_markup_import (const gchar *text, - AsMarkupConvertFormat format, - GError **error); - GQuark as_utils_error_quark (void); gboolean as_utils_is_stock_icon_name (const gchar *name); gboolean as_utils_is_spdx_license_id (const gchar *license_id); |