fix: Correctly parse the reason of a spoiler

Previously only the first child node of a spoiler was considered to
determine if there should be a spoiler reason. This was, unfortunately,
incorrect, as soon as e.g. the reason had more than one space. This is
fixed by properly iterating all child nodes to search for the reason.
This commit is contained in:
Sorunome 2021-08-16 17:37:19 +02:00 committed by Krille Fear
parent 37cfadd7e9
commit fb16b96ea6
2 changed files with 30 additions and 10 deletions

View File

@ -37,21 +37,35 @@ class SpoilerSyntax extends TagSyntax {
@override @override
Node close(InlineParser parser, Delimiter opener, Delimiter closer, Node close(InlineParser parser, Delimiter opener, Delimiter closer,
{List<Node> Function() getChildren}) { {List<Node> Function() getChildren}) {
var reason = '';
final children = getChildren(); final children = getChildren();
if (children.isNotEmpty) { final newChildren = <Node>[];
final te = children[0]; var searchingForReason = true;
if (te is Text) { var reason = '';
final tx = te.text; for (final child in children) {
final ix = tx.indexOf('|'); // If we already found a reason, let's just use our child nodes as-is
if (!searchingForReason) {
newChildren.add(child);
continue;
}
if (child is Text) {
final ix = child.text.indexOf('|');
if (ix > 0) { if (ix > 0) {
reason = tx.substring(0, ix); reason += child.text.substring(0, ix);
children[0] = Text(tx.substring(ix + 1)); newChildren.add(Text(child.text.substring(ix + 1)));
searchingForReason = false;
} else {
reason += child.text;
}
} else {
// if we don't have a text node as reason we just want to cancel this whole thing
break;
} }
} }
} // if we were still searching for a reason that means there was none - use the original children!
final element = Element('span', children); final element =
element.attributes['data-mx-spoiler'] = htmlAttrEscape.convert(reason); Element('span', searchingForReason ? children : newChildren);
element.attributes['data-mx-spoiler'] =
searchingForReason ? '' : htmlAttrEscape.convert(reason);
return element; return element;
} }
} }

View File

@ -49,6 +49,12 @@ void main() {
'Snape killed <span data-mx-spoiler="">Dumbledoor</span>'); 'Snape killed <span data-mx-spoiler="">Dumbledoor</span>');
expect(markdown('Snape killed ||Story|Dumbledoor||'), expect(markdown('Snape killed ||Story|Dumbledoor||'),
'Snape killed <span data-mx-spoiler="Story">Dumbledoor</span>'); 'Snape killed <span data-mx-spoiler="Story">Dumbledoor</span>');
expect(markdown('Snape killed ||Some dumb loser|Dumbledoor||'),
'Snape killed <span data-mx-spoiler="Some dumb loser">Dumbledoor</span>');
expect(markdown('Snape killed ||Some dumb loser|Dumbledoor **bold**||'),
'Snape killed <span data-mx-spoiler="Some dumb loser">Dumbledoor <strong>bold</strong></span>');
expect(markdown('Snape killed ||Dumbledoor **bold**||'),
'Snape killed <span data-mx-spoiler="">Dumbledoor <strong>bold</strong></span>');
}); });
test('multiple paragraphs', () { test('multiple paragraphs', () {
expect(markdown('Heya!\n\nBeep'), '<p>Heya!</p>\n<p>Beep</p>'); expect(markdown('Heya!\n\nBeep'), '<p>Heya!</p>\n<p>Beep</p>');