diff options
| -rwxr-xr-x | filters/html-converters/md2html | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/filters/html-converters/md2html b/filters/html-converters/md2html index 79d4a17..d2906ec 100755 --- a/filters/html-converters/md2html +++ b/filters/html-converters/md2html @@ -31,6 +31,13 @@ _MD_ANYITEM = re.compile(r'^ {0,3}(?:[-*+]|\d{1,9}[.)])[ \t]') class _ListInterruptPreprocessor(Preprocessor): def run(self, lines): out, in_fence, fence = [], False, None + # Track whether we're already inside a list. A bullet that merely + # continues an existing list must NOT get a blank line inserted before + # it: that would turn a tight list into a loose one (every item wrapped + # in <p>), which is exactly what happens when a preceding item wraps onto + # an indented continuation line and we mistake the next bullet for a + # paragraph->list transition. We only want to interrupt a real paragraph. + in_list = False for line in lines: m = _MD_FENCE.match(line) if m: @@ -41,12 +48,28 @@ class _ListInterruptPreprocessor(Preprocessor): in_fence, fence = False, None out.append(line) continue - if not in_fence and out: + if in_fence: + out.append(line) + continue + if not line.strip(): + # a blank line doesn't end a list (loose lists / lazy + # continuation), so leave in_list untouched + out.append(line) + continue + is_item = bool(_MD_ANYITEM.match(line)) + indented = line[:1] in (' ', '\t') + # a non-indented, non-item line after a list closes that list + if in_list and not is_item and not indented: + in_list = False + if out: prev = out[-1] - if (prev.strip() and not _MD_ANYITEM.match(prev) + if (prev.strip() and not in_list + and not _MD_ANYITEM.match(prev) and not prev.startswith((' ', '\t')) and (_MD_BULLET.match(line) or _MD_ORDERED1.match(line))): out.append('') + if is_item: + in_list = True out.append(line) return out |
