OILS / doctools / ul_table_test.py View on Github | oils.pub

432 lines, 98 significant
1#!/usr/bin/env python2
2from __future__ import print_function
3
4import cmark # Oils dev dependency
5
6import unittest
7
8from lazylex import html
9from doctools import ul_table
10
11# <ulcol> is a special annotation
12TEST1 = """\
13<table id="foo">
14
15- thead
16 - <cell-attrs class="foo" /> name
17 - <cell-attrs class="bar" /> [age](https://example.com/)
18- tr
19 - alice *italic*
20 - 30
21- tr
22 - bob
23 - 42
24
25</table>""" # no extra
26
27TD_ATTRS = """\
28<table>
29
30- thead
31 - <cell-attrs class=unquoted /> name
32 - <cell-attrs class=quoted /> age
33 - role
34- tr <!-- comment --> <!-- comment 2 -->
35 - <cell-attrs class="cool" /> alice
36 - 30
37 - parent
38- tr
39 - bob
40 - 42
41 - <cell-attrs class=child /> child
42
43</table>
44"""
45
46TD_ATTRS_HTML = """\
47<table>
48<thead>
49<tr>
50 <th> name</th>
51 <th> age</th>
52 <th>role</th>
53</tr>
54</thead>
55<tr>
56 <td class="unquoted cool"> alice</td>
57 <td class="quoted">30</td>
58 <td>parent</td>
59</tr>
60<tr>
61 <td class="unquoted">bob</td>
62 <td class="quoted">42</td>
63 <td class="child"> child</td>
64</tr>
65</table>
66"""
67
68TRAILING_ATTRS = """\
69<table>
70
71- thead
72 - OSH
73 - YSH
74- tr
75 - ```
76 echo osh
77 ```
78 <cell-attrs class=osh-code />
79 - ```
80 echo ysh
81 ```
82 <cell-attrs class=ysh-code />
83
84</table>
85"""
86
87TRAILING_ATTRS_HTML = """\
88<table>
89<thead>
90<tr>
91 <th>OSH</th>
92 <th>YSH</th>
93</tr>
94</thead>
95<tr>
96 <td class="osh-code">
97<pre><code>echo osh
98</code></pre>
99
100</td>
101 <td class="ysh-code">
102<pre><code>echo ysh
103</code></pre>
104
105</td>
106</tr>
107</table>
108"""
109
110TR_ATTRS = """\
111<table>
112
113- thead
114 - <cell-attrs class=unquoted /> name
115 - <cell-attrs class=quoted /> age
116 - role
117- tr <row-attrs class=totals />
118 - alice
119 - 30
120 - parent
121- tr
122 - bob
123 - 42
124 - <cell-attrs class=child /> child
125
126</table>
127"""
128
129TR_ATTRS_HTML = """\
130<table>
131<thead>
132<tr>
133 <th> name</th>
134 <th> age</th>
135 <th>role</th>
136</tr>
137</thead>
138<tr class="totals">
139 <td class="unquoted">alice</td>
140 <td class="quoted">30</td>
141 <td>parent</td>
142</tr>
143<tr>
144 <td class="unquoted">bob</td>
145 <td class="quoted">42</td>
146 <td class="child"> child</td>
147</tr>
148</table>
149"""
150
151# Note CSS Grid can express colspan
152# https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column
153
154COLSPAN = """\
155<!-- begin REPLACE -->
156
157<table>
158
159- thead
160 - <cell-attrs class=foo /> name
161 - age
162- tr
163 - alice
164 - 30
165- tr
166 - <cell-attrs colspan=2 /> ... more ...
167- tr
168 - bob
169 - 42
170
171</table>
172
173<!-- end REPLACE -->
174"""
175
176COLSPAN_HTML = """\
177<!-- begin REPLACE -->
178<table>
179<thead>
180<tr>
181 <th> name</th>
182 <th>age</th>
183</tr>
184</thead>
185<tr>
186 <td class="foo">alice</td>
187 <td>30</td>
188</tr>
189<tr>
190 <td class="foo" colspan="2"> ... more ...</td>
191</tr>
192<tr>
193 <td class="foo">bob</td>
194 <td>42</td>
195</tr>
196</table>
197<!-- end REPLACE -->
198"""
199
200# UNUSED - not worth it now
201MIXED_TR = """\
202<table>
203
204- thead
205 - name
206 - age
207- tr
208 - 30
209 - parent
210
211<tr>
212 <td colspan=2> - </td>
213</tr>
214
215- tr
216 - bob
217 - 42
218 - <cell-attrs class=child /> child
219
220</table>
221"""
222
223
224def MarkdownToTable(md):
225 # type: (str) -> str
226 # markdown -> HTML
227
228 h = cmark.md2html(md)
229 # Markdown adds a newline
230 if h.endswith('\n'):
231 print('ENDS WITH NEWLINE %r' % h[-10:])
232
233 if 1:
234 print('---')
235 print('ORIGINAL')
236 print(h)
237 print('')
238
239 h = ul_table.RemoveComments(h)
240 h = ul_table.ReplaceTables(h)
241
242 if 1:
243 print('---')
244 print('REPLACED')
245 print(h)
246 print('')
247
248 return h
249
250
251class UlTableTest(unittest.TestCase):
252
253 def testOne(self):
254 # type: () -> None
255 h = MarkdownToTable('hi\n' + TEST1 + '\n\n bye \n')
256
257 def testNoHeader(self):
258 # type: () -> None
259 # HTML looks like:
260 #
261 # <table>
262 # <ul> # problem: we need to lookahead SPACE <li> (tr or thead)
263 # <li>tr
264 # <ul>
265 # <li>one</li>
266 # </ul>
267 # </li>
268 # </ul>
269 # </table>
270
271 h = MarkdownToTable('''\
272<table>
273
274- tr
275 - one
276 - two
277
278</table>
279''')
280 print(h)
281
282 def testSimple(self):
283 # type: () -> None
284 h = MarkdownToTable("""\
285<table>
286
287- thead
288 - *name*
289 - *age*
290- tr
291 - alice
292 - 30
293- tr
294 - bob
295 - 40
296
297<table>
298""")
299 self.assertMultiLineEqual(
300 """\
301<table>
302<thead>
303<tr>
304 <th><em>name</em></th>
305 <th><em>age</em></th>
306</tr>
307</thead>
308<tr>
309 <td>alice</td>
310 <td>30</td>
311</tr>
312<tr>
313 <td>bob</td>
314 <td>40</td>
315</tr>
316<table>
317""", h)
318
319 def testMultipleTables(self):
320 # type: () -> None
321 # They can be right next to each other
322 html_one = MarkdownToTable(TEST1)
323
324 self.assert_(not TEST1.endswith('\n'))
325 # CommonMark added a newline
326 self.assert_(html_one.endswith('\n'))
327 html_one = html_one[:-1]
328
329 html_two = MarkdownToTable(TEST1 + TEST1)
330
331 # The output is just concatenated
332 self.assertMultiLineEqual(html_one + html_one + '\n', html_two)
333
334 def testMultipleTablesWithSpace(self):
335 # type: () -> None
336 h = MarkdownToTable(TEST1 + '\n\n hi \n' + TEST1)
337
338 def testTdAttrs(self):
339 # type: () -> None
340 h = MarkdownToTable(TD_ATTRS)
341 self.assertMultiLineEqual(TD_ATTRS_HTML, h)
342
343 def testTdAttrsTrailing(self):
344 # type: () -> None
345 self.maxDiff = 2000
346 h = MarkdownToTable(TRAILING_ATTRS)
347 if 1:
348 print('expect', repr(TRAILING_ATTRS_HTML))
349 print('actual', repr(h))
350 self.assertMultiLineEqual(TRAILING_ATTRS_HTML, h)
351
352 def testColspan(self):
353 # type: () -> None
354 h = MarkdownToTable(COLSPAN)
355 self.assertMultiLineEqual(COLSPAN_HTML, h)
356
357 def testTrAttrs(self):
358 # type: () -> None
359 h = MarkdownToTable(TR_ATTRS)
360 self.assertMultiLineEqual(TR_ATTRS_HTML, h)
361
362 def testMixedTr(self):
363 # type: () -> None
364 # Not worth it
365 return
366 h = MarkdownToTable(MIXED_TR)
367 #self.assertMultiLineEqual(MIXED_TR, h)
368
369 def testSyntaxErrors(self):
370 # type: () -> None
371 # Once we get <table><ul>, then we TAKE OVER, and start being STRICT
372
373 try:
374 h = MarkdownToTable("""
375<table>
376
377- should be thead
378 - one
379 - two
380""")
381 except html.ParseError as e:
382 print(e)
383 else:
384 self.fail('Expected parse error')
385
386 try:
387 h = MarkdownToTable("""
388<table>
389
390- thead
391 - one
392 - two
393- tr <bad-attrs />
394 - 1
395 - 2
396""")
397 except html.ParseError as e:
398 print(e)
399 else:
400 self.fail('Expected parse error')
401
402 def testColumnCheck(self):
403 # type: () -> None
404 # Disabled because of colspan
405 return
406
407 try:
408 h = MarkdownToTable("""
409<table>
410
411- thead
412 - one
413 - two
414- tr
415 - 1
416 - 2
417- tr
418 - wrong number of cells
419- tr
420 - 3
421 - 4
422
423</table>
424""")
425 except html.ParseError as e:
426 print(e)
427 else:
428 self.fail('Expected parse error')
429
430
431if __name__ == '__main__':
432 unittest.main()