Skip to content

markup.escape() doesn't escape an outer tag when it contains a nested "[" #6614

Description

@le-codeur-rapide

Hello ! I think that I found a bug in the markup.escape function.

The bug

textual.markup.escape is documented as escaping text "so that it won't be interpreted as markup", but it leaves an outer [ unescaped when the bracketed region contains a nested [ before its closing ]. The "escaped" string then raises MarkupError when passed to to_content / Content.from_markup.

Real-world trigger: machine-generated strings like Pydantic v2 validation errors, e.g.
[type=value_error, input_value={'questions[0].header': ...}, input_type=dict].

MRE (Textual 8.2.7)

from textual.markup import escape, to_content

s = "[type=x, v={'a[0]'}]"   # nested '[' inside an outer '[...]'
e = escape(s)
print(e == s)                # True  -> escape did nothing
to_content(e)                # MarkupError: Expected markup value (found "={'a[0]'}]").

Cause
The escape pattern (\*)([[a-z#/@][^[]*?]) requires the tag-like segment to close with ] and forbids any [ in between ([^[]). An outer bracket containing a nested [ never matches, so it isn't escaped.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions