Skip to content

Commit ebeb9e9

Browse files
committed
Documentation formatting: Allow splitting list items into multiple lines by indenting continuing lines
Update issue 1174 Status: Done Owner: pekka.klarck Implemented, tested, and documented.
1 parent 2c8590b commit ebeb9e9

4 files changed

Lines changed: 68 additions & 22 deletions

File tree

doc/userguide/src/Appendices/DocumentationFormatting.txt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,12 +302,14 @@ example would be formatted like this in HTML:
302302
Lists
303303
~~~~~
304304

305-
Lists are created by starting a line with a hyphen and space ('- ').
306-
An empty line or line not starting with '- ' ends the list::
305+
Lists are created by starting a line with a hyphen and space ('- '). List items
306+
can be split into multiple lines by indenting continuing lines with one or more
307+
spaces. A line that does not start with '- ' and is not indented ends the list::
307308

308309
Example:
309310
- a list item
310-
- a second list item
311+
- second list item
312+
is continued
311313

312314
This is outside the list.
313315

@@ -319,14 +321,15 @@ The above documentation is formatted like this in HTML:
319321
<p>Example:</p>
320322
<ul>
321323
<li>a list item</li>
322-
<li>a second list item</li>
324+
<li>second list item is continued</li>
323325
</ul>
324326
<p>This is outside the list.</p>
325327
</div>
326328

327329
.. note:: Support for formatting lists was added in 2.7.2. Prior to that,
328330
the same syntax prevented :prog:`libdoc` from combining lines to
329-
paragraphs, though, so the end result was similar.
331+
paragraphs, so the end result was similar. Support for splitting
332+
list items into multiple lines was added in 2.7.4.
330333

331334
Preformatted text
332335
~~~~~~~~~~~~~~~~~

src/robot/htmldata/testdata/dir.suite/__init__.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ Documentation Documentation for the whole test suite. All this forms a single
1414
... regular line
1515
... | pre *formatted*
1616
... | \ \ content\t\with whitespaces
17+
... ---
18+
... - first list item
19+
... - second list item
20+
... \ is continued \
21+
... using *two* different approaches
1722
Metadata URL http://robotframework.org
1823
Metadata Image http://code.google.com/p/robotframework/logo?ext.png
1924
Metadata Formatting *Bold* and _italics_

src/robot/utils/htmlformatters.py

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,12 @@ def __init__(self):
119119

120120
def format(self, text):
121121
for line in text.splitlines():
122-
self._process_line(line.strip())
122+
self._process_line(line)
123123
self._end_current()
124124
return '\n'.join(self._results)
125125

126126
def _process_line(self, line):
127-
if not line:
127+
if not line.strip():
128128
self._end_current()
129129
elif self._current and self._current.handles(line):
130130
self._current.add(line)
@@ -145,12 +145,19 @@ def _find_formatter(self, line):
145145

146146

147147
class _BlockFormatter(object):
148+
_strip_lines = True
148149

149150
def __init__(self):
150151
self._lines = []
151152

153+
def handles(self, line):
154+
return self._handles(line.strip() if self._strip_lines else line)
155+
156+
def _handles(self, line):
157+
raise NotImplementedError
158+
152159
def add(self, line):
153-
self._lines.append(line)
160+
self._lines.append(line.strip() if self._strip_lines else line)
154161

155162
def end(self):
156163
result = self.format(self._lines)
@@ -164,7 +171,7 @@ def format(self, lines):
164171
class RulerFormatter(_BlockFormatter):
165172
_hr_matcher = re.compile('^-{3,}$').match
166173

167-
def handles(self, line):
174+
def _handles(self, line):
168175
return not self._lines and self._hr_matcher(line)
169176

170177
def format(self, lines):
@@ -178,22 +185,22 @@ def __init__(self, other_formatters):
178185
_BlockFormatter.__init__(self)
179186
self._other_formatters = other_formatters
180187

181-
def handles(self, line):
182-
if any(formatter.handles(line) for formatter in self._other_formatters):
183-
return False
184-
if line:
185-
return True
186-
return not self._lines
188+
def _handles(self, line):
189+
return not any(other.handles(line)
190+
for other in self._other_formatters)
187191

188192
def format(self, lines):
189193
return '<p>%s</p>' % self._format_line(' '.join(lines))
190194

191195

192196
class TableFormatter(_BlockFormatter):
193-
handles = re.compile('^\| (.* |)\|$').match
197+
_table_line = re.compile('^\| (.* |)\|$')
194198
_line_splitter = re.compile(' \|(?= )')
195199
_format_cell = LineFormatter().format
196200

201+
def _handles(self, line):
202+
return self._table_line.match(line) is not None
203+
197204
def format(self, lines):
198205
return self._format_table([self._split_to_cells(l) for l in lines])
199206

@@ -215,7 +222,7 @@ def _format_table(self, rows):
215222
class PreformattedFormatter(_BlockFormatter):
216223
_format_line = LineFormatter().format
217224

218-
def handles(self, line):
225+
def _handles(self, line):
219226
return line.startswith('| ') or line == '|'
220227

221228
def format(self, lines):
@@ -224,12 +231,26 @@ def format(self, lines):
224231

225232

226233
class ListFormatter(_BlockFormatter):
234+
_strip_lines = False
227235
_format_item = LineFormatter().format
228236

229-
def handles(self, line):
230-
return line.startswith('- ')
237+
def _handles(self, line):
238+
return line.strip().startswith('- ') or \
239+
line.startswith(' ') and self._lines
231240

232241
def format(self, lines):
233-
items = ['<li>%s</li>' % self._format_item(line[2:].strip())
234-
for line in lines]
242+
items = ['<li>%s</li>' % self._format_item(line)
243+
for line in self._combine_lines(lines)]
235244
return '\n'.join(['<ul>'] + items + ['</ul>'])
245+
246+
def _combine_lines(self, lines):
247+
current = []
248+
for line in lines:
249+
line = line.strip()
250+
if not line.startswith('- '):
251+
current.append(line)
252+
continue
253+
if current:
254+
yield ' '.join(current)
255+
current = [line[2:].strip()]
256+
yield ' '.join(current)

utest/utils/test_markuputils.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,21 @@ def test_list_with_formatted_content(self):
529529
'<ul>\n<li><b>bold</b> text</li>\n<li><i>italic</i></li>\n'
530530
'<li><a href="http://url">link</a></li>\n</ul>')
531531

532+
def test_indentation_can_be_used_to_continue_list_item(self):
533+
assert_format('''
534+
outside list
535+
- this item
536+
continues
537+
- 2nd item
538+
continues
539+
twice
540+
''', '''\
541+
<p>outside list</p>
542+
<ul>
543+
<li>this item continues</li>
544+
<li>2nd item continues twice</li>
545+
</ul>''')
546+
532547
def test_lists_with_other_content_around(self):
533548
assert_format('''
534549
before
@@ -538,6 +553,8 @@ def test_lists_with_other_content_around(self):
538553
539554
- c
540555
- d
556+
e
557+
f
541558
542559
---
543560
''', '''\
@@ -549,7 +566,7 @@ def test_lists_with_other_content_around(self):
549566
<p>between</p>
550567
<ul>
551568
<li>c</li>
552-
<li>d</li>
569+
<li>d e f</li>
553570
</ul>
554571
<hr>''')
555572

0 commit comments

Comments
 (0)