Add `process_text_links` text utility to linkify URL's in text

Moved from Socialhome.
merge-requests/159/merge
Jason Robinson 2020-01-26 01:08:54 +02:00
rodzic 5ab541440d
commit 47d3d53a18
4 zmienionych plików z 53 dodań i 1 usunięć

Wyświetl plik

@ -8,6 +8,8 @@
If Django is configured, a profile will be retrieved using the configured profile
getter function and the profile name or username will be used for the link.
* Add `process_text_links` text utility to linkify URL's in text.
### Changed

Wyświetl plik

@ -1,4 +1,4 @@
from federation.utils.text import decode_if_bytes, encode_if_text, validate_handle
from federation.utils.text import decode_if_bytes, encode_if_text, validate_handle, process_text_links
def test_decode_if_bytes():
@ -11,6 +11,29 @@ def test_encode_if_text():
assert encode_if_text("foobar") == b"foobar"
class TestProcessTextLinks:
def test_link_at_start_or_end(self):
assert process_text_links('https://example.org example.org\nhttp://example.org') == \
'<a href="https://example.org" rel="nofollow" target="_blank">https://example.org</a> ' \
'<a href="http://example.org" rel="nofollow" target="_blank">example.org</a>\n' \
'<a href="http://example.org" rel="nofollow" target="_blank">http://example.org</a>'
def test_existing_links_get_attrs_added(self):
assert process_text_links('<a href="https://example.org">https://example.org</a>') == \
'<a href="https://example.org" rel="nofollow" target="_blank">https://example.org</a>'
def test_code_sections_are_skipped(self):
assert process_text_links('<code>https://example.org</code><code>\nhttps://example.org\n</code>') == \
'<code>https://example.org</code><code>\nhttps://example.org\n</code>'
def test_emails_are_skipped(self):
assert process_text_links('foo@example.org') == 'foo@example.org'
def test_does_not_add_target_blank_if_link_is_internal(self):
assert process_text_links('<a href="/streams/tag/foobar">#foobar</a>') == \
'<a href="/streams/tag/foobar">#foobar</a>'
def test_validate_handle():
assert validate_handle("foo@bar.com")
assert validate_handle("Foo@baR.com")

Wyświetl plik

@ -1,6 +1,9 @@
import re
from urllib.parse import urlparse
import bleach
from bleach import callbacks
def decode_if_bytes(text):
try:
@ -24,6 +27,29 @@ def get_path_from_url(url: str) -> str:
return parsed.path
def process_text_links(text):
"""Process links in text, adding some attributes and linkifying textual links."""
link_callbacks = [callbacks.nofollow, callbacks.target_blank]
def link_attributes(attrs, new=False):
"""Run standard callbacks except for internal links."""
href_key = (None, "href")
if attrs.get(href_key).startswith("/"):
return attrs
# Run the standard callbacks
for callback in link_callbacks:
attrs = callback(attrs, new)
return attrs
return bleach.linkify(
text,
callbacks=[link_attributes],
parse_email=False,
skip_tags=["code"],
)
def validate_handle(handle):
"""
Very basic handle validation as per

Wyświetl plik

@ -28,6 +28,7 @@ setup(
license="BSD 3-clause",
install_requires=[
"attrs",
"bleach>3.0",
"commonmark",
"cryptography",
"cssselect>=0.9.2",