@@ -63,6 +63,7 @@ def __init__(self, message: Message, model: "Model", last_message: Any) -> None:
6363 self .message_links : Dict [str , Tuple [str , int , bool ]] = dict ()
6464 self .topic_links : Dict [str , Tuple [str , int , bool ]] = dict ()
6565 self .time_mentions : List [Tuple [str , str ]] = list ()
66+ self .spoilers : List [Tuple [int , List [Any ], List [Any ]]] = list ()
6667 self .last_message = last_message
6768 # if this is the first message
6869 if self .last_message is None :
@@ -371,12 +372,22 @@ def footlinks_view(
371372 @classmethod
372373 def soup2markup (
373374 cls , soup : Any , metadata : Dict [str , Any ], ** state : Any
374- ) -> Tuple [List [Any ], Dict [str , Tuple [str , int , bool ]], List [Tuple [str , str ]]]:
375+ ) -> Tuple [
376+ List [Any ],
377+ Dict [str , Tuple [str , int , bool ]],
378+ List [Tuple [str , str ]],
379+ List [Tuple [int , List [Any ], List [Any ]]],
380+ ]:
375381 # Ensure a string is provided, in case the soup finds none
376382 # This could occur if eg. an image is removed or not shown
377383 markup : List [Union [str , Tuple [Optional [str ], Any ]]] = ["" ]
378384 if soup is None : # This is not iterable, so return promptly
379- return markup , metadata ["message_links" ], metadata ["time_mentions" ]
385+ return (
386+ markup ,
387+ metadata ["message_links" ],
388+ metadata ["time_mentions" ],
389+ metadata ["spoilers" ],
390+ )
380391 unrendered_tags = { # In pairs of 'tag_name': 'text'
381392 # TODO: Some of these could be implemented
382393 "br" : "" , # No indicator of absence
@@ -647,6 +658,10 @@ def soup2markup(
647658 part [1 ] if isinstance (part , tuple ) else part
648659 for part in processed_header
649660 )
661+ header_len = sum (
662+ len (part [1 ]) if isinstance (part , tuple ) else len (part )
663+ for part in processed_header
664+ )
650665
651666 # Limit to the first 10 characters and append "..."
652667 if len (processed_header_text ) > 10 :
@@ -671,9 +686,33 @@ def soup2markup(
671686 ]
672687 )
673688 markup .extend (bottom_border )
689+ # Spoiler content
690+ content = element .find (class_ = "spoiler-content" )
691+
692+ # Remove surrounding newlines.
693+ content_contents = content .contents
694+ if len (content_contents ) > 2 :
695+ if content_contents [- 1 ] == "\n " :
696+ content .contents .pop (- 1 )
697+ if content_contents [0 ] == "\n " :
698+ content .contents .pop (0 )
699+ if len (content_contents ) == 1 and content_contents [0 ] == "\n " :
700+ content .contents .pop (0 )
701+
702+ # FIXME: Do not soup2markup content in the MessageBox as it
703+ # will render 'sensitive' spoiler anchor tags in the footlinks.
704+ processed_content = cls .soup2markup (content , metadata )[0 ]
705+ metadata ["spoilers" ].append (
706+ (header_len , processed_header , processed_content )
707+ )
674708 else :
675709 markup .extend (cls .soup2markup (element , metadata )[0 ])
676- return markup , metadata ["message_links" ], metadata ["time_mentions" ]
710+ return (
711+ markup ,
712+ metadata ["message_links" ],
713+ metadata ["time_mentions" ],
714+ metadata ["spoilers" ],
715+ )
677716
678717 def main_view (self ) -> List [Any ]:
679718 # Recipient Header
@@ -769,9 +808,12 @@ def main_view(self) -> List[Any]:
769808 )
770809
771810 # Transform raw message content into markup (As needed by urwid.Text)
772- content , self .message_links , self .time_mentions = self .transform_content (
773- self .message ["content" ], self .model .server_url
774- )
811+ (
812+ content ,
813+ self .message_links ,
814+ self .time_mentions ,
815+ self .spoilers ,
816+ ) = self .transform_content (self .message ["content" ], self .model .server_url )
775817 self .content .set_text (content )
776818
777819 if self .message ["id" ] in self .model .index ["edited_messages" ]:
@@ -858,6 +900,7 @@ def transform_content(
858900 Tuple [None , Any ],
859901 Dict [str , Tuple [str , int , bool ]],
860902 List [Tuple [str , str ]],
903+ List [Tuple [int , List [Any ], List [Any ]]],
861904 ]:
862905 soup = BeautifulSoup (content , "lxml" )
863906 body = soup .find (name = "body" )
@@ -866,13 +909,14 @@ def transform_content(
866909 server_url = server_url ,
867910 message_links = dict (),
868911 time_mentions = list (),
912+ spoilers = list (),
869913 ) # type: Dict[str, Any]
870914
871915 if isinstance (body , Tag ) and body .find (name = "blockquote" ):
872916 metadata ["bq_len" ] = cls .indent_quoted_content (soup , QUOTED_TEXT_MARKER )
873917
874- markup , message_links , time_mentions = cls .soup2markup (body , metadata )
875- return (None , markup ), message_links , time_mentions
918+ markup , message_links , time_mentions , spoilers = cls .soup2markup (body , metadata )
919+ return (None , markup ), message_links , time_mentions , spoilers
876920
877921 @staticmethod
878922 def indent_quoted_content (soup : Any , padding_char : str ) -> int :
0 commit comments