annotate cagou/core/simple_xhtml.py @ 488:beedff600d2b

blog: blog widget implementation: this patch implements a basic blog widget. The search bare can be used to change node (only node for now, will be improved to do search and all). Publication on current node can be done by pressing the pencil icon. A checkbox can be activated to use end-to-end encryption. No pagination or comments are supported for now. Due to lack of HTML rendering in Kivy, only simple formatting is supported. If item is end-2-end encrypted, a green closed locker is shown next to publication date. rel 380
author Goffi <goffi@goffi.org>
date Sat, 15 Oct 2022 20:20:10 +0200
parents 3c9ba4a694ef
children 203755bbe0fe
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
379
1da3c379205b fixed shebangs
Goffi <goffi@goffi.org>
parents: 378
diff changeset
1 #!/usr/bin/env python3
1da3c379205b fixed shebangs
Goffi <goffi@goffi.org>
parents: 378
diff changeset
2
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client
461
3c9ba4a694ef dates update
Goffi <goffi@goffi.org>
parents: 453
diff changeset
5 # Copyright (C) 2016-2021 Jérôme Poisson (goffi@goffi.org)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
20
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
21 from xml.etree import ElementTree as ET
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
22 from kivy.uix.stacklayout import StackLayout
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
23 from kivy.uix.label import Label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
24 from kivy.utils import escape_markup
422
efee0e0afb78 core (common): moved simple_xhtml's image code to a generic "SizedImage" widget
Goffi <goffi@goffi.org>
parents: 379
diff changeset
25 from kivy.metrics import sp
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from kivy import properties
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
27 from sat.core import log as logging
106
9909ed7a7a20 moved SimpleXHTMLWidget to a dedicated module
Goffi <goffi@goffi.org>
parents: 105
diff changeset
28 from sat_frontends.tools import css_color, strings as sat_strings
335
597cc207c8e7 core (simple_xhtml): handle `aesgcm` schemes:
Goffi <goffi@goffi.org>
parents: 325
diff changeset
29 from cagou import G
422
efee0e0afb78 core (common): moved simple_xhtml's image code to a generic "SizedImage" widget
Goffi <goffi@goffi.org>
parents: 379
diff changeset
30 from cagou.core.common import SizedImage
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
31
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
32
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
33 log = logging.getLogger(__name__)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
34
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
35
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
36 class Escape(str):
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
37 """Class used to mark that a message need to be escaped"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
38
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
39
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
40 class SimpleXHTMLWidgetEscapedText(Label):
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
41
185
ab3f5173ef5c chat, simple XHTML: font size adjustement
Goffi <goffi@goffi.org>
parents: 126
diff changeset
42 def on_parent(self, instance, parent):
288
44752e8031f8 simple XHTML: fixed crash when parent is set to None + fixed bold restoration when escaped message is modified
Goffi <goffi@goffi.org>
parents: 284
diff changeset
43 if parent is not None:
44752e8031f8 simple XHTML: fixed crash when parent is set to None + fixed bold restoration when escaped message is modified
Goffi <goffi@goffi.org>
parents: 284
diff changeset
44 self.font_size = parent.font_size
185
ab3f5173ef5c chat, simple XHTML: font size adjustement
Goffi <goffi@goffi.org>
parents: 126
diff changeset
45
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
46 def _addUrlMarkup(self, text):
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
47 text_elts = []
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
48 idx = 0
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
49 links = 0
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
50 while True:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
51 m = sat_strings.RE_URL.search(text[idx:])
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
52 if m is not None:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
53 text_elts.append(escape_markup(m.string[0:m.start()]))
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
54 link_key = 'link_' + str(links)
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
55 url = m.group()
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
56 escaped_url = escape_markup(url)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
57 text_elts.append(
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
58 f'[color=5500ff][ref={link_key}]{escaped_url}[/ref][/color]')
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
59 if not links:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
60 self.ref_urls = {link_key: url}
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
61 else:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
62 self.ref_urls[link_key] = url
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
63 links += 1
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
64 idx += m.end()
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
65 else:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
66 if links:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
67 text_elts.append(escape_markup(text[idx:]))
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
68 self.markup = True
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
69 self.text = ''.join(text_elts)
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
70 break
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
71
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
72 def on_text(self, instance, text):
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
73 # do NOT call the method if self.markup is set
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
74 # this would result in infinite loop (because self.text
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
75 # is changed if an URL is found, and in this case markup too)
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
76 if text and not self.markup:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
77 self._addUrlMarkup(text)
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
78
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
79 def on_ref_press(self, ref):
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
80 url = self.ref_urls[ref]
344
83697218b9b2 core: handle URLs opening in a per-platform way:
Goffi <goffi@goffi.org>
parents: 335
diff changeset
81 G.local_platform.open_url(url, self)
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
82
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
83
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
84 class SimpleXHTMLWidgetText(Label):
185
ab3f5173ef5c chat, simple XHTML: font size adjustement
Goffi <goffi@goffi.org>
parents: 126
diff changeset
85
ab3f5173ef5c chat, simple XHTML: font size adjustement
Goffi <goffi@goffi.org>
parents: 126
diff changeset
86 def on_parent(self, instance, parent):
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
87 if parent is not None:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
88 self.font_size = parent.font_size
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
89
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
90
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
91 class SimpleXHTMLWidget(StackLayout):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
92 """widget handling simple XHTML parsing"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
93 xhtml = properties.StringProperty()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
94 color = properties.ListProperty([1, 1, 1, 1])
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
95 # XXX: bold is only used for escaped text
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
96 bold = properties.BooleanProperty(False)
185
ab3f5173ef5c chat, simple XHTML: font size adjustement
Goffi <goffi@goffi.org>
parents: 126
diff changeset
97 font_size = properties.NumericProperty(sp(14))
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
98
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
99 # text/XHTML input
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
100
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
101 def on_xhtml(self, instance, xhtml):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
102 """parse xhtml and set content accordingly
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
103
288
44752e8031f8 simple XHTML: fixed crash when parent is set to None + fixed bold restoration when escaped message is modified
Goffi <goffi@goffi.org>
parents: 284
diff changeset
104 if xhtml is an instance of Escape, a Label with no markup will be used
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
105 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
106 self.clear_widgets()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
107 if isinstance(xhtml, Escape):
288
44752e8031f8 simple XHTML: fixed crash when parent is set to None + fixed bold restoration when escaped message is modified
Goffi <goffi@goffi.org>
parents: 284
diff changeset
108 label = SimpleXHTMLWidgetEscapedText(
44752e8031f8 simple XHTML: fixed crash when parent is set to None + fixed bold restoration when escaped message is modified
Goffi <goffi@goffi.org>
parents: 284
diff changeset
109 text=xhtml, color=self.color, bold=self.bold)
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
110 self.bind(font_size=label.setter('font_size'))
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
111 self.bind(color=label.setter('color'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
112 self.bind(bold=label.setter('bold'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
113 self.add_widget(label)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
114 else:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
115 xhtml = ET.fromstring(xhtml.encode())
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
116 self.current_wid = None
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
117 self.styles = []
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
118 self._callParseMethod(xhtml)
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
119 if len(self.children) > 1:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
120 self._do_split_labels()
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
121
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
122 def escape(self, text):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
123 """mark that a text need to be escaped (i.e. no markup)"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
124 return Escape(text)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
125
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
126 def _do_split_labels(self):
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
127 """Split labels so their content can flow with images"""
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
128 # XXX: to make things easier, we split labels in words
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
129 log.debug("labels splitting start")
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
130 children = self.children[::-1]
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
131 self.clear_widgets()
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
132 for child in children:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
133 if isinstance(child, Label):
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
134 log.debug("label before split: {}".format(child.text))
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
135 styles = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
136 tag = False
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
137 new_text = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
138 current_tag = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
139 current_value = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
140 current_wid = self._createText()
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
141 value = False
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
142 close = False
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
143 # we will parse the text and create a new widget
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
144 # on each new word (actually each space)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
145 # FIXME: handle '\n' and other white chars
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
146 for c in child.text:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
147 if tag:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
148 # we are parsing a markup tag
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
149 if c == ']':
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
150 current_tag_s = ''.join(current_tag)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
151 current_style = (current_tag_s, ''.join(current_value))
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
152 if close:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
153 for idx, s in enumerate(reversed(styles)):
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
154 if s[0] == current_tag_s:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
155 del styles[len(styles) - idx - 1]
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
156 break
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
157 else:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
158 styles.append(current_style)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
159 current_tag = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
160 current_value = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
161 tag = False
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
162 value = False
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
163 close = False
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
164 elif c == '/':
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
165 close = True
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
166 elif c == '=':
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
167 value = True
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
168 elif value:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
169 current_value.append(c)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
170 else:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
171 current_tag.append(c)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
172 new_text.append(c)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
173 else:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
174 # we are parsing regular text
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
175 if c == '[':
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
176 new_text.append(c)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
177 tag = True
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
178 elif c == ' ':
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
179 # new word, we do a new widget
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
180 new_text.append(' ')
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
181 for t, v in reversed(styles):
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
182 new_text.append('[/{}]'.format(t))
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
183 current_wid.text = ''.join(new_text)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
184 new_text = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
185 self.add_widget(current_wid)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
186 log.debug("new widget: {}".format(current_wid.text))
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
187 current_wid = self._createText()
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
188 for t, v in styles:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
189 new_text.append('[{tag}{value}]'.format(
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
190 tag = t,
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
191 value = '={}'.format(v) if v else ''))
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
192 else:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
193 new_text.append(c)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
194 if current_wid.text:
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
195 # we may have a remaining widget after the parsing
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
196 close_styles = []
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
197 for t, v in reversed(styles):
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
198 close_styles.append('[/{}]'.format(t))
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
199 current_wid.text = ''.join(close_styles)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
200 self.add_widget(current_wid)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
201 log.debug("new widget: {}".format(current_wid.text))
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
202 else:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
203 # non Label widgets, we just add them
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
204 self.add_widget(child)
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
205 self.splitted = True
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
206 log.debug("split OK")
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
207
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
208 # XHTML parsing methods
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
209
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
210 def _callParseMethod(self, e):
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
211 """Call the suitable method to parse the element
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
212
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
213 self.xhtml_[tag] will be called if it exists, else
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
214 self.xhtml_generic will be used
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
215 @param e(ET.Element): element to parse
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
216 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
217 try:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
218 method = getattr(self, f"xhtml_{e.tag}")
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
219 except AttributeError:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
220 log.warning(f"Unhandled XHTML tag: {e.tag}")
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
221 method = self.xhtml_generic
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
222 method(e)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
223
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
224 def _addStyle(self, tag, value=None, append_to_list=True):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
225 """add a markup style to label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
226
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
227 @param tag(unicode): markup tag
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
228 @param value(unicode): markup value if suitable
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
229 @param append_to_list(bool): if True style we be added to self.styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
230 self.styles is needed to keep track of styles to remove
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
231 should most probably be set to True
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
232 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
233 label = self._getLabel()
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
234 label.text += '[{tag}{value}]'.format(
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
235 tag = tag,
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
236 value = '={}'.format(value) if value else ''
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
237 )
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
238 if append_to_list:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
239 self.styles.append((tag, value))
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
240
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
241 def _removeStyle(self, tag, remove_from_list=True):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
242 """remove a markup style from the label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
243
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
244 @param tag(unicode): markup tag to remove
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
245 @param remove_from_list(bool): if True, remove from self.styles too
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
246 should most probably be set to True
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
247 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
248 label = self._getLabel()
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
249 label.text += '[/{tag}]'.format(
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
250 tag = tag
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
251 )
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
252 if remove_from_list:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
253 for rev_idx, style in enumerate(reversed(self.styles)):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
254 if style[0] == tag:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
255 tag_idx = len(self.styles) - 1 - rev_idx
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
256 del self.styles[tag_idx]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
257 break
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
258
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
259 def _getLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
260 """get current Label if it exists, or create a new one"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
261 if not isinstance(self.current_wid, Label):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
262 self._addLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
263 return self.current_wid
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
264
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
265 def _addLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
266 """add a new Label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
267
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
268 current styles will be closed and reopened if needed
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
269 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
270 self._closeLabel()
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
271 self.current_wid = self._createText()
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
272 for tag, value in self.styles:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
273 self._addStyle(tag, value, append_to_list=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
274 self.add_widget(self.current_wid)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
275
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
276 def _createText(self):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
277 label = SimpleXHTMLWidgetText(color=self.color, markup=True)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
278 self.bind(color=label.setter('color'))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
279 label.bind(texture_size=label.setter('size'))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
280 return label
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
281
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
282 def _closeLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
283 """close current style tags in current label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
284
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
285 needed when you change label to keep style between
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
286 different widgets
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
287 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
288 if isinstance(self.current_wid, Label):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
289 for tag, value in reversed(self.styles):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
290 self._removeStyle(tag, remove_from_list=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
291
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
292 def _parseCSS(self, e):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
293 """parse CSS found in "style" attribute of element
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
294
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
295 self._css_styles will be created and contained markup styles added by this method
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
296 @param e(ET.Element): element which may have a "style" attribute
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
297 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
298 styles_limit = len(self.styles)
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
299 styles = e.attrib['style'].split(';')
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
300 for style in styles:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
301 try:
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
302 prop, value = style.split(':')
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
303 except ValueError:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
304 log.warning(f"can't parse style: {style}")
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
305 continue
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
306 prop = prop.strip().replace('-', '_')
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
307 value = value.strip()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
308 try:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
309 method = getattr(self, f"css_{prop}")
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
310 except AttributeError:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
311 log.warning(f"Unhandled CSS: {prop}")
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
312 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
313 method(e, value)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
314 self._css_styles = self.styles[styles_limit:]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
315
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
316 def _closeCSS(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
317 """removed CSS styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
318
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
319 styles in self._css_styles will be removed
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
320 and the attribute will be deleted
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
321 """
284
ca4daced4638 misc: replaced "dummy" by "__"
Goffi <goffi@goffi.org>
parents: 282
diff changeset
322 for tag, __ in reversed(self._css_styles):
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
323 self._removeStyle(tag)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
324 del self._css_styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
325
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
326 def xhtml_generic(self, elem, style=True, markup=None):
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
327 """Generic method for adding HTML elements
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
328
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
329 this method handle content, style and children parsing
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
330 @param elem(ET.Element): element to add
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
331 @param style(bool): if True handle style attribute (CSS)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
332 @param markup(tuple[unicode, (unicode, None)], None): kivy markup to use
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
333 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
334 # we first add markup and CSS style
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
335 if markup is not None:
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
336 if isinstance(markup, str):
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
337 tag, value = markup, None
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
338 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
339 tag, value = markup
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
340 self._addStyle(tag, value)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
341 style_ = 'style' in elem.attrib and style
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
342 if style_:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
343 self._parseCSS(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
344
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
345 # then content
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
346 if elem.text:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
347 self._getLabel().text += escape_markup(elem.text)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
348
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
349 # we parse the children
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
350 for child in elem:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
351 self._callParseMethod(child)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
352
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
353 # closing CSS style and markup
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
354 if style_:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
355 self._closeCSS()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
356 if markup is not None:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
357 self._removeStyle(tag)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
358
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
359 # and the tail, which is regular text
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
360 if elem.tail:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
361 self._getLabel().text += escape_markup(elem.tail)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
362
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
363 # method handling XHTML elements
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
364
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
365 def xhtml_br(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
366 label = self._getLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
367 label.text+='\n'
453
2d277a3d9cec core (simple_xhtml): fixed xhtml_generic call in xhtml_br
Goffi <goffi@goffi.org>
parents: 422
diff changeset
368 self.xhtml_generic(elem, style=False)
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
369
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
370 def xhtml_em(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
371 self.xhtml_generic(elem, markup='i')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
372
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
373 def xhtml_img(self, elem):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
374 try:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
375 src = elem.attrib['src']
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
376 except KeyError:
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
377 log.warning("<img> element without src: {}".format(ET.tostring(elem)))
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
378 return
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
379 try:
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
380 target_height = int(elem.get('height', 0))
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
381 except ValueError:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
382 log.warning(f"Can't parse image height: {elem.get('height')}")
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
383 target_height = None
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
384 try:
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
385 target_width = int(elem.get('width', 0))
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
386 except ValueError:
325
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
387 log.warning(f"Can't parse image width: {elem.get('width')}")
5868a5575e01 chat: cleaning + some improvments:
Goffi <goffi@goffi.org>
parents: 312
diff changeset
388 target_width = None
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
389
422
efee0e0afb78 core (common): moved simple_xhtml's image code to a generic "SizedImage" widget
Goffi <goffi@goffi.org>
parents: 379
diff changeset
390 img = SizedImage(
efee0e0afb78 core (common): moved simple_xhtml's image code to a generic "SizedImage" widget
Goffi <goffi@goffi.org>
parents: 379
diff changeset
391 source=src, target_height=target_height, target_width=target_width)
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
392 self.current_wid = img
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
393 self.add_widget(img)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
394
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
395 def xhtml_p(self, elem):
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
396 if isinstance(self.current_wid, Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
397 self.current_wid.text+="\n\n"
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
398 self.xhtml_generic(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
399
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
400 def xhtml_span(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
401 self.xhtml_generic(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
402
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
403 def xhtml_strong(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
404 self.xhtml_generic(elem, markup='b')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
405
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
406 # methods handling CSS properties
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
407
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
408 def css_color(self, elem, value):
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
409 self._addStyle("color", css_color.parse(value))
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
410
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
411 def css_text_decoration(self, elem, value):
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
412 if value == 'underline':
299
86b1cd8121dd core (simple_xhtml): activated underline and line-through which are now available
Goffi <goffi@goffi.org>
parents: 288
diff changeset
413 self._addStyle('u')
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
414 elif value == 'line-through':
299
86b1cd8121dd core (simple_xhtml): activated underline and line-through which are now available
Goffi <goffi@goffi.org>
parents: 288
diff changeset
415 self._addStyle('s')
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
416 else:
312
772c170b47a9 Python3 port:
Goffi <goffi@goffi.org>
parents: 299
diff changeset
417 log.warning("unhandled text decoration: {}".format(value))