add <pytanie> if missing
[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_cwiczenie(self, element):
141         self.options = {'excercise': element.attrib['typ']}
142         self.question_counter = 0
143         self.piece_counter = 0
144
145         pre = u"""
146 <div class="excercise %(typ)s" data-type="%(typ)s">
147 <form action="#" method="POST">
148 """ % element.attrib
149         post = u"""
150 <div class="buttons">
151 <span class="message"></span>
152 <input type="button" class="check" value="sprawdź"/>
153 <input type="button" class="solutions" value="pokaż rozwiązanie"/>
154 </div>
155 </form>
156 </div>
157 """
158         # Add a single <pytanie> tag if it's not there
159         if not element.xpath(".//pytanie"):
160             qpre, qpost = self.handle_pytanie(element)
161             pre = pre + qpre
162             post = qpost + post
163         return pre, post
164  
165     def handle_pytanie(self, element):
166         """This will handle <cwiczenie> element, when there is no <pytanie>
167         """
168         self.question_counter += 1
169         self.piece_counter = 0
170         solution = element.attrib.get('rozw', None)
171         if solution: solution_s = ' data-solution="%s"' % solution
172         else: solution_s = ''
173
174         return '<div class="question" data-no="%d" %s>' %\
175             (self.question_counter, solution_s), \
176     "</div>"    
177
178
179 class Wybor(Excercise):
180     def handle_punkt(self, element):
181         if self.options['excercise'] and element.attrib.get('nazwa', None):
182             qc = self.question_counter
183             self.piece_counter += 1
184             no = self.piece_counter
185             eid = "q%(qc)d_%(no)d" % locals()
186             return u"""
187 <li class="question-piece" data-qc="%(qc)d" data-no="%(no)d">
188 <input type="checkbox" name="" id="%(eid)s" />
189 <label for="%(eid)s">
190 """ % locals(), u"</label></li>"
191
192         else:
193             return super(Wybor, self).handle_punkt(element)
194
195
196 class Uporzadkuj(Excercise):
197     def handle_cwiczenie(self, element):
198         pre, post = super(Uporzadkuj, self).handle_cwiczenie(element)
199         order_items = element.xpath(".//punkt/@rozw")
200         if order_items == []: pdb.set_trace()
201
202         return pre + u"""<div class="question" data-original="%s">""" % \
203             ','.join(order_items), \
204             u"""</div>""" + post
205     
206     def handle_punkt(self, element):
207         return """<li class="question-piece" data-pos="%(rozw)s"/>""" \
208             % element.attrib,\
209             "</li>"
210
211
212 class Luki(Excercise):
213     def handle_luka(self, element):
214         return '<input type="text" class="luka question-piece" data-solution="%s"></input>' % element.text
215
216
217
218 class Zastap(Excercise):
219     def handle_zastap(self, element):
220         return '<span class="zastap question-piece" data-solution="%(rozw)s">' % element.attrib, '</span>'
221
222
223 class Przyporzadkuj(Excercise):
224     def handle_lista(self, lista):
225         print "in lista %s %s" % (lista.attrib, self.options)
226         if 'nazwa' in lista.attrib:
227             attrs = {
228                 'data-name': lista.attrib['nazwa'],
229                 'class': 'predicate'
230                 }
231             self.options = {'predicate': True}
232         elif 'cel' in lista.attrib:
233             attrs = {
234                 'data-target': lista.attrib['cel'],
235                 'class': 'subject'
236                 }
237             self.options = {'subject': True}
238         else:
239             attrs = {}
240         return super(Przyporzadkuj, self).handle_lista(lista, attrs)  
241
242
243     def handle_punkt(self, element):
244         print "in punkt %s %s" % (element.attrib, self.options)
245
246         if self.options['subject']:
247             return '<li data-solution="%(rozw)s" class="question-piece draggable multiple">' % element.attrib, '</li>'
248         elif self.options['predicate']:
249             return '<li data-predicate="%(nazwa)s">' % element.attrib, '<ul class="subjects droppable"><li>Placeholder</li></ul></li>'
250         else:
251             return super(Przyporzadkuj, self).handle_punkt(element)
252
253
254
255
256 def transform(wldoc, stylesheet='edumed', options=None, flags=None):
257     """Transforms the WL document to XHTML.
258
259     If output_filename is None, returns an XML,
260     otherwise returns True if file has been written,False if it hasn't.
261     File won't be written if it has no content.
262     """
263     
264     edumod = EduModule(options)
265 #    from pdb import set_trace; set_trace()
266     html = edumod.generate(wldoc.edoc.getroot())
267
268     return OutputFile.from_string(html.encode('utf-8'))