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

419 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 # markdown -> HTML
226
227 h = cmark.md2html(md)
228 # Markdown adds a newline
229 if h.endswith('\n'):
230 print('ENDS WITH NEWLINE %r' % h[-10:])
231
232 if 1:
233 print('---')
234 print('ORIGINAL')
235 print(h)
236 print('')
237
238 h = ul_table.RemoveComments(h)
239 h = ul_table.ReplaceTables(h)
240
241 if 1:
242 print('---')
243 print('REPLACED')
244 print(h)
245 print('')
246
247 return h
248
249
250class UlTableTest(unittest.TestCase):
251
252 def testOne(self):
253 h = MarkdownToTable('hi\n' + TEST1 + '\n\n bye \n')
254
255 def testNoHeader(self):
256 # HTML looks like:
257 #
258 # <table>
259 # <ul> # problem: we need to lookahead SPACE <li> (tr or thead)
260 # <li>tr
261 # <ul>
262 # <li>one</li>
263 # </ul>
264 # </li>
265 # </ul>
266 # </table>
267
268 h = MarkdownToTable('''\
269<table>
270
271- tr
272 - one
273 - two
274
275</table>
276''')
277 print(h)
278
279 def testSimple(self):
280 h = MarkdownToTable("""\
281<table>
282
283- thead
284 - *name*
285 - *age*
286- tr
287 - alice
288 - 30
289- tr
290 - bob
291 - 40
292
293<table>
294""")
295 self.assertMultiLineEqual(
296 """\
297<table>
298<thead>
299<tr>
300 <th><em>name</em></th>
301 <th><em>age</em></th>
302</tr>
303</thead>
304<tr>
305 <td>alice</td>
306 <td>30</td>
307</tr>
308<tr>
309 <td>bob</td>
310 <td>40</td>
311</tr>
312<table>
313""", h)
314
315 def testMultipleTables(self):
316 # They can be right next to each other
317 html_one = MarkdownToTable(TEST1)
318
319 self.assert_(not TEST1.endswith('\n'))
320 # CommonMark added a newline
321 self.assert_(html_one.endswith('\n'))
322 html_one = html_one[:-1]
323
324 html_two = MarkdownToTable(TEST1 + TEST1)
325
326 # The output is just concatenated
327 self.assertMultiLineEqual(html_one + html_one + '\n', html_two)
328
329 def testMultipleTablesWithSpace(self):
330 h = MarkdownToTable(TEST1 + '\n\n hi \n' + TEST1)
331
332 def testTdAttrs(self):
333 h = MarkdownToTable(TD_ATTRS)
334 self.assertMultiLineEqual(TD_ATTRS_HTML, h)
335
336 def testTdAttrsTrailing(self):
337 self.maxDiff = 2000
338 h = MarkdownToTable(TRAILING_ATTRS)
339 if 1:
340 print('expect', repr(TRAILING_ATTRS_HTML))
341 print('actual', repr(h))
342 self.assertMultiLineEqual(TRAILING_ATTRS_HTML, h)
343
344 def testColspan(self):
345 h = MarkdownToTable(COLSPAN)
346 self.assertMultiLineEqual(COLSPAN_HTML, h)
347
348 def testTrAttrs(self):
349 h = MarkdownToTable(TR_ATTRS)
350 self.assertMultiLineEqual(TR_ATTRS_HTML, h)
351
352 def testMixedTr(self):
353 # Not worth it
354 return
355 h = MarkdownToTable(MIXED_TR)
356 #self.assertMultiLineEqual(MIXED_TR, h)
357
358 def testSyntaxErrors(self):
359 # Once we get <table><ul>, then we TAKE OVER, and start being STRICT
360
361 try:
362 h = MarkdownToTable("""
363<table>
364
365- should be thead
366 - one
367 - two
368""")
369 except html.ParseError as e:
370 print(e)
371 else:
372 self.fail('Expected parse error')
373
374 try:
375 h = MarkdownToTable("""
376<table>
377
378- thead
379 - one
380 - two
381- tr <bad-attrs />
382 - 1
383 - 2
384""")
385 except html.ParseError as e:
386 print(e)
387 else:
388 self.fail('Expected parse error')
389
390 def testColumnCheck(self):
391 # Disabled because of colspan
392 return
393
394 try:
395 h = MarkdownToTable("""
396<table>
397
398- thead
399 - one
400 - two
401- tr
402 - 1
403 - 2
404- tr
405 - wrong number of cells
406- tr
407 - 3
408 - 4
409
410</table>
411""")
412 except html.ParseError as e:
413 print(e)
414 else:
415 self.fail('Expected parse error')
416
417
418if __name__ == '__main__':
419 unittest.main()