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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions