Merge pull request #309 from LukeShu/tidy-markup
Tidy and fix markup handling.
This commit is contained in:
commit
96ebb4625a
110
src/markup.c
Normal file
110
src/markup.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* copyright 2013 Sascha Kruse and contributors (see LICENSE for licensing information) */
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "markup.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "utils.h"
|
||||
|
||||
static char *markup_quote(char *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
str = string_replace_all("&", "&", str);
|
||||
str = string_replace_all("\"", """, str);
|
||||
str = string_replace_all("'", "'", str);
|
||||
str = string_replace_all("<", "<", str);
|
||||
str = string_replace_all(">", ">", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *markup_unquote(char *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
str = string_replace_all(""", "\"", str);
|
||||
str = string_replace_all("'", "'", str);
|
||||
str = string_replace_all("<", "<", str);
|
||||
str = string_replace_all(">", ">", str);
|
||||
str = string_replace_all("&", "&", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *markup_br2nl(char *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
str = string_replace_all("<br>", "\n", str);
|
||||
str = string_replace_all("<br/>", "\n", str);
|
||||
str = string_replace_all("<br />", "\n", str);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip any markup from text; turn it in to plain text.
|
||||
*
|
||||
* For well-formed markup, the following two commands should be
|
||||
* roughly equivalent:
|
||||
*
|
||||
* out = markup_strip(in);
|
||||
* pango_parse_markup(in, -1, 0, NULL, &out, NULL, NULL);
|
||||
*
|
||||
* However, `pango_parse_markup()` balks at invalid markup;
|
||||
* `markup_strip()` shouldn't care if there is invalid markup.
|
||||
*/
|
||||
char *markup_strip(char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* strip all tags */
|
||||
string_strip_delimited(str, '<', '>');
|
||||
|
||||
/* unquote the remainder */
|
||||
str = markup_unquote(str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform the string in accordance with `markup_mode` and
|
||||
* `settings.ignore_newline`
|
||||
*/
|
||||
char *markup_transform(char *str, enum markup_mode markup_mode)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (markup_mode) {
|
||||
case MARKUP_NULL:
|
||||
/* `assert(false)`, but with a meaningful error message */
|
||||
assert(markup_mode != MARKUP_NULL);
|
||||
break;
|
||||
case MARKUP_NO:
|
||||
str = markup_quote(str);
|
||||
break;
|
||||
case MARKUP_STRIP:
|
||||
str = markup_br2nl(str);
|
||||
str = markup_strip(str);
|
||||
str = markup_quote(str);
|
||||
break;
|
||||
case MARKUP_FULL:
|
||||
str = markup_br2nl(str);
|
||||
break;
|
||||
}
|
||||
|
||||
if (settings.ignore_newline) {
|
||||
str = string_replace_all("\n", " ", str);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
11
src/markup.h
Normal file
11
src/markup.h
Normal file
@ -0,0 +1,11 @@
|
||||
/* copyright 2013 Sascha Kruse and contributors (see LICENSE for licensing information) */
|
||||
#ifndef DUNST_MARKUP_H
|
||||
#define DUNST_MARKUP_H
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
char *markup_strip(char *str);
|
||||
char *markup_transform(char *str, enum markup_mode markup_mode);
|
||||
|
||||
#endif
|
||||
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "dbus.h"
|
||||
#include "dunst.h"
|
||||
#include "markup.h"
|
||||
#include "menu.h"
|
||||
#include "rules.h"
|
||||
#include "settings.h"
|
||||
@ -196,46 +197,6 @@ void notification_free(notification * n)
|
||||
g_free(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip any markup from text
|
||||
*/
|
||||
char *notification_strip_markup(char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* strip all tags */
|
||||
string_strip_delimited(str, '<', '>');
|
||||
|
||||
/* unquote the remainder */
|
||||
str = string_replace_all(""", "\"", str);
|
||||
str = string_replace_all("'", "'", str);
|
||||
str = string_replace_all("&", "&", str);
|
||||
str = string_replace_all("<", "<", str);
|
||||
str = string_replace_all(">", ">", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quote a text string for rendering with pango
|
||||
*/
|
||||
char *notification_quote_markup(char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = string_replace_all("&", "&", str);
|
||||
str = string_replace_all("\"", """, str);
|
||||
str = string_replace_all("'", "'", str);
|
||||
str = string_replace_all("<", "<", str);
|
||||
str = string_replace_all(">", ">", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace all occurrences of "needle" with a quoted "replacement",
|
||||
* according to the markup settings.
|
||||
@ -245,32 +206,7 @@ char *notification_replace_format(const char *needle, const char *replacement,
|
||||
char* tmp;
|
||||
char* ret;
|
||||
|
||||
if (markup_mode == MARKUP_NO) {
|
||||
tmp = g_strdup(replacement);
|
||||
tmp = notification_quote_markup(tmp);
|
||||
} else {
|
||||
tmp = g_strdup(replacement);
|
||||
if (settings.ignore_newline) {
|
||||
tmp = string_replace_all("<br>", " ", tmp);
|
||||
tmp = string_replace_all("<br/>", " ", tmp);
|
||||
tmp = string_replace_all("<br />", " ", tmp);
|
||||
} else {
|
||||
tmp = string_replace_all("<br>", "\n", tmp);
|
||||
tmp = string_replace_all("<br/>", "\n", tmp);
|
||||
tmp = string_replace_all("<br />", "\n", tmp);
|
||||
}
|
||||
|
||||
if (markup_mode != MARKUP_FULL ) {
|
||||
tmp = notification_strip_markup(tmp);
|
||||
tmp = notification_quote_markup(tmp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (settings.ignore_newline) {
|
||||
tmp = string_replace_all("\n", " ", tmp);
|
||||
}
|
||||
|
||||
tmp = markup_transform(g_strdup(replacement), markup_mode);
|
||||
ret = string_replace_all(needle, tmp, haystack);
|
||||
g_free(tmp);
|
||||
|
||||
|
@ -69,8 +69,6 @@ int notification_is_duplicate(const notification *a, const notification *b);
|
||||
void notification_run_script(notification * n);
|
||||
int notification_close(notification * n, int reason);
|
||||
void notification_print(notification * n);
|
||||
char *notification_strip_markup(char *str);
|
||||
char *notification_quote_markup(char *str);
|
||||
char *notification_replace_format(const char *needle, const char *replacement, char *haystack, enum markup_mode markup);
|
||||
void notification_update_text_to_render(notification *n);
|
||||
int notification_get_ttl(notification *n);
|
||||
|
3
src/x.c
3
src/x.c
@ -22,6 +22,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dunst.h"
|
||||
#include "markup.h"
|
||||
#include "notification.h"
|
||||
#include "settings.h"
|
||||
#include "utils.h"
|
||||
@ -475,7 +476,7 @@ static colored_layout *r_create_layout_from_notification(cairo_t *c, notificatio
|
||||
pango_layout_set_attributes(cl->l, cl->attr);
|
||||
} else {
|
||||
/* remove markup and display plain message instead */
|
||||
n->text_to_render = notification_strip_markup(n->text_to_render);
|
||||
n->text_to_render = markup_strip(n->text_to_render);
|
||||
cl->text = NULL;
|
||||
cl->attr = NULL;
|
||||
pango_layout_set_text(cl->l, n->text_to_render, -1);
|
||||
|
57
test/markup.c
Normal file
57
test/markup.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include "greatest.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "src/markup.h"
|
||||
|
||||
TEST test_markup_strip(void)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ASSERT_STR_EQ(""", (ptr=markup_strip(g_strdup("&quot;"))));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ("'", (ptr=markup_strip(g_strdup("&apos;"))));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ("<", (ptr=markup_strip(g_strdup("&lt;"))));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ(">", (ptr=markup_strip(g_strdup("&gt;"))));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ("&", (ptr=markup_strip(g_strdup("&amp;"))));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ(">A ", (ptr=markup_strip(g_strdup(">A <img> <string"))));
|
||||
g_free(ptr);
|
||||
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST test_markup_transform(void)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
settings.ignore_newline = false;
|
||||
ASSERT_STR_EQ("<i>foo</i><br>bar\nbaz", (ptr=markup_transform(g_strdup("<i>foo</i><br>bar\nbaz"), MARKUP_NO)));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ("foo\nbar\nbaz", (ptr=markup_transform(g_strdup("<i>foo</i><br>bar\nbaz"), MARKUP_STRIP)));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ("<i>foo</i>\nbar\nbaz", (ptr=markup_transform(g_strdup("<i>foo</i><br>bar\nbaz"), MARKUP_FULL)));
|
||||
g_free(ptr);
|
||||
|
||||
settings.ignore_newline = true;
|
||||
ASSERT_STR_EQ("<i>foo</i><br>bar baz", (ptr=markup_transform(g_strdup("<i>foo</i><br>bar\nbaz"), MARKUP_NO)));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ("foo bar baz", (ptr=markup_transform(g_strdup("<i>foo</i><br>bar\nbaz"), MARKUP_STRIP)));
|
||||
g_free(ptr);
|
||||
ASSERT_STR_EQ("<i>foo</i> bar baz", (ptr=markup_transform(g_strdup("<i>foo</i><br>bar\nbaz"), MARKUP_FULL)));
|
||||
g_free(ptr);
|
||||
|
||||
PASS();
|
||||
}
|
||||
|
||||
SUITE(suite_markup)
|
||||
{
|
||||
RUN_TEST(test_markup_strip);
|
||||
RUN_TEST(test_markup_transform);
|
||||
}
|
||||
|
||||
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
@ -3,6 +3,7 @@
|
||||
SUITE_EXTERN(suite_utils);
|
||||
SUITE_EXTERN(suite_option_parser);
|
||||
SUITE_EXTERN(suite_notification);
|
||||
SUITE_EXTERN(suite_markup);
|
||||
|
||||
GREATEST_MAIN_DEFS();
|
||||
|
||||
@ -11,6 +12,7 @@ int main(int argc, char *argv[]) {
|
||||
RUN_SUITE(suite_utils);
|
||||
RUN_SUITE(suite_option_parser);
|
||||
RUN_SUITE(suite_notification);
|
||||
RUN_SUITE(suite_markup);
|
||||
GREATEST_MAIN_END();
|
||||
}
|
||||
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
||||
|
Loading…
x
Reference in New Issue
Block a user