diff --git a/lib/naughty/widget/_markup.lua b/lib/naughty/widget/_markup.lua new file mode 100644 index 00000000..3077c02b --- /dev/null +++ b/lib/naughty/widget/_markup.lua @@ -0,0 +1,62 @@ +local beautiful = require("beautiful") + +local module = {} + +-- Since some escaping needs to be undone, we have to escape the escaped <>. +local pre_escape = {["<"] = "&zzlt;", [">"] = "&zzgt;"} + +local escape_pattern = "[<>&]" +local escape_subs = { ['<'] = "<", ['>'] = ">", ['&'] = "&" } + +-- Also reverse escaping some allowed tags because people actually use them. +local escape_undo = {['<span '] = "" + escape_undo['</'..allowed..'>'] = "" +end + +-- Best effort attempt to allow a subset of pango markup in the text while +-- removing invalid content. If invalid content is present, nothing is +-- displayed. +local function escape_text(text) + -- Take care of the already escaped content. + for pattern, subs in pairs(pre_escape) do + text = text:gsub(pattern, subs) + end + + -- Try to set the text while only interpreting
. + text = text:gsub("", "\n") + + -- Since the title cannot contain markup, it must be escaped first so that + -- it is not interpreted by Pango later. + text = text:gsub(escape_pattern, escape_subs) + + -- Restore a subset of markup tags. + for pattern, subs in pairs(escape_undo) do + text = text:gsub(pattern, subs) + end + + -- Restore pre-escaped content. + for subs, pattern in pairs(pre_escape) do + text = text:gsub(pattern, subs) + end + + return text +end + +function module.set_markup(wdg, text, fg, font) + local ret = escape_text(text or "") + fg = fg or beautiful.notification_fg + + wdg:set_font(font or beautiful.notification_font) + + if fg then + ret = "" .. ret .. "" + end + + wdg:set_markup_silently(ret) + return ret +end + +return module diff --git a/lib/naughty/widget/message.lua b/lib/naughty/widget/message.lua index c9f31fb7..0dac616e 100644 --- a/lib/naughty/widget/message.lua +++ b/lib/naughty/widget/message.lua @@ -17,22 +17,10 @@ local textbox = require("wibox.widget.textbox") local gtable = require("gears.table") local beautiful = require("beautiful") +local markup = require("naughty.widget._markup").set_markup local message = {} -local function markup(notif, wdg) - local ret = notif.message or "" - local fg = notif.fg or beautiful.notification_fg - - wdg:set_font(notif.font or beautiful.notification_font) - - if fg then - ret = "" .. ret .. "" - end - - return ret -end - --- The attached notification. -- @property notification -- @tparam naughty.notification notification @@ -48,7 +36,7 @@ function message:set_notification(notif) self._private.message_changed_callback) end - self:set_markup(markup(notif, self)) + markup(self, notif.message, notif.fg, notif.font) self._private.notification = notif @@ -73,7 +61,12 @@ local function new(args) gtable.crush(tb, message, true) function tb._private.message_changed_callback() - tb:set_markup(markup(tb._private.notification, tb)) + markup( + tb, + tb._private.notification.message, + tb._private.notification.fg, + tb._private.notification.font + ) end if args.notification then diff --git a/lib/naughty/widget/title.lua b/lib/naughty/widget/title.lua index 38ce7327..6f35dc2b 100644 --- a/lib/naughty/widget/title.lua +++ b/lib/naughty/widget/title.lua @@ -17,22 +17,10 @@ local textbox = require("wibox.widget.textbox") local gtable = require("gears.table") local beautiful = require("beautiful") +local markup = require("naughty.widget._markup").set_markup local title = {} -local function markup(notif, wdg) - local ret = ""..(notif.title or "").."" - local fg = notif.fg or beautiful.notification_fg - - wdg:set_font(notif.font or beautiful.notification_font) - - if fg then - ret = "" .. ret .. "" - end - - return ret -end - --- The attached notification. -- @property notification -- @tparam naughty.notification notification @@ -48,7 +36,7 @@ function title:set_notification(notif) self._private.title_changed_callback) end - self:set_markup(markup(notif, self)) + markup(self, notif.title, notif.fg, notif.font) self._private.notification = notif self._private.title_changed_callback() @@ -74,7 +62,12 @@ local function new(args) gtable.crush(tb, title, true) function tb._private.title_changed_callback() - tb:set_markup(markup(tb._private.notification, tb)) + markup( + tb, + tb._private.notification.title, + tb._private.notification.fg, + tb._private.notification.font + ) end if args.notification then