File tree Expand file tree Collapse file tree 4 files changed +42
-18
lines changed Expand file tree Collapse file tree 4 files changed +42
-18
lines changed Original file line number Diff line number Diff line change @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
1818- Added experimental opt-in support for https://github.com/willmcgugan/textual-speedups
1919
20+ ### Changed
21+
22+ - Content markup is now more lenient; if a 'tag' doesn't contain a valid style it will be included verbatim. https://github.com/Textualize/textual/pull/5851
23+
2024## [ 3.3.0] - 2025-06-01
2125
2226### Fixed
Original file line number Diff line number Diff line change @@ -48,8 +48,9 @@ class MarkupError(Exception):
4848 variable_ref = VARIABLE_REF ,
4949 whitespace = r"\s+" ,
5050 )
51- .expect_eof (False )
51+ .expect_eof (True )
5252 .expect_semicolon (False )
53+ .extract_text (True )
5354)
5455
5556expect_markup = Expect (
@@ -374,14 +375,36 @@ def process_text(template_text: str, /) -> str:
374375 elif token_name == "open_tag" :
375376 tag_text = []
376377
378+ eof = False
379+ contains_text = False
377380 for token in iter_tokens :
378381 if token .name == "end_tag" :
379382 break
383+ elif token .name == "text" :
384+ contains_text = True
385+ elif token .name == "eof" :
386+ eof = True
380387 tag_text .append (token .value )
381- opening_tag = "" .join (tag_text ).strip ()
382- style_stack .append (
383- (position , opening_tag , normalize_markup_tag (opening_tag ))
384- )
388+ if contains_text or eof :
389+ # "tag" was unparsable
390+ text_content = f"[{ '' .join (tag_text )} " + ("" if eof else "]" )
391+ text_append (text_content )
392+ position += len (text_content )
393+ else :
394+ opening_tag = "" .join (tag_text )
395+
396+ if not opening_tag .strip ():
397+ blank_tag = f"[{ opening_tag } ]"
398+ text_append (blank_tag )
399+ position += len (blank_tag )
400+ else :
401+ style_stack .append (
402+ (
403+ position ,
404+ opening_tag ,
405+ normalize_markup_tag (opening_tag .strip ()),
406+ )
407+ )
385408
386409 elif token_name == "open_closing_tag" :
387410 tag_text = []
Original file line number Diff line number Diff line change @@ -229,6 +229,7 @@ def test_assemble():
229229 ("\\ [/foo" , "[/foo" ),
230230 ("\\ [/foo]" , "[/foo]" ),
231231 ("\\ []" , "[]" ),
232+ ("\\ [0]" , "[0]" ),
232233 ],
233234)
234235def test_escape (markup : str , plain : str ) -> None :
@@ -273,14 +274,3 @@ def test_first_line():
273274 first_line = content .first_line
274275 assert first_line .plain == "foo"
275276 assert first_line .spans == [Span (0 , 3 , "red" )]
276-
277-
278- def test_errors ():
279- with pytest .raises (Exception ):
280- Content .from_markup ("[" )
281-
282- with pytest .raises (Exception ):
283- Content .from_markup ("[:" )
284-
285- with pytest .raises (Exception ):
286- Content .from_markup ("[foo" )
Original file line number Diff line number Diff line change 1010 ["markup" , "content" ],
1111 [
1212 ("" , Content ("" )),
13+ ("[" , Content ("[" )),
14+ ("[]" , Content ("[]" )),
15+ ("[ " , Content ("[ " )),
16+ ("[ " , Content ("[ " )),
17+ ("[ ]" , Content ("[ ]" )),
18+ ("[0" , Content ("[0" )),
19+ ("[0]" , Content ("[0]" )),
20+ ("[red" , Content ("[red" )),
21+ ("[red]" , Content ("" )),
1322 ("foo" , Content ("foo" )),
1423 ("foo\n " , Content ("foo\n " )),
1524 ("foo\n bar" , Content ("foo\n bar" )),
@@ -152,8 +161,6 @@ def test_to_content(markup: str, content: Content):
152161
153162
154163def test_content_parse_fail () -> None :
155- with pytest .raises (MarkupError ):
156- to_content ("[rgb(1,2,3,4)]foo" )
157164 with pytest .raises (MarkupError ):
158165 to_content ("[foo]foo[/bar]" )
159166 with pytest .raises (MarkupError ):
You can’t perform that action at this time.
0 commit comments