diff --git a/README.md b/README.md index 4a7bec85..52cddc2b 100644 --- a/README.md +++ b/README.md @@ -318,6 +318,8 @@ Changelog * Revise whitespace handling; use `white-space: pre` CSS in HTML output. * Facebook: * Bug fix: don't interpret `photo.php` as username in post URLs. +* Atom: + * Switch from `white-space: pre` CSS back to converting newlines to `
`s because some feed readers ([eg NewsBlur](https://forum.newsblur.com/t/android-cant-read-line-pre-formatted-lines/6116)) follow it too strictly and don't even line wrap. * RSS: * Default title to ellipsized content. diff --git a/granary/atom.py b/granary/atom.py index ba0e009a..0c867a20 100644 --- a/granary/atom.py +++ b/granary/atom.py @@ -357,7 +357,11 @@ def _prepare_activity(a, reader=True): # Render content as HTML; escape &s obj['rendered_content'] = _encode_ampersands(microformats2.render_content( - primary, include_location=reader, render_attachments=True)) + primary, include_location=reader, render_attachments=True, + # Readers often obey CSS white-space: pre strictly and don't even line wrap, + # so don't use it. + # https://forum.newsblur.com/t/android-cant-read-line-pre-formatted-lines/6116 + white_space_pre=False)) # Make sure every activity has the title field, since Atom requires # the title element. diff --git a/granary/microformats2.py b/granary/microformats2.py index 2db7716d..538e36a3 100644 --- a/granary/microformats2.py +++ b/granary/microformats2.py @@ -769,7 +769,7 @@ def hcard_to_html(hcard, parent_props=None): def render_content(obj, include_location=True, synthesize_content=True, - render_attachments=False): + render_attachments=False, white_space_pre=True): """Renders the content of an ActivityStreams object as HTML. Includes tags, mentions, and non-note/article attachments. (Note/article @@ -784,6 +784,9 @@ def render_content(obj, include_location=True, synthesize_content=True, include_location: whether to render location, if provided synthesize_content: whether to generate synthetic content if the object doesn't have its own, e.g. 'likes this.' or 'shared this.' + white_space_pre: boolean, whether to wrap in CSS white-space: pre. If False, + newlines will be converted to
tags instead. Background: + https://indiewebcamp.com/note#Indieweb_whitespace_thinking Returns: string, rendered HTML @@ -826,7 +829,10 @@ def render_content(obj, include_location=True, synthesize_content=True, # https://indiewebcamp.com/note#Indieweb_whitespace_thinking # https://github.com/snarfed/granary/issues/80 if content and not obj.get('content_is_html') and '\n' in content: - content = '
%s
' % content + if white_space_pre: + content = '
%s
' % content + else: + content = content.replace('\n', '
\n') # linkify embedded links. ignore the "mention" tags that we added ourselves. # TODO: fix the bug in test_linkify_broken() in webutil/tests/test_util.py, then diff --git a/granary/tests/test_microformats2.py b/granary/tests/test_microformats2.py index 27404878..1115054a 100644 --- a/granary/tests/test_microformats2.py +++ b/granary/tests/test_microformats2.py @@ -204,7 +204,7 @@ def test_render_content_multiple_image_attachments(self):

""", microformats2.render_content(obj, render_attachments=True)) - def test_render_content_converts_newlines_to_brs(self): + def test_render_content_newlines_default_white_space_pre(self): self.assert_equals("""\
foo bar @@ -214,6 +214,16 @@ def test_render_content_converts_newlines_to_brs(self): 'tags': [{'url': 'http://baz', 'startIndex': 8, 'length': 3}] })) + def test_render_content_convert_newlines_to_brs(self): + self.assert_equals("""\ +foo
+bar
+baz +""", microformats2.render_content({ + 'content': 'foo\nbar\nbaz', + 'tags': [{'url': 'http://baz', 'startIndex': 8, 'length': 3}] +}, white_space_pre=False)) + def test_render_content_omits_tags_without_urls(self): self.assert_equals("""\ foo @@ -633,8 +643,8 @@ def test_json_to_object_with_categories(self): }, ], obj.get('tags')) - def test_json_to_object_converts_text_newlines_to_brs(self): - """Text newlines should be converted to
s.""" + def test_json_to_object_text_newlines(self): + """Text newlines should not be converted to
s.""" self.assert_equals({ 'objectType': 'note', 'content': 'asdf\nqwer',