3690724e33acf6127ee02f1c777c7f6881d68d72
[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             aname = element.attrib.get('nazwa', None)
190             return u"""
191 <li class="question-piece" data-qc="%(qc)d" data-no="%(no)d" data-name="%(aname)s">
192 <input type="checkbox" name="" id="%(eid)s" />
193 <label for="%(eid)s">
194 """ % locals(), u"</label></li>"
195
196         else:
197             return super(Wybor, self).handle_punkt(element)
198
199
200 class Uporzadkuj(Excercise):
201     def handle_pytanie(self, element):
202         """
203 Overrides the returned content default handle_pytanie
204         """
205         # we ignore the result, returning our own
206         super(Uporzadkuj, self).handle_pytanie(element)
207         order_items = element.xpath(".//punkt/@rozw")
208
209         return u"""<div class="question" data-original="%s" data-no="%s">""" % \
210             (','.join(order_items), self.question_counter), \
211             u"""</div>"""
212
213     def handle_punkt(self, element):
214         return """<li class="question-piece" data-pos="%(rozw)s"/>""" \
215             % element.attrib,\
216             "</li>"
217
218
219 class Luki(Excercise):
220     def handle_luka(self, element):
221         return '<input type="text" class="luka question-piece" data-solution="%s"></input>' % element.text
222
223
224 class Zastap(Excercise):
225     def handle_zastap(self, element):
226         return '<span class="zastap question-piece" data-solution="%(rozw)s">' % element.attrib, '</span>'
227
228
229 class Przyporzadkuj(Excercise):
230     def handle_lista(self, lista):
231         print "in lista %s %s" % (lista.attrib, self.options)
232         if 'nazwa' in lista.attrib:
233             attrs = {
234                 'data-name': lista.attrib['nazwa'],
235                 'class': 'predicate'
236                 }
237             self.options = {'predicate': True}
238         elif 'cel' in lista.attrib:
239             attrs = {
240                 'data-target': lista.attrib['cel'],
241                 'class': 'subject'
242                 }
243             self.options = {'subject': True}
244         else:
245             attrs = {}
246         pre, post = super(Przyporzadkuj, self).handle_lista(lista, attrs)
247         return pre, post + '<br class="clr"/>'
248
249     def handle_punkt(self, element):
250         print "in punkt %s %s" % (element.attrib, self.options)
251
252         if self.options['subject']:
253             return '<li data-solution="%(rozw)s" class="question-piece draggable">' % element.attrib, '</li>'
254         elif self.options['predicate']:
255             return '<li data-predicate="%(nazwa)s">' % element.attrib, '<ul class="subjects droppable"></ul></li>'
256         else:
257             return super(Przyporzadkuj, self).handle_punkt(element)
258
259
260 def transform(wldoc, stylesheet='edumed', options=None, flags=None):
261     """Transforms the WL document to XHTML.
262
263     If output_filename is None, returns an XML,
264     otherwise returns True if file has been written,False if it hasn't.
265     File won't be written if it has no content.
266     """
267     edumod = EduModule(options)
268 #    from pdb import set_trace; set_trace()
269     html = edumod.generate(wldoc.edoc.getroot())
270
271     return OutputFile.from_string(html.encode('utf-8'))