bb835ae91b28dcc1c579c0cf99ac2b7ccc7243f2
[librarian.git] / librarian / pyhtml.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 #
6 from lxml import etree
7 from librarian import OutputFile, RDFNS, DCNS
8 from xmlutils import Xmill, tag, tagged, ifoption
9  
10
11 class EduModule(Xmill):
12     def __init__(self, *args):
13         super(EduModule, self).__init__(*args)
14         self.activity_counter = 0
15
16     def handle_powiesc(self, element):
17         return u"""
18 <div class="module" id="book-text">
19  <span class="teacher-toggle">
20   <input type="checkbox" name="teacher-toggle" id="teacher-toggle"/>
21   <label for="teacher-toggle">Pokaż treść dla nauczyciela</label>
22  </span>
23
24 """, u"</div>"
25
26
27     handle_autor_utworu = tag("span", "author")
28     handle_nazwa_utworu = tag("h1", "title")
29     handle_dzielo_nadrzedne = tag("span", "collection")
30     handle_podtytul = tag("span", "subtitle")
31     handle_naglowek_akt = handle_naglowek_czesc = handle_srodtytul = tag("h2")
32     handle_naglowek_scena = handle_naglowek_rozdzial = tag('h3')
33     handle_naglowek_osoba = handle_naglowek_podrozdzial = tag('h4')
34     handle_akap = handle_akap_dialog = handle_akap_cd = tag('p', 'paragraph')
35     handle_strofa = tag('div', 'stanza')
36
37     def handle_aktywnosc(self, element):
38         self.activity_counter += 1
39         self.options = {
40             'activity': True, 
41             'activity_counter': self.activity_counter
42             }
43         submill = EduModule()
44
45         opis = submill.generate(element.xpath('opis')[0])
46
47         n = element.xpath('wskazowki')
48         if n: wskazowki = submill.generate(n[0])
49
50         else: wskazowki = ''
51         n = element.xpath('pomoce')
52
53         if n: pomoce = submill.generate(n[0])
54         else: pomoce = ''
55
56         forma = ''.join(element.xpath('forma/text()'))
57
58         czas = ''.join(element.xpath('czas/text()'))
59
60         counter = self.activity_counter
61
62         return u"""
63 <div class="activity">
64  <div class="text">%(counter)d. 
65   %(opis)s
66   %(wskazowki)s
67  </div>
68  <div class="info">
69   <p>Czas: %(czas)s min</p>
70   <p>Forma: %(forma)s</p>
71   %(pomoce)s
72  </div>
73  <div class="clearboth"></div>
74 </div>
75 """ % locals()
76
77     handle_opis = ifoption(activity=False)(tag('div', 'description'))
78     handle_wskazowki = ifoption(activity=False)(tag('div', ('hints', 'teacher')))
79     
80     @ifoption(activity=False)
81     @tagged('div', 'materials')
82     def handle_pomoce(self, _):
83         return "Pomoce: ", ""
84     
85     def handle_czas(self, *_):
86         return
87
88     def handle_forma(self, *_):
89         return
90             
91     def handle_cwiczenie(self, element):
92         excercise_handlers = {
93             'wybor': Wybor,
94             'uporzadkuj': Uporzadkuj,
95             'luki': Luki,
96             'zastap': Zastap,
97             'przyporzadkuj': Przyporzadkuj
98             }
99         
100         typ = element.attrib['typ']
101         handler = excercise_handlers[typ](self.options)
102         return handler.generate(element)
103
104     # Lists
105     def handle_lista(self, element, attrs={}):
106         ltype = element.attrib.get('typ', 'punkt')
107         if ltype == 'slowniczek':
108             self.options = {'slowniczek': True}
109             return '<div class="slowniczek">', '</div>'
110 ### robie teraz punkty wyboru
111         listtag = {'num': 'ol', 
112                'punkt': 'ul', 
113                'alfa': 'ul', 
114                'czytelnia': 'ul'}[ltype]
115
116         classes = attrs.get('class', '')
117         if classes: del attrs['class']
118             
119         attrs_s = ' '.join(['%s="%s"' % kv for kv in attrs.items()])
120         if attrs_s: attrs_s = ' ' + attrs_s
121             
122         return '<%s class="lista %s %s"%s>' % (listtag, ltype, classes, attrs_s), '</%s>' % listtag
123
124     def handle_punkt(self, element):
125         if self.options['slowniczek']:
126             return '<dl>', '</dl>'
127         else:
128             return '<li>', '</li>'
129
130     def handle_rdf__RDF(self, _):
131         # ustal w opcjach  rzeczy :D
132         return 
133
134
135 class Excercise(EduModule):
136     def __init__(self, *args, **kw):
137         self.question_counter = 0
138         super(Excercise, self).__init__(*args, **kw)
139
140     def handle_rozw_kom(self, element):
141         return None
142
143     def handle_cwiczenie(self, element):
144         self.options = {'excercise': element.attrib['typ']}
145         self.question_counter = 0
146         self.piece_counter = 0
147
148         pre = u"""
149 <div class="excercise %(typ)s" data-type="%(typ)s">
150 <form action="#" method="POST">
151 """ % element.attrib
152         post = u"""
153 <div class="buttons">
154 <span class="message"></span>
155 <input type="button" class="check" value="sprawdź"/>
156 <input type="button" class="solutions" value="pokaż rozwiązanie"/>
157 </div>
158 </form>
159 </div>
160 """
161         # Add a single <pytanie> tag if it's not there
162         if not element.xpath(".//pytanie"):
163             qpre, qpost = self.handle_pytanie(element)
164             pre = pre + qpre
165             post = qpost + post
166         return pre, post
167  
168     def handle_pytanie(self, element):
169         """This will handle <cwiczenie> element, when there is no <pytanie>
170         """
171         self.question_counter += 1
172         self.piece_counter = 0
173         solution = element.attrib.get('rozw', None)
174         if solution: solution_s = ' data-solution="%s"' % solution
175         else: solution_s = ''
176
177         return '<div class="question" data-no="%d" %s>' %\
178             (self.question_counter, solution_s), \
179     "</div>"
180
181
182 class Wybor(Excercise):
183     def handle_punkt(self, element):
184         if self.options['excercise'] and element.attrib.get('nazwa', None):
185             qc = self.question_counter
186             self.piece_counter += 1
187             no = self.piece_counter
188             eid = "q%(qc)d_%(no)d" % locals()
189             return u"""
190 <li class="question-piece" data-qc="%(qc)d" data-no="%(no)d">
191 <input type="checkbox" name="" id="%(eid)s" />
192 <label for="%(eid)s">
193 """ % locals(), u"</label></li>"
194
195         else:
196             return super(Wybor, self).handle_punkt(element)
197
198
199 class Uporzadkuj(Excercise):
200     def handle_pytanie(self, element):
201         """
202 Overrides the returned content default handle_pytanie
203         """
204         # we ignore the result, returning our own
205         super(Uporzadkuj, self).handle_pytanie(element)
206         order_items = element.xpath(".//punkt/@rozw")
207
208         return u"""<div class="question" data-original="%s" data-no="%s">""" % \
209             (','.join(order_items), self.question_counter), \
210             u"""</div>"""
211
212     def handle_punkt(self, element):
213         return """<li class="question-piece" data-pos="%(rozw)s"/>""" \
214             % element.attrib,\
215             "</li>"
216
217
218 class Luki(Excercise):
219     def handle_luka(self, element):
220         return '<input type="text" class="luka question-piece" data-solution="%s"></input>' % element.text
221
222
223 class Zastap(Excercise):
224     def handle_zastap(self, element):
225         return '<span class="zastap question-piece" data-solution="%(rozw)s">' % element.attrib, '</span>'
226
227
228 class Przyporzadkuj(Excercise):
229     def handle_lista(self, lista):
230         print "in lista %s %s" % (lista.attrib, self.options)
231         if 'nazwa' in lista.attrib:
232             attrs = {
233                 'data-name': lista.attrib['nazwa'],
234                 'class': 'predicate'
235                 }
236             self.options = {'predicate': True}
237         elif 'cel' in lista.attrib:
238             attrs = {
239                 'data-target': lista.attrib['cel'],
240                 'class': 'subject'
241                 }
242             self.options = {'subject': True}
243         else:
244             attrs = {}
245         pre, post = super(Przyporzadkuj, self).handle_lista(lista, attrs)
246         return pre, post + '<br class="clr"/>'
247
248     def handle_punkt(self, element):
249         print "in punkt %s %s" % (element.attrib, self.options)
250
251         if self.options['subject']:
252             return '<li data-solution="%(rozw)s" class="question-piece draggable">' % element.attrib, '</li>'
253         elif self.options['predicate']:
254             return '<li data-predicate="%(nazwa)s">' % element.attrib, '<ul class="subjects droppable"></ul></li>'
255         else:
256             return super(Przyporzadkuj, self).handle_punkt(element)
257
258
259 def transform(wldoc, stylesheet='edumed', options=None, flags=None):
260     """Transforms the WL document to XHTML.
261
262     If output_filename is None, returns an XML,
263     otherwise returns True if file has been written,False if it hasn't.
264     File won't be written if it has no content.
265     """
266     edumod = EduModule(options)
267 #    from pdb import set_trace; set_trace()
268     html = edumod.generate(wldoc.edoc.getroot())
269
270     return OutputFile.from_string(html.encode('utf-8'))