Browse Source

Style user and group links in text differently

Now that all links in text have underlines by default, I think this
looks pretty strange for ~group and @user links, which are quite common
and unnecessary to have underlined all the time. This modifies the
markdown parser to add link-user and link-group classes to these links,
which allows them to be styled differently.

In addition, some of the markdown tests needed to be changed to use
BeautifulSoup instead of simple string-matching, since it's not as
simple to recognize links any more (and the order of attrs might
change).
merge-requests/55/head
Deimos 6 years ago
parent
commit
53ccc25586
  1. 5
      tildes/scss/modules/_link.scss
  2. 28
      tildes/tests/test_markdown.py
  3. 10
      tildes/tildes/lib/markdown.py

5
tildes/scss/modules/_link.scss

@ -3,4 +3,9 @@
a.link-user, a.link-group { a.link-user, a.link-group {
white-space: nowrap; white-space: nowrap;
text-decoration: none;
&:hover {
text-decoration: underline;
}
} }

28
tildes/tests/test_markdown.py

@ -1,6 +1,8 @@
# Copyright (c) 2018 Tildes contributors <code@tildes.net> # Copyright (c) 2018 Tildes contributors <code@tildes.net>
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
from bs4 import BeautifulSoup
from tildes.lib.markdown import convert_markdown_to_safe_html from tildes.lib.markdown import convert_markdown_to_safe_html
@ -201,7 +203,8 @@ def test_group_reference_linkified():
markdown = "Yeah, I saw that in ~books.fantasy yesterday." markdown = "Yeah, I saw that in ~books.fantasy yesterday."
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert '<a href="/~books.fantasy">' in processed
soup = BeautifulSoup(processed, features="html5lib")
assert soup.find("a", href="/~books.fantasy")
def test_multiple_group_references_linkified(): def test_multiple_group_references_linkified():
@ -214,7 +217,8 @@ def test_multiple_group_references_linkified():
) )
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert processed.count("<a") == 3
soup = BeautifulSoup(processed, features="html5lib")
assert len(soup.find_all("a")) == 3
def test_invalid_group_reference_not_linkified(): def test_invalid_group_reference_not_linkified():
@ -241,7 +245,8 @@ def test_uppercase_group_ref_links_correctly():
markdown = "That was in ~Music.Metal.Progressive" markdown = "That was in ~Music.Metal.Progressive"
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert '<a href="/~music.metal.progressive' in processed
soup = BeautifulSoup(processed, features="html5lib")
assert soup.find("a", href="/~music.metal.progressive")
def test_existing_link_group_ref_not_replaced(): def test_existing_link_group_ref_not_replaced():
@ -280,7 +285,8 @@ def test_group_ref_inside_other_tags_linkified():
markdown = "> Here is **a ~group.reference inside** other stuff" markdown = "> Here is **a ~group.reference inside** other stuff"
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert '<a href="/~group.reference">' in processed
soup = BeautifulSoup(processed, features="html5lib")
assert soup.find("a", href="/~group.reference")
def test_username_reference_linkified(): def test_username_reference_linkified():
@ -288,7 +294,8 @@ def test_username_reference_linkified():
markdown = "Hey @SomeUser, what do you think of this?" markdown = "Hey @SomeUser, what do you think of this?"
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert '<a href="/user/SomeUser">@SomeUser</a>' in processed
soup = BeautifulSoup(processed, features="html5lib")
assert soup.find("a", href="/user/SomeUser")
def test_u_style_username_ref_linked(): def test_u_style_username_ref_linked():
@ -296,7 +303,8 @@ def test_u_style_username_ref_linked():
markdown = "Hey /u/SomeUser, what do you think of this?" markdown = "Hey /u/SomeUser, what do you think of this?"
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert '<a href="/user/SomeUser">/u/SomeUser</a>' in processed
soup = BeautifulSoup(processed, features="html5lib")
assert soup.find("a", href="/user/SomeUser")
def test_u_alt_style_username_ref_linked(): def test_u_alt_style_username_ref_linked():
@ -304,7 +312,8 @@ def test_u_alt_style_username_ref_linked():
markdown = "Hey u/SomeUser, what do you think of this?" markdown = "Hey u/SomeUser, what do you think of this?"
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert '<a href="/user/SomeUser">u/SomeUser</a>' in processed
soup = BeautifulSoup(processed, features="html5lib")
assert soup.find("a", href="/user/SomeUser")
def test_accidental_u_alt_style_not_linked(): def test_accidental_u_alt_style_not_linked():
@ -320,8 +329,9 @@ def test_username_and_group_refs_linked():
markdown = "@SomeUser makes the best posts in ~some.group for sure" markdown = "@SomeUser makes the best posts in ~some.group for sure"
processed = convert_markdown_to_safe_html(markdown) processed = convert_markdown_to_safe_html(markdown)
assert '<a href="/user/SomeUser">@SomeUser</a>' in processed
assert '<a href="/~some.group">~some.group</a>' in processed
soup = BeautifulSoup(processed, features="html5lib")
assert soup.find("a", href="/user/SomeUser")
assert soup.find("a", href="/~some.group")
def test_invalid_username_not_linkified(): def test_invalid_username_not_linkified():

10
tildes/tildes/lib/markdown.py

@ -376,7 +376,10 @@ class LinkifyFilter(Filter):
{ {
"type": "StartTag", "type": "StartTag",
"name": "a", "name": "a",
"data": {(None, "href"): f"/~{group_path}"},
"data": {
(None, "class"): "link-group",
(None, "href"): f"/~{group_path}",
},
}, },
{"type": "Characters", "data": match[0]}, {"type": "Characters", "data": match[0]},
{"type": "EndTag", "name": "a"}, {"type": "EndTag", "name": "a"},
@ -394,7 +397,10 @@ class LinkifyFilter(Filter):
{ {
"type": "StartTag", "type": "StartTag",
"name": "a", "name": "a",
"data": {(None, "href"): f"/user/{match[1]}"},
"data": {
(None, "class"): "link-user",
(None, "href"): f"/user/{match[1]}",
},
}, },
{"type": "Characters", "data": match[0]}, {"type": "Characters", "data": match[0]},
{"type": "EndTag", "name": "a"}, {"type": "EndTag", "name": "a"},

Loading…
Cancel
Save