From 9de322bea3fe5e9431fd1a5aeef8841ef27b19c1 Mon Sep 17 00:00:00 2001 From: mathieui Date: Tue, 14 May 2013 22:29:45 +0200 Subject: Rewrite the poezio colors parser (also Fix #2279) The parser now handles text with multiple style attributes (e.g. bold, underlined and red text). --- src/xhtml.py | 93 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/xhtml.py b/src/xhtml.py index cae3e8f4..11435ab3 100644 --- a/src/xhtml.py +++ b/src/xhtml.py @@ -398,61 +398,64 @@ number_to_color_names = { 7: 'white' } +def format_inline_css(_dict): + return ''.join(('%s: %s;' % (key, value) for key, value in _dict.items())) + def poezio_colors_to_html(string): """ - Convert poezio colors to html makups - (e.g. \x191: ) + Convert poezio colors to html + (e.g. \x191}: ) """ - # XXX: You cannot underline AND use color on the same portion of your - # message (because both these things use a element, and the - # current way it is done, when you open a element, you close the - # previous one). Dectecting if a span is already opened, close it and - # reopen it with the same style PLUS the new style seems complicated. - # I'll keep it that way unless someone fixes that properly. - - # a list of all opened elements, e.g. ['strong', 'span'] - # So that we know what we need to close - opened_elements = [] - res = "

" + # Maintain a list of the current css attributes used + # And check if a tag is open (by design, we only open + # spans tag, and they cannot be nested. + current_attrs = {} + tag_open = False next_attr_char = string.find('\x19') + build = ["

"] + + def check_property(key, value): + nonlocal tag_open + if current_attrs.get(key, None) == value: + return + current_attrs[key] = value + if tag_open: + tag_open = False + build.append('') + while next_attr_char != -1: attr_char = string[next_attr_char+1].lower() - if next_attr_char != 0: - res += xml.sax.saxutils.escape(string[:next_attr_char]) + + if next_attr_char != 0 and string[:next_attr_char]: + if current_attrs and not tag_open: + build.append('' % format_inline_css(current_attrs)) + tag_open = True + build.append(xml.sax.saxutils.escape(string[:next_attr_char])) + if attr_char == 'o': - for elem in opened_elements[::-1]: - res += '' % (elem,) - opened_elements = [] + if tag_open: + build.append('') + tag_open = False + current_attrs = {} elif attr_char == 'b': - if 'strong' not in opened_elements: - opened_elements.append('strong') - res += '' + check_property('font-weight', 'bold') elif attr_char == 'u': - if 'strong' in opened_elements: - res += '' - opened_elements.remove('strong') - if 'span' in opened_elements: - res += '' - else: - opened_elements.append('span') - res += "" + check_property('text-decoration', 'underline') + if attr_char in digits: - number_str = string[next_attr_char+1:string.find('}', next_attr_char)] - number = int(number_str) - if 'strong' in opened_elements: - res += '' - opened_elements.remove('strong') - if 'span' in opened_elements: - res += '' - else: - opened_elements.append('span') - res += "" % (ncurses_color_to_html(number),) - string = string[next_attr_char+len(number_str)+2:] + number = int(attr_char) + check_property('color', number_to_color_names.get(number, 'black')) + string = string[next_attr_char+3:] else: string = string[next_attr_char+2:] next_attr_char = string.find('\x19') - res += xml.sax.saxutils.escape(string) - for elem in opened_elements[::-1]: - res += '' % (elem,) - res += "

" - return res.replace('\n', '
') + + if current_attrs and not tag_open and string: + build.append('' % format_inline_css(current_attrs)) + tag_open = True + build.append(xml.sax.saxutils.escape(string)) + if tag_open: + build.append('') + build.append("

") + text = ''.join(build) + return text.replace('\n', '
') -- cgit v1.2.3