diff --git a/docs/api.rst b/docs/api.rst index dc2a491..83c23f6 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -7,7 +7,7 @@ Main Interface -------------- Examples for the most relevant api functions can be viewed in the test -file. md_toc's API uses `type hints`_ instead of assertions to check input and +file. md_toc's API uses `type hints`_ instead of assertions to check input and output types. .. _type hints: https://docs.python.org/3/library/typing.html @@ -29,6 +29,15 @@ output types. .. autofunction:: is_closing_code_fence .. autofunction:: init_indentation_status_list .. autofunction:: toc_renders_as_coherent_list +.. autofunction:: remove_html_tags +.. autofunction:: get_generic_fdr_indices +.. autofunction:: get_fdr_indices +.. autofunction:: can_open_emphasis +.. autofunction:: can_close_emphasis +.. autofunction:: remove_emphasis +.. autofunction:: get_nearest_list_id + + Exceptions ---------- diff --git a/md_toc/__init__.py b/md_toc/__init__.py index 6b91443..bdfd2da 100644 --- a/md_toc/__init__.py +++ b/md_toc/__init__.py @@ -22,7 +22,8 @@ from .api import ( get_md_header, get_atx_heading, build_toc_line, remove_html_tags, - get_generic_fdr_indices, get_fdr_indices, + get_generic_fdr_indices, get_fdr_indices, can_open_emphasis, + can_close_emphasis, remove_emphasis, get_nearest_list_id, increase_index_ordered_list, build_anchor_link, init_indentation_log, compute_toc_line_indentation_spaces, build_toc_line_without_indentation, build_toc, build_multiple_tocs, write_string_on_file_between_markers, diff --git a/md_toc/api.py b/md_toc/api.py index 4091c3d..611e675 100644 --- a/md_toc/api.py +++ b/md_toc/api.py @@ -683,22 +683,41 @@ def remove_html_tags(line: str, parser: str = 'github') -> str: def get_generic_fdr_indices(i: int, line: str, char: str, mem: dict, type: str = 'left', parser='github') -> int: - r"""get_generic_fdr_indices. + r"""Compute the indices of flanking delimiter runs in a string. :parameter i: the current iterating index of the line. + :parameter line: a string. + :parameter char: the delimiter type. + :parameter mem: a data structure containing the fdr indices + grouped by char, in start-end lists. See the get_fdr_indices function. + :parameter type: the type of FDR. This value can only be ``left`` or ``right``. + :parameter parser: decides rules on how to find FDR indices. + Defaults to ``github``. + :type i: int + :type line: str + :type char: str + :type mem: dict + :type type: str + :type parser: str + :returns: the current iterating index. + :rtype: int + :raises: a built-in exception. """ - if char not in ['*', '_']: - raise ValueError - if '*' not in mem: + if len(char) != 1: raise ValueError - if '_' not in mem: - raise ValueError - if not isinstance(mem['*'], list): - raise TypeError - if not isinstance(mem['_'], list): - raise TypeError if type != 'left' and type != 'right': raise ValueError + if parser in ['github', 'cmark', 'gitlab', 'commonmarker']: + if char not in ['*', '_']: + raise ValueError + if '*' not in mem: + raise ValueError + if '_' not in mem: + raise ValueError + if not isinstance(mem['*'], list): + raise TypeError + if not isinstance(mem['_'], list): + raise TypeError if parser in ['github', 'cmark', 'gitlab', 'commonmarker']: is_fdr = False @@ -773,7 +792,20 @@ def get_generic_fdr_indices(i: int, line: str, char: str, mem: dict, type: str = def get_fdr_indices(line: str, type: str = 'left', parser: str = 'github') -> dict: - r"""Find FDR indices.""" + r"""Iteratevly find flanking delimiter runs indices. + + :parameter line: a string. + :parameter type: the type of FDR. This value can only be ``left`` or ``right``. + :parameter parser: decides rules on how to find FDR indices. + Defaults to ``github``. + :type line: str + :type type: str + :type parser: str + :returns: a data structure contaning the flanking delimiter runs indices. + See the ``fdr_indices`` data structure. + :rtype: dict + :raises: a built-in exception. + """ if type != 'left' and type != 'right': raise ValueError @@ -782,86 +814,282 @@ def get_fdr_indices(line: str, type: str = 'left', parser: str = 'github') -> di # the get_generic_fdr_indices function. line = line[::-1] - i = 0 + fdr_indices = dict() + if parser in ['github', 'cmark', 'gitlab', 'commonmarker']: + + # A data structure containing the lfdr indices by type ,divided into couples start-end: + # '*': [[s0,e0], [s1,e1], ..., [sn,en]] + # '_': [[s0,e0], [s1,e1], ..., [sn,en]] + fdr_indices['*'] = list() + fdr_indices['_'] = list() + + i = 0 + while i < len(line): + i = get_generic_fdr_indices(i, line, '*', fdr_indices, type, parser) + i = get_generic_fdr_indices(i, line, '_', fdr_indices, type, parser) + i += 1 + + return fdr_indices + + +def can_open_emphasis(line: str, emphasis_char: str, start: int, end: int, parser: str = 'github') -> bool: + r"""Check if a substring can open emphasis. + + :parameter line: a string. + :emphasis_char: a character. + :start: index where to start the analysis. + :end: index where to end the analysis. + :parameter parser: decides rules on how to find FDR indices. + Defaults to ``github``. + :type line: str + :type emphasis_char: str + :type start: int + :type end: int + :type parser: str + :returns: a boolean that is set to ``True`` if a substring can open emphasis, + ``False`` otherwise. + :rtype: bool + :raises: a built-in exception. + """ + if len(emphasis_char) != 1: + raise ValueError + if start < 0: + raise ValueError + if end > len(line) - 1: + raise ValueError - # A data structure containing the lfdr indices by type ,divided into couples start-end: - # '*': [[s0,e0], [s1,e1], ..., [sn,en]] - # '_': [[s0,e0], [s1,e1], ..., [sn,en]] - m = { + # Absence of flanking delimiter run. + no_fdr = { '*': list(), '_': list(), } - while i < len(line): - i = get_generic_fdr_indices(i, line, '*', m, type, parser) - i = get_generic_fdr_indices(i, line, '_', m, type, parser) - i += 1 + # See + # https://spec.commonmark.org/0.28/#can-open-emphasis - return m + can_open = False + # Rule 1, 2, 5, 6. + if get_fdr_indices(line=line[start: end + 1], type='left') != no_fdr: + can_open = True + # Rule 5, 6. + if can_open and emphasis_char == '_': + can_open = False + condition = False + # end + 1 is to get the end index really. + if get_fdr_indices(line=line[start: end + 1], type='right') == no_fdr: + can_open = True + condition = True + if not condition: + if get_fdr_indices(line=line[start: end + 1], type='right') != no_fdr and line[start] in md_parser['github']['pseudo-re']['PC']: + can_open = True -def get_remove_emphasis_indices(line: str): - r"""get_remove_emphasis_indices.""" - i = 0 - j = len(line) - 1 - ignore_list = list() + return can_open + + +def can_close_emphasis(line: str, emphasis_char: str, start: int, end: int) -> bool: + r"""Check if a substring can close emphasis. + + :parameter line: a string. + :emphasis_char: a character. + :start: index where to start the analysis. + :end: index where to end the analysis. + :parameter parser: decides rules on how to find FDR indices. + Defaults to ``github``. + :type line: str + :type emphasis_char: str + :type start: int + :type end: int + :type parser: str + :returns: a boolean that is set to ``True`` if a substring can close emphasis, + ``False`` otherwise. + :rtype: bool + :raises: a built-in exception. + """ + if start < 0: + raise ValueError + if end > len(line) - 1: + raise ValueError + + # Absence of flanking delimiter run. no_fdr = { '*': list(), '_': list(), } - while i < len(line) and j >= 0 and i < j: - Si = i - has_open = False - has_close = False - is_lfdr = True + # See + # https://spec.commonmark.org/0.28/#can-close-emphasis - while i < len(line) and line[i] == '*': - i += 1 + can_close = False + # Rule 3, 4, 7, 8. + if get_fdr_indices(line=line[start: end + 1], type='right') != no_fdr: + can_close = True - if Si > 0: - start_inspect = Si - 1 - else: - start_inspect = Si + # Rule 7, 8. + if can_close and emphasis_char == '_': + can_close = False + condition = False + if get_fdr_indices(line=line[start: end + 1], type='left') == no_fdr: + can_close = True + condition = True + if not condition: + if get_fdr_indices(line=line[start: end + 1], type='left') != no_fdr and line[end] in md_parser['github']['pseudo-re']['PC']: + can_close = True - lfdr_indices = get_fdr_indices(line=line[start_inspect:i + 1], type='left') - if lfdr_indices == no_fdr: - is_lfdr = False + return can_close - iter = i - Si - if iter > 0 and is_lfdr: - has_open = True - has_close = False +def remove_emphasis(line: str, parser: str = 'github') -> str: + r"""Remove emphasis. - while i < j and iter > 0: - Sj = j + :parameter line: a string. + :parameter parser: decides rules on how to find FDR indices. + Defaults to ``github``. + :type line: str + :type parser: str + :returns: the input line without emphasis. + :rtype: str + :raises: a built-in exception. - while line[j] != '*' and j > i: - j -= 1 + ..note: In case of cmark we don't care about removing ``*`` because + all ``*`` are removed anyway by the build_anchor_link function. + If you care to remove ``*`` this function needs to be tweaked. + """ + ignore = list() + if parser in ['github', 'cmark', 'gitlab', 'commonmarker']: + all = list() + j = len(line) - 1 + # Get all delimiter runs and divide them into lists. + while j >= 0: + Sj = j + tmp = list() + while j >= 0 and line[j] == '_': + tmp.append(j) + j -= 1 + if Sj > j: + all.append(tmp) + + j -= 1 + + opn = list() + cls = list() + while len(all) > 0: + # Every x is a delimiter run. + x = all.pop() + + # Check line limits. + if x[-1] == 0: + start = 0 + else: + start = x[-1] - 1 + if x[0] == len(line) - 1: + end = len(line) - 1 + else: + end = x[0] + 1 - # Last position of a star character. - last_j = j + # Separate delimiter runs into opening and closing emphasis. + # Delimiter runs may be in both lists. + if can_close_emphasis(line, '_', start, end): + cls.append(sorted(x)) + if can_open_emphasis(line, '_', start, end): + opn.append(x) - # Check if characters are part of RFDR to determine if they might be closing emphasis. - while j > 0 and line[j] == '*' and last_j - j < iter and line[j - 1] != '\\': - j -= 1 + # Reverse. + opn = opn[::-1] + + i = 0 + # Add elements to ignore list if: + # 1. opening and closing delimiters match in length + # 2. closing > opening in terms of indices + while i < len(opn): + if len(cls) > 0: + # Get the closing delimiter of the last opening delimiter. + x = get_nearest_list_id(opn[i][0], cls) + j = 0 + while j < len(opn[i]): + # Skip if delimiter can both open and close but + # we need to avoid duplicates. + # For example, try: + # + # md_toc.api.remove_emphasis('foo-_(bar)_') + # + # opn = [[4]] + # cls = [[4], [10]] + # The first iteration is skipped because + # 4 !> 4 + # but the second is not, because + # 10 > 4 + # so we have + # ignore.append(close) == 10 + # ignore.append(open) == 4 + if sorted(opn[i]) in cls and len(cls) < len(opn): + pass + else: + if len(cls[x]) > 0: + # Empty the closing list so we don't have to + # keep track of indices. + close = cls[x].pop(0) + open = opn[i][-j] + if close > open: + ignore.append(close) + ignore.append(open) + j += 1 + # Remove an empty closing list. + if len(cls) > 0 and len(cls[-1]) == 0: + cls.pop(-1) + i += 1 + + # Keep line indices which are not in the ignore list. + s = sorted(ignore) + final = str() + i = 0 + while i < len(line): + if i not in s: + final += line[i] + i += 1 - closing_emph = False - if get_fdr_indices(line=line[j:Sj + 1], type='right') != no_fdr: - closing_emph = True + return final - if j < Sj and closing_emph: - total_closed = last_j - j - iter -= total_closed - ignore_list.append([j + 1, last_j]) - has_close = True - if has_open and has_close: - ignore_list.append([Si, i - 1]) +def get_nearest_list_id(index: int, integer_lists: list) -> int: + r"""Given a list of lists of integers, find the list id corresponding to the nearest bigger number to be searched (the index). + + :parameter index: an integer from which to start searching. + :parameter integer_lists: a list of lists of integers. + :type index: int + :type integer_lists: list + :returns: the list id corresponding to the nearest bigger number to be searched. + :rtype: int + :raises: a built-in exception. + + ..note: the lists must be sorted increasingly and the container list as well. + """ + if len(integer_lists) == 0: + raise ValueError + if len(integer_lists[-1]) == 0: + raise ValueError + for ll in integer_lists: + for e in ll: + if not isinstance(e, int): + raise TypeError + + i = 0 + # Initially, min = max. + min = integer_lists[-1][-1] + nearest_list_id = len(integer_lists) - 1 + done = False + while i < len(integer_lists) and not done: + j = 0 + while j < len(integer_lists[i]) and not done: + # nearest_list_id must always come after the index. + if integer_lists[i][j] > index and integer_lists[i][j] < min: + min = integer_lists[i][j] + nearest_list_id = i + done = True + j += 1 i += 1 - return ignore_list + return nearest_list_id def build_anchor_link(header_text_trimmed: str, @@ -895,7 +1123,7 @@ def build_anchor_link(header_text_trimmed: str, header_text_trimmed = remove_html_tags(header_text_trimmed, parser) # Filter "emphasis and strong emphasis". - # TODO + header_text_trimmed = remove_emphasis(header_text_trimmed, parser) # Remove punctuation: Keep spaces, hypens and "word characters" # only. diff --git a/md_toc/tests/tests.py b/md_toc/tests/tests.py index 64190ca..446ad5a 100644 --- a/md_toc/tests/tests.py +++ b/md_toc/tests/tests.py @@ -430,6 +430,14 @@ def test_build_toc_line(self): Refer to those two functions for the unit tests. """ + @unittest.skip("empty test") + def get_generic_fdr_indices(self): + r"""Test that LFDR and RFDR indices are computed correctly. + + This function is not tested because all its functionality is tested + in the test_get_fdr_indices function. + """ + def test_get_fdr_indices(self): r"""Test get flanking delimiter run indices. @@ -470,145 +478,224 @@ def test_get_fdr_indices(self): self.assertEqual(api.get_fdr_indices('abc *** def', 'right', 'github'), {'*': list(), '_': list(), }) self.assertEqual(api.get_fdr_indices('a _ b', 'right', 'github'), {'*': list(), '_': list(), }) - def test_get_remove_emphasis_indices(self): - r"""Test get remove emphasis indices.""" - # Example 331 - self.assertEqual(api.get_remove_emphasis_indices('*foo bar*'), [[8, 8], [0, 0]]) + @unittest.skip("empty test") + def test_can_open_emphasis(self): + r"""Test that a substring can open emphasis in specific cases. - # Example 332 - self.assertEqual(api.get_remove_emphasis_indices('a * foo bar*'), list()) + This function is not tested because all its functionality is tested + in the remove_emphasis function. + """ - # Example 333 - self.assertEqual(api.get_remove_emphasis_indices('a*"foo"*'), list()) + @unittest.skip("empty test") + def test_can_close_emphasis(self): + r"""Test that a substring can close emphasis in specific cases. - # Example 334 - self.assertEqual(api.get_remove_emphasis_indices('* a *'), list()) + This function is not tested because all its functionality is tested + in the remove_emphasis function. + """ - # Example 335 - self.assertEqual(api.get_remove_emphasis_indices('foo*bar*'), [[7, 7], [3, 3]]) + @unittest.skip("empty test") + def test_get_generic_fdr_indices(self): + r"""Test that LFDR and RFDR indices are computed correctly. - # Example 336 - self.assertEqual(api.get_remove_emphasis_indices('5*6*78'), [[3, 3], [1, 1]]) + This function is not tested because all its functionality is tested + in the test_get_fdr_indices function. + """ + def test_remove_emphasis(self): + r"""Test that removing emphasis works correctly correctly. + + .. note: not all tests are enabled because of a missing implementation + and possible bugs. + """ # Example 337 - # self.assertEqual(api.get_remove_emphasis_indices('_foo bar_'), [[3, 3], [1, 1]]) + self.assertEqual(api.remove_emphasis('_foo bar_'), 'foo bar') + # Example 338 + self.assertEqual(api.remove_emphasis('_ foo bar_'), '_ foo bar_') + # Example 339 + self.assertEqual(api.remove_emphasis('a_"foo"_'), 'a_"foo"_') + # Example 340 - # Example 341 - # Example 342 - # Example 343 - # Example 344 - # Example 345 + self.assertEqual(api.remove_emphasis('foo_bar_'), 'foo_bar_') - # Example 346 - self.assertEqual(api.get_remove_emphasis_indices('*foo bar *'), list()) + # Example 341 + self.assertEqual(api.remove_emphasis('5_6_78'), '5_6_78') - # Example 347 - self.assertEqual(api.get_remove_emphasis_indices('*foo bar\n*'), list()) + # Example 342 + self.assertEqual(api.remove_emphasis('пристаням_стремятся_'), 'пристаням_стремятся_') - # Example 348 - self.assertEqual(api.get_remove_emphasis_indices('*(*foo)'), list()) + # Example 343 + self.assertEqual(api.remove_emphasis('aa_"bb"_cc'), 'aa_"bb"_cc') - # Example 349 - self.assertEqual(api.get_remove_emphasis_indices('*(*foo*)*'), [[8, 8], [0, 0], [6, 6], [2, 2]]) + # Example 344 + self.assertEqual(api.remove_emphasis('foo-_(bar)_'), 'foo-(bar)') - # Example 350 - self.assertEqual(api.get_remove_emphasis_indices('*foo*bar'), [[4, 4], [0, 0]]) + # Example 345 + self.assertEqual(api.remove_emphasis('_foo*'), '_foo*') # Example 351 + self.assertEqual(api.remove_emphasis('_foo bar _'), '_foo bar _') + # Example 352 + self.assertEqual(api.remove_emphasis('_(_foo)'), '_(_foo)') + # Example 353 - # Example 354 - # Example 355 - # Example 356 - # Example 357 + self.assertEqual(api.remove_emphasis('_(_foo_)_'), '(foo)') - # Example 358 - self.assertEqual(api.get_remove_emphasis_indices('**foo bar**'), [[9, 10], [0, 1]]) + # Example 354 + self.assertEqual(api.remove_emphasis('_foo_bar'), '_foo_bar') - # Example 359 - self.assertEqual(api.get_remove_emphasis_indices('** foo bar**'), list()) + # Example 355 + self.assertEqual(api.remove_emphasis('_пристаням_стремятся'), '_пристаням_стремятся') - # Example 360 - self.assertEqual(api.get_remove_emphasis_indices('a**"foo"**'), list()) + # Example 356 + self.assertEqual(api.remove_emphasis('_foo_bar_baz_'), 'foo_bar_baz') - # Example 361 - self.assertEqual(api.get_remove_emphasis_indices('foo**bar**'), [[8, 9], [3, 4]]) + # Example 357 + self.assertEqual(api.remove_emphasis('_(bar)_.'), '(bar).') # Example 362 + self.assertEqual(api.remove_emphasis('__foo bar__'), 'foo bar') + # Example 363 + self.assertEqual(api.remove_emphasis('__ foo bar__'), '__ foo bar__') + # Example 364 - # Example 365 - # Example 366 - # Example 367 - # Example 368 - # Example 369 - # Example 370 + self.assertEqual(api.remove_emphasis('__\nfoo bar__'), '__\nfoo bar__') - # Example 371 - self.assertEqual(api.get_remove_emphasis_indices('**foo bar **'), list()) + # Example 365 + self.assertEqual(api.remove_emphasis('a__"foo"__'), 'a__"foo"__') - # Example 372 - self.assertEqual(api.get_remove_emphasis_indices('**(**foo)'), list()) + # Example 366 + self.assertEqual(api.remove_emphasis('foo__bar__'), 'foo__bar__') - # Example 373 - self.assertEqual(api.get_remove_emphasis_indices('*(**foo**)*'), [[10, 10], [0, 0], [7, 8], [2, 3]]) + # Example 367 + self.assertEqual(api.remove_emphasis('5__6__78'), '5__6__78') - # Example 374 -# self.assertEqual(api.get_remove_emphasis_indices('**Gomphocarpus (*Gomphocarpus physocarpus*, syn.\n*Asclepias physocarpa*)**'), [[0, 1], [16, 16], [41, 41], [49, 49], [70, 70], [72, 73]]) + # Example 368 + self.assertEqual(api.remove_emphasis('пристаням__стремятся__'), 'пристаням__стремятся__') - # Example 375 - self.assertEqual(api.get_remove_emphasis_indices('**foo "*bar*" foo**'), [[17, 18], [0, 1], [11, 11], [7, 7]]) + # Example 369 + self.assertEqual(api.remove_emphasis('__foo, __bar__, baz__'), 'foo, bar, baz') - # Example 376 - self.assertEqual(api.get_remove_emphasis_indices('**foo**bar'), [[5, 6], [0, 1]]) + # Example 370 + self.assertEqual(api.remove_emphasis('foo-__(bar)__'), 'foo-(bar)') # Example 377 + self.assertEqual(api.remove_emphasis('__foo bar __'), '__foo bar __') + # Example 378 + self.assertEqual(api.remove_emphasis('__(__foo)'), '__(__foo)') + # Example 379 + self.assertEqual(api.remove_emphasis('_(__foo__)_'), '(foo)') + # Example 380 + self.assertEqual(api.remove_emphasis('__foo__bar'), '__foo__bar') + # Example 381 - # Example 382 - # Example 383 + self.assertEqual(api.remove_emphasis('__пристаням__стремятся'), '__пристаням__стремятся') - # Example 384 - self.assertEqual(api.get_remove_emphasis_indices('*foo [bar](/url)*'), [[16, 16], [0, 0]]) + # Example 382 + self.assertEqual(api.remove_emphasis('__foo__bar__baz__'), 'foo__bar__baz') - # Example 385 - self.assertEqual(api.get_remove_emphasis_indices('*foo\nbar*'), [[8, 8], [0, 0]]) + # Example 383 + self.assertEqual(api.remove_emphasis('__(bar)__.'), '(bar).') # Example 386 + self.assertEqual(api.remove_emphasis('_foo __bar__ baz_'), 'foo bar baz') + # Example 387 + self.assertEqual(api.remove_emphasis('_foo _bar_ baz_'), 'foo bar baz') + # Example 388 +# self.assertEqual(api.remove_emphasis('__foo_ bar_'), 'foo bar') + + # Example 401 + self.assertEqual(api.remove_emphasis('__foo _bar_ baz__'), 'foo bar baz') + + # Example 402 + self.assertEqual(api.remove_emphasis('__foo __bar__ baz__'), 'foo bar baz') + + # Example 403 +# self.assertEqual(api.remove_emphasis('____foo__ bar__'), 'foo bar') + + # Example 411 + self.assertEqual(api.remove_emphasis('__ is not an empty emphasis'), '__ is not an empty emphasis') + + # Example 412 + self.assertEqual(api.remove_emphasis('____ is not an empty strong emphasis'), '____ is not an empty strong emphasis') + + # Example 425 + self.assertEqual(api.remove_emphasis('foo ___'), 'foo ___') + + # Example 426 + self.assertEqual(api.remove_emphasis(r'foo _\__'), r'foo \_') + + # Example 427 +# self.assertEqual(api.remove_emphasis('foo _*_'), 'foo *') + + # Example 428 + self.assertEqual(api.remove_emphasis('foo _____'), 'foo _____') + + # Example 429 + self.assertEqual(api.remove_emphasis(r'foo __\___'), r'foo \_') + + # Example 430 +# self.assertEqual(api.remove_emphasis('foo __*__'), 'foo *') + + # Example 431 + self.assertEqual(api.remove_emphasis('__foo_'), '_foo') + + # Example 432 + self.assertEqual(api.remove_emphasis('_foo__'), 'foo_') + + # Example 433 + self.assertEqual(api.remove_emphasis('___foo__'), '_foo') + + # Example 434 + self.assertEqual(api.remove_emphasis('____foo_'), '___foo') - # Example 389 -# self.assertEqual(api.get_remove_emphasis_indices('*foo *bar**'), [[9, 10], [5, 5], [0, 0]]) + # Example 435 + self.assertEqual(api.remove_emphasis('__foo___'), 'foo_') - # Example 390 - self.assertEqual(api.get_remove_emphasis_indices('*foo **bar** baz*'), [[16, 16], [0, 0], [10, 11], [5, 6]]) + # Example 436 + self.assertEqual(api.remove_emphasis('_foo____'), 'foo___') - # Example 391 + # Example 438 + self.assertEqual(api.remove_emphasis('*_foo_*'), '*foo*') - # Example 392 + # Example 439 + self.assertEqual(api.remove_emphasis('__foo__'), 'foo') - # Example 393 + # Example 440 +# self.assertEqual(api.remove_emphasis('_*foo*_'), '*foo*') - # Example 394 + # Example 442 + self.assertEqual(api.remove_emphasis('____foo____'), 'foo') - # Example 395 + # Example 445 + self.assertEqual(api.remove_emphasis('_____foo_____'), 'foo') - # Example 396 + # Example 446 +# self.assertEqual(api.remove_emphasis('*foo _bar* baz_'), '*foo _bar* baz_') - # Example 397 + # Example 447 + self.assertEqual(api.remove_emphasis('*foo __bar *baz bim__ bam*'), '*foo bar *baz bim bam*') - # Example 398 + # Example 451 +# self.assertEqual(api.remove_emphasis('_foo [bar_](/url)'), '_foo [bar_](/url)') - # Example 399 + # Example 454 +# self.assertEqual(api.remove_emphasis('__'), '__') - # Example 400 + # Example 456 +# self.assertEqual(api.remove_emphasis('_a `_`_'), 'a `_`') # Example 458 +# self.assertEqual(api.remove_emphasis('__a'), '__a') def test_remove_html_tags(self): r"""Test remove html tags."""