From 6a43559f4fb7542ed95968357fdc72abfd5e0bac Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 23 Nov 2017 12:10:39 +0000 Subject: Add a Markup plugin. --- slixmpp/plugins/xep_0394/markup.py | 161 +++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 slixmpp/plugins/xep_0394/markup.py (limited to 'slixmpp/plugins/xep_0394/markup.py') diff --git a/slixmpp/plugins/xep_0394/markup.py b/slixmpp/plugins/xep_0394/markup.py new file mode 100644 index 00000000..d3ec69e6 --- /dev/null +++ b/slixmpp/plugins/xep_0394/markup.py @@ -0,0 +1,161 @@ +""" + Slixmpp: The Slick XMPP Library + Copyright (C) 2017 Emmanuel Gil Peyrot + This file is part of Slixmpp. + + See the file LICENSE for copying permission. +""" + + +from slixmpp.stanza import Message +from slixmpp.plugins import BasePlugin +from slixmpp.xmlstream import register_stanza_plugin, ET, tostring +from slixmpp.plugins.xep_0394 import stanza, Markup, Span, BlockCode, List, Li, BlockQuote +from slixmpp.plugins.xep_0071 import XHTML_IM + + +class Start: + def __init__(self, elem): + self.elem = elem + + def __repr__(self): + return 'Start(%s)' % self.elem + + +class End: + def __init__(self, elem): + self.elem = elem + + def __repr__(self): + return 'End(%s)' % self.elem + + +class XEP_0394(BasePlugin): + + name = 'xep_0394' + description = 'XEP-0394: Message Markup' + dependencies = {'xep_0030', 'xep_0071'} + stanza = stanza + + def plugin_init(self): + register_stanza_plugin(Message, Markup) + + def session_bind(self, jid): + self.xmpp['xep_0030'].add_feature(feature=Markup.namespace) + + def plugin_end(self): + self.xmpp['xep_0030'].del_feature(feature=Markup.namespace) + + @staticmethod + def _split_first_level(body, markup_elem): + split_points = [] + elements = {} + for markup in markup_elem['substanzas']: + start = markup['start'] + end = markup['end'] + split_points.append(start) + split_points.append(end) + elements.setdefault(start, []).append(Start(markup)) + elements.setdefault(end, []).append(End(markup)) + if isinstance(markup, List): + lis = markup['lis'] + for i, li in enumerate(lis): + start = li['start'] + split_points.append(start) + li_end = lis[i + 1]['start'] if i < len(lis) - 1 else end + elements.setdefault(li_end, []).append(End(li)) + elements.setdefault(start, []).append(Start(li)) + split_points = set(split_points) + new_body = [[]] + for i, letter in enumerate(body + '\x00'): + if i in split_points: + body_elements = [] + for elem in elements[i]: + body_elements.append(elem) + new_body.append(body_elements) + new_body.append([]) + new_body[-1].append(letter) + new_body[-1] = new_body[-1][:-1] + final = [] + for chunk in new_body: + if not chunk: + continue + final.append(''.join(chunk) if isinstance(chunk[0], str) else chunk) + return final + + def to_plain_text(self, body, markup_elem): + chunks = self._split_first_level(body, markup_elem) + final = [] + for chunk in chunks: + if isinstance(chunk, str): + final.append(chunk) + return ''.join(final) + + def to_xhtml_im(self, body, markup_elem): + chunks = self._split_first_level(body, markup_elem) + final = [] + stack = [] + for chunk in chunks: + if isinstance(chunk, str): + chunk = (chunk.replace("&", '&') + .replace('<', '<') + .replace('>', '>') + .replace('"', '"') + .replace("'", ''') + .replace('\n', '
')) + final.append(chunk) + continue + num_end = 0 + for elem in chunk: + if isinstance(elem, End): + num_end += 1 + + for i in range(num_end): + stack_top = stack.pop() + for elem in chunk: + if not isinstance(elem, End): + continue + elem = elem.elem + if elem is stack_top: + if isinstance(elem, Span): + final.append('') + elif isinstance(elem, BlockCode): + final.append('') + elif isinstance(elem, List): + final.append('') + elif isinstance(elem, Li): + final.append('') + elif isinstance(elem, BlockQuote): + final.append('') + break + else: + assert False + for elem in chunk: + if not isinstance(elem, Start): + continue + elem = elem.elem + stack.append(elem) + if isinstance(elem, Span): + style = [] + for type_ in elem['types']: + if type_ == 'emphasis': + style.append('font-style: italic;') + if type_ == 'code': + style.append('font-family: monospace;') + if type_ == 'deleted': + style.append('text-decoration: line-through;') + final.append("" % ' '.join(style)) + elif isinstance(elem, BlockCode): + final.append('
')
+                elif isinstance(elem, List):
+                    final.append('
    ') + elif isinstance(elem, Li): + final.append('
  • ') + elif isinstance(elem, BlockQuote): + final.append('
    ') + p = "

    %s

    " % ''.join(final) + p2 = ET.fromstring(p) + print('coucou', p, tostring(p2)) + xhtml_im = XHTML_IM() + xhtml_im['body'] = p2 + return xhtml_im -- cgit v1.2.3