def markup(self, width: int) -> str: start = self.start_tag() end = self.end_tag() remaining_width = width - len(start) - len(end) tokens = [] for child in self.children: tokens += child.tokens() content = ''.join(tokens) if content and len(content) > remaining_width: prefix = ' ' child_width = width - len(prefix) wrapped_tokens = wrap_tokens(tokens, child_width) if wrapped_tokens[-1].isspace(): wrapped_tokens[-1] = '\n' else: wrapped_tokens.append('\n') wrapped_content = ''.join(wrapped_tokens) if self.omit_end_tag(): return start + '\n' + indent(wrapped_content, prefix) else: return start + '\n' + indent(wrapped_content, prefix) + end + '\n' else: if self.omit_end_tag(): return start + content + '\n' else: return start + content + end + '\n'
def test_wrap_tokens_adjacent_words(self): tokens = [ '<em>', 'This', '</em>', ' ', 'is', ' ', 'some', ' ', 'text.' ] self.assertEqual( ['<em>', 'This', '</em>', '\n', 'is', ' ', 'some', '\n', 'text.'], wrap_tokens(tokens, 10))
def test_wrap_tokens_walks_back_to_break_for_adjacent_words(self): tokens = [ 'Find', ' ', 'a', ' ', '<i>', '<strong>', 'needle', '</strong>', '</i>', ' ', 'in', ' ', 'a', ' ', 'haystack.' ] self.assertEqual([ 'Find', ' ', 'a', '\n', '<i>', '<strong>', 'needle', '</strong>', '</i>', '\n', 'in', ' ', 'a', '\n', 'haystack.' ], wrap_tokens(tokens, 10))
def test_wrap_adds_two_spaces_after_a_period_inside_markup(self): tokens = [ '<em>', 'This', ' ', 'is', ' ', 'a', ' ', 'sentence.', '</em>', ' ', 'And', ' ', 'so', ' ', 'is', ' ', 'this.' ] self.assertEqual([ '<em>', 'This', ' ', 'is', ' ', 'a', ' ', 'sentence.', '</em>', ' ', 'And', ' ', 'so', ' ', 'is', ' ', 'this.' ], wrap_tokens(tokens, 80))
def test_wrap_breaks_line_after_a_period(self): tokens = [ 'This', ' ', 'is', ' ', 'a', ' ', 'sentence.', ' ', 'And', ' ', 'so', ' ', 'is', ' ', 'this.' ] self.assertEqual([ 'This', ' ', 'is', ' ', 'a', ' ', 'sentence.', '\n', 'And', ' ', 'so', ' ', 'is', ' ', 'this.' ], wrap_tokens(tokens, 20))
def test_wrap_tokens_wont_break_on_initial_space(self): tokens = [ ' ', '<i>', '<strong>', 'needle', '</strong>', '</i>', ' ', 'in', ' ', 'a', ' ', 'haystack.' ] self.assertEqual([ ' ', '<i>', '<strong>', 'needle', '</strong>', '</i>', '\n', 'in', ' ', 'a', '\n', 'haystack.' ], wrap_tokens(tokens, 10))
def append_tokens(): nonlocal markup, tokens if tokens: if tokens[0].isspace(): del tokens[0] if tokens and tokens[-1].isspace(): del tokens[-1] wrapped = wrap_tokens(tokens, child_width) wrapped.append('\n') s = ''.join(wrapped) markup += indent(s, prefix) tokens = []
def test_wrap_tokens_for_sentence_that_starts_with_long_word(self): tokens = [ '1234567890FOOBAR', ' ', '1234', ' ', '1234', ] self.assertEqual([ '1234567890FOOBAR', '\n', '1234', ' ', '1234', ], wrap_tokens(tokens, 10))
def test_wrap_tokens_for_lines_breaking_at_width(self): tokens = [ '1234', ' ', '12345', ' ', '1234', ' ', '12345', ] self.assertEqual([ '1234', ' ', '12345', '\n', '1234', ' ', '12345', ], wrap_tokens(tokens, 10))
def test_wrap_single_word(self): tokens = ['foobar'] self.assertEqual(['foobar'], wrap_tokens(tokens, 10))
def test_wrap_tokens_for_empty_list(self): tokens = [] self.assertEqual([], wrap_tokens(tokens, 10))
def test_wrap_tokens_for_long_sentence(self): tokens = ['This', ' ', 'is', ' ', 'some', ' ', 'text.'] self.assertEqual(['This', ' ', 'is', '\n', 'some', ' ', 'text.'], wrap_tokens(tokens, 10))
def test_wrap_tokens_for_short_sentence(self): tokens = ['This', ' ', 'is'] self.assertEqual(['This', ' ', 'is'], wrap_tokens(tokens, 10))
def test_wrap_tokens_for_starting_space(self): tokens = [' ', 'This', ' ', 'is', ' ', 'some', ' ', 'text.'] self.assertEqual([' ', 'This', ' ', 'is', '\n', 'some', ' ', 'text.'], wrap_tokens(tokens, 10))
def test_wrap_single_word_exact_width(self): tokens = ['1234567890'] self.assertEqual(['1234567890'], wrap_tokens(tokens, 10))
def test_wrap_tokens_for_ending_space_at_width(self): tokens = ['This', ' ', 'is', ' ', 'some', ' ', 'text.', ' '] self.assertEqual(['This', ' ', 'is', '\n', 'some', ' ', 'text.', '\n'], wrap_tokens(tokens, 10))
def test_wrap_tokens_for_ending_space_beyond_width(self): tokens = ['This', ' ', 'is', ' ', 'a_really_long_word.', ' '] self.assertEqual( ['This', ' ', 'is', '\n', 'a_really_long_word.', '\n'], wrap_tokens(tokens, 10))
def test_wrap_single_long_word(self): tokens = ['1234567890FOOBAR'] self.assertEqual(['1234567890FOOBAR'], wrap_tokens(tokens, 10))
def markup(self, width: int) -> str: wrapped = wrap_tokens(self.tokens(), width) return ''.join(wrapped)