Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to display a limited set of HTML tags (aligned with mastodon PR #23913) plus URL support #356

Closed
wants to merge 53 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
80814eb
Support for rendering a subset of HTML tags in status content
danschwarz Mar 24, 2023
3b4f46c
comments and formatting
danschwarz Apr 1, 2023
717a0e4
Removed unneeded import
danschwarz Apr 1, 2023
479907b
Support for rendering a subset of HTML tags in status content
danschwarz Apr 4, 2023
4ceb3e5
Ignore warning W503
danschwarz Apr 4, 2023
eb8033c
add get_lists method
danschwarz Apr 4, 2023
524115e
Make button widget unicode-aware (spacing)
danschwarz Apr 4, 2023
d65cac1
Add basic support for Mastodon Lists
danschwarz Apr 4, 2023
7189c6b
"toot list" console command added
danschwarz Apr 4, 2023
94315dd
added "toot list_accounts" command
danschwarz Apr 4, 2023
85c228b
Added "toot list_delete" and "toot list_create" commands
danschwarz Apr 4, 2023
678cc19
Added toot list_add_account command
danschwarz Apr 4, 2023
1164d0c
Added toot list_remove_account command
danschwarz Apr 4, 2023
7ad9e7c
minor improvement of feedback messages
danschwarz Apr 4, 2023
0430eed
Changed parameters for list cmds
danschwarz Apr 4, 2023
45cffb6
Give a more specfic error message if we can't add an account to list
danschwarz Apr 4, 2023
037f7f9
Break up integration tests
ihabunek Apr 4, 2023
1c9935e
Add a simple table printer and apply to lists
ihabunek Apr 4, 2023
4023bf0
Add integration tests for lists
ihabunek Apr 4, 2023
fe3044f
Fix tests
ihabunek Apr 4, 2023
006ad85
Extract fetching list ID
ihabunek Apr 4, 2023
d3ea1e5
Simplify integration tests by catching ConsoleError
ihabunek Apr 4, 2023
1fb0561
Slightly tightened up list number spacing
danschwarz Apr 4, 2023
c48501e
renamed get_style_name to get_urwid_attr_name for clarity
danschwarz Apr 4, 2023
dc9fa05
Make output match existing master branch status rendering exactly
danschwarz Apr 4, 2023
9ed0a47
fixed up palette constants a bit
danschwarz Apr 4, 2023
6e1d36f
Removed unneeded import
danschwarz Apr 4, 2023
0098371
Unicode normalize 'NKFC' incoming HTML text before rendering
danschwarz Apr 4, 2023
84663d6
Cleaned up type violations
danschwarz Apr 4, 2023
486cd6c
Make HTML class handling more sensible
danschwarz Apr 4, 2023
103767d
switch pre and code to render as light grey rather than dark
danschwarz Apr 4, 2023
eb64cb9
Handle nested B and I tags, also nested EM and STRONG tags
danschwarz Apr 4, 2023
e6b708f
Merge branch 'master' into richtext
danschwarz Apr 4, 2023
72aa934
make pytest work properly
danschwarz Apr 5, 2023
e9b4bfb
fix markup for br tag
danschwarz Apr 6, 2023
bb31054
elaborated comment
danschwarz Apr 7, 2023
739c009
Merge branch 'master' of https://github.com/danschwarz/toot
danschwarz Apr 7, 2023
0e6c726
Merge branch 'master' into richtext
danschwarz Apr 7, 2023
306cf45
README.rst: Fix image links
vitorgalvao Apr 18, 2023
5d47a0a
added urwidgets dependency
danschwarz May 1, 2023
9ccfd6b
Support OSC 8 underline of anchor links
danschwarz May 8, 2023
4a5db5b
added OSC 8 hyperlinks for media links and card links
danschwarz May 8, 2023
baa50ca
Added a workaround for statuses with malformed HTML
danschwarz May 13, 2023
de3461e
Hashtag highlighting now works correctly
danschwarz May 13, 2023
457facd
Fix for rendering HTML that starts with an inline tag
danschwarz May 13, 2023
fe88a40
Switched to released version of urwidgets (0.1.0)
danschwarz May 15, 2023
b3c654b
Added support for li value attribute, ol start and reverse attributes
danschwarz May 16, 2023
86304df
fix ws
danschwarz May 16, 2023
4c51220
Removed followed_tags highlight feature (incompatible with HTML render)
danschwarz May 17, 2023
5c6644b
Login to servers that don't honor the uri spec for V1::Instance
danschwarz May 26, 2023
f14653a
Anchor tags with class = hashtag or mention_hashtag are highlighted
danschwarz May 28, 2023
33afe39
URLEncode hrefs; fixes crash bug with href urls in foreign scripts
danschwarz May 28, 2023
f45dfa1
Merge branch 'master' into rt-hyperlinks
danschwarz Jun 22, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ publish :
twine upload dist/*.tar.gz dist/*.whl

test:
pytest -v
pytest tests/*.py -v
flake8
vermin --target=3.6 --no-tips --violations --exclude-regex venv/.* .

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ requests>=2.13,<3.0
beautifulsoup4>=4.5.0,<5.0
wcwidth>=0.1.7
urwid>=2.0.0,<3.0

urwidgets=>=0.1,<0.2
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"beautifulsoup4>=4.5.0,<5.0",
"wcwidth>=0.1.7",
"urwid>=2.0.0,<3.0",
"urwidgets>=0.1,<0.2",
],
entry_points={
'console_scripts': [
Expand Down
17 changes: 0 additions & 17 deletions toot/tui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ def __init__(self, app, user, args):
def run(self):
self.loop.set_alarm_in(0, lambda *args: self.async_load_instance())
self.loop.set_alarm_in(0, lambda *args: self.async_load_followed_accounts())
self.loop.set_alarm_in(0, lambda *args: self.async_load_followed_tags())
self.loop.set_alarm_in(0, lambda *args: self.async_load_timeline(
is_initial=True, timeline_name="home"))
self.loop.run()
Expand Down Expand Up @@ -315,22 +314,6 @@ def _done_accounts(accounts):

self.run_in_thread(_load_accounts, done_callback=_done_accounts)

def async_load_followed_tags(self):
def _load_tag_list():
try:
return api.followed_tags(self.app, self.user)
except ApiError:
# not supported by all Mastodon servers so fail silently if necessary
return []

def _done_tag_list(tags):
if len(tags) > 0:
self.followed_tags = [t["name"] for t in tags]
else:
self.followed_tags = []

self.run_in_thread(_load_tag_list, done_callback=_done_tag_list)

def refresh_footer(self, timeline):
"""Show status details in footer."""
status, index, count = timeline.get_focused_status_with_counts()
Expand Down
24 changes: 23 additions & 1 deletion toot/tui/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,29 @@
('yellow_bold', 'yellow,bold', ''),
('red', 'dark red', ''),
('warning', 'light red', ''),
('white_bold', 'white,bold', '')
('white_bold', 'white,bold', ''),

# HTML tag styling
('a', ',italics', ''),
# em tag is mapped to i
('i', ',italics', ''),
# strong tag is mapped to b
('b', ',bold', ''),
# special case for bold + italic nested tags
('bi', ',bold,italics', ''),
('u', ',underline', ''),
('del', ',strikethrough', ''),
('code', 'light gray, standout', ''),
('pre', 'light gray, standout', ''),
('blockquote', 'light gray', ''),
('h1', ',bold', ''),
('h2', ',bold', ''),
('h3', ',bold', ''),
('h4', ',bold', ''),
('h5', ',bold', ''),
('h6', ',bold', ''),
('class_mention_hashtag', 'light cyan,bold', ''),
('class_hashtag', 'light cyan,bold', ''),
]

VISIBILITY_OPTIONS = [
Expand Down
21 changes: 14 additions & 7 deletions toot/tui/overlays.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import webbrowser

from toot import __version__
from toot.utils import format_content
from .utils import highlight_hashtags, highlight_keys
from .widgets import Button, EditBox, SelectableText
from toot import api
from .utils import highlight_keys
from .widgets import Button, EditBox, SelectableText
from .richtext import ContentParser


class StatusSource(urwid.Padding):
Expand Down Expand Up @@ -255,6 +255,8 @@ def setup_listbox(self):
super().__init__(walker)

def generate_contents(self, account, relationship=None, last_action=None):
parser = ContentParser()

if self.last_action and not self.last_action.startswith("Confirm"):
yield Button(f"Confirm {self.last_action}", on_press=take_action, user_data=self)
yield Button("Cancel", on_press=cancel_action, user_data=self)
Expand All @@ -279,8 +281,10 @@ def generate_contents(self, account, relationship=None, last_action=None):

if account["note"]:
yield urwid.Divider()
for line in format_content(account["note"]):
yield urwid.Text(highlight_hashtags(line, followed_tags=set()))

widgetlist = parser.html_to_widgets(account["note"])
for line in widgetlist:
yield (line)

yield urwid.Divider()
yield urwid.Text(["ID: ", ("green", f"{account['id']}")])
Expand Down Expand Up @@ -312,8 +316,11 @@ def generate_contents(self, account, relationship=None, last_action=None):
name = field["name"].title()
yield urwid.Divider()
yield urwid.Text([("yellow", f"{name.rstrip(':')}"), ":"])
for line in format_content(field["value"]):
yield urwid.Text(highlight_hashtags(line, followed_tags=set()))

widgetlist = parser.html_to_widgets(field["value"])
for line in widgetlist:
yield (line)

if field["verified_at"]:
yield urwid.Text(("green", "✓ Verified"))

Expand Down
12 changes: 8 additions & 4 deletions toot/tui/poll.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from toot import api
from toot.exceptions import ApiError
from toot.utils import format_content
from .utils import highlight_hashtags, parse_datetime
from .utils import parse_datetime
from .widgets import Button, CheckBox, RadioButton
from .richtext import ContentParser


class Poll(urwid.ListBox):
Expand Down Expand Up @@ -85,8 +85,12 @@ def generate_poll_detail(self):

def generate_contents(self, status):
yield urwid.Divider()
for line in format_content(status.data["content"]):
yield urwid.Text(highlight_hashtags(line, set()))

parser = ContentParser()
widgetlist = parser.html_to_widgets(status.data["content"])

for line in widgetlist:
yield (line)

yield urwid.Divider()
yield self.build_linebox(self.generate_poll_detail())
Expand Down
Loading