From 609faad76b80ff10da0e471183ad0cede3221571 Mon Sep 17 00:00:00 2001 From: facelessuser Date: Mon, 17 Nov 2014 18:36:43 -0700 Subject: Issue #365 Bold/Italic nesting fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic for the current regex for strong/em and em/strong was sound, but the way it was implemented caused some unintended side effects. Whether it is a quirk with regex in general or just with Python’s re engine, I am not sure. Put basically `(\*|_){3}` causes issues with nested bold/italic. So, allowing the group to be defined, and then using the group number to specify the remaining sequential chars is a better way that works more reliably `(\*|_)\2{2}. Test from issue #365 was also added to check for this case in the future. --- markdown/inlinepatterns.py | 4 ++-- tests/misc/nested-patterns.html | 4 +++- tests/misc/nested-patterns.txt | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/markdown/inlinepatterns.py b/markdown/inlinepatterns.py index b63bc8c..c9d82fd 100644 --- a/markdown/inlinepatterns.py +++ b/markdown/inlinepatterns.py @@ -101,8 +101,8 @@ BACKTICK_RE = r'(?link link link

-

I am italic and bold I am just bold

\ No newline at end of file +

I am italic and bold I am just bold

+

Example bold italic on the same line bold italic.

+

Example bold italic on the same line bold italic.

\ No newline at end of file diff --git a/tests/misc/nested-patterns.txt b/tests/misc/nested-patterns.txt index e347ccf..9032cf1 100644 --- a/tests/misc/nested-patterns.txt +++ b/tests/misc/nested-patterns.txt @@ -7,3 +7,7 @@ __[*link*](http://example.com)__ [***link***](http://example.com) ***I am ___italic_ and__ bold* I am `just` bold** + +Example __*bold italic*__ on the same line __*bold italic*__. + +Example **_bold italic_** on the same line **_bold italic_**. -- cgit v1.2.3 From 69fd8b4871f3c027b78072af88bb8a62202bc7e7 Mon Sep 17 00:00:00 2001 From: facelessuser Date: Mon, 17 Nov 2014 18:44:08 -0700 Subject: Issue #366 Recursion error in toc ext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reworks the toc ordering to be done in a single pass with no recursion. Very long documents with lots of headers can actually exceed Python’s max recursion limit. By handling the toc ordering with no recursion, large documents can no longer cause toc to fail with recursion erros. --- markdown/extensions/toc.py | 95 +++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/markdown/extensions/toc.py b/markdown/extensions/toc.py index d21ea96..f7fb675 100644 --- a/markdown/extensions/toc.py +++ b/markdown/extensions/toc.py @@ -27,60 +27,59 @@ def order_toc_list(toc_list): [{'level': 1}, {'level': 2}] => [{'level': 1, 'children': [{'level': 2, 'children': []}]}] - + A wrong list is also converted: [{'level': 2}, {'level': 1}] => [{'level': 2, 'children': []}, {'level': 1, 'children': []}] """ - - def build_correct(remaining_list, prev_elements=[{'level': 1000}]): - - if not remaining_list: - return [], [] - - current = remaining_list.pop(0) - if not 'children' in current.keys(): - current['children'] = [] - - if not prev_elements: - # This happens for instance with [8, 1, 1], ie. when some - # header level is outside a scope. We treat it as a - # top-level - next_elements, children = build_correct(remaining_list, [current]) - current['children'].append(children) - return [current] + next_elements, [] - - prev_element = prev_elements.pop() - children = [] - next_elements = [] - # Is current part of the child list or next list? - if current['level'] > prev_element['level']: - #print "%d is a child of %d" % (current['level'], prev_element['level']) - prev_elements.append(prev_element) - prev_elements.append(current) - prev_element['children'].append(current) - next_elements2, children2 = build_correct(remaining_list, prev_elements) - children += children2 - next_elements += next_elements2 - else: - #print "%d is ancestor of %d" % (current['level'], prev_element['level']) - if not prev_elements: - #print "No previous elements, so appending to the next set" - next_elements.append(current) - prev_elements = [current] - next_elements2, children2 = build_correct(remaining_list, prev_elements) - current['children'].extend(children2) + + ordered_list = [] + if len(toc_list): + # Initialize everything by processing the first entry + last = toc_list.pop(0) + last['children'] = [] + levels = [last['level']] + ordered_list.append(last) + parents = [] + + # Walk the rest nesting the entries properly + while toc_list: + t = toc_list.pop(0) + current_level = t['level'] + t['children'] = [] + + # Reduce depth if current level < last item's level + if current_level < levels[-1]: + # Pop last level since we know we are less than it + levels.pop() + + # Pop parents and levels we are less than or equal to + to_pop = 0 + for p in reversed(parents): + if current_level <= p['level']: + to_pop += 1 + else: + break + if to_pop: + levels = levels[:-to_pop] + parents = parents[:-to_pop] + + # Note current level as last + levels.append(current_level) + + # Level is the same, so append to the current parent (if available) + if current_level == levels[-1]: + (parents[-1]['children'] if parents else ordered_list).append(t) + + # Current level is > last item's level, + # So make last item a parent and append current as child else: - #print "Previous elements, comparing to those first" - remaining_list.insert(0, current) - next_elements2, children2 = build_correct(remaining_list, prev_elements) - children.extend(children2) - next_elements += next_elements2 - - return next_elements, children - - ordered_list, __ = build_correct(toc_list) + last['children'].append(t) + parents.append(last) + levels.append(current_level) + last = t + return ordered_list -- cgit v1.2.3