diff --git a/src/mwparserfromhell/parser/builder.py b/src/mwparserfromhell/parser/builder.py index ab2cb9a..db4aa22 100644 --- a/src/mwparserfromhell/parser/builder.py +++ b/src/mwparserfromhell/parser/builder.py @@ -162,8 +162,14 @@ class Builder: self._push() elif isinstance(token, tokens.WikilinkClose): if title is not None: - return Wikilink(title, self._pop()) - return Wikilink(self._pop()) + wikilink = Wikilink(title, self._pop()) + else: + wikilink = Wikilink(self._pop()) + # MediaWiki treats [[]] and [[|...]] (empty title) as plain + # text rather than actual wikilinks. + if not str(wikilink.title): + return Text(str(wikilink)) + return wikilink else: self._write(self._handle_token(token)) raise ParserError("_handle_wikilink() missed a close token") diff --git a/tests/test_parser.py b/tests/test_parser.py index 8ec4a40..b8886e9 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -102,3 +102,24 @@ def test_skip_style_tags(pyparser): without_style = parser.Parser().parse(text, skip_style_tags=True) assert_wikicode_equal(a, with_style) assert_wikicode_equal(b, without_style) + + +@pytest.mark.parametrize( + "text", + [ + "[[]]", + "[[|]]", + "[[|foo]]", + "[[|||]]", + ], +) +def test_empty_title_wikilink_is_text(text): + """[[]] and [[|...]] have an empty title and should not be wikilinks. + + MediaWiki does not render these as hyperlinks; the parser must treat them + as plain text so that filter_wikilinks() does not return false positives. + Regression test for https://github.com/earwig/mwparserfromhell/issues/292. + """ + parsed = parser.Parser().parse(text) + assert parsed.filter_wikilinks() == [] + assert str(parsed) == text