Skip to content

Commit cb9d185

Browse files
gnpricePIG208
authored andcommitted
content [nfc]: Split out _ZulipInlineContentParser class
This helps organize the parsing code a bit more cleanly -- not to mention more statically, by making the dynamic _debugParserContext assertions redundant.
1 parent 7d0c0e4 commit cb9d185

File tree

1 file changed

+25
-43
lines changed

1 file changed

+25
-43
lines changed

lib/model/content.dart

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ class MathInlineNode extends InlineContentNode {
786786
class GlobalTimeNode extends InlineContentNode {
787787
const GlobalTimeNode({super.debugHtmlNode, required this.datetime});
788788

789-
/// Always in UTC, enforced in [_ZulipContentParser.parseInlineContent].
789+
/// Always in UTC, enforced in [_ZulipInlineContentParser.parseInlineContent].
790790
final DateTime datetime;
791791

792792
@override
@@ -852,32 +852,19 @@ String? _parseMath(dom.Element element, {required bool block}) {
852852
return descendant4.text.trim();
853853
}
854854

855-
/// What sort of nodes a [_ZulipContentParser] is currently expecting to find.
856-
enum _ParserContext {
857-
/// The parser is currently looking for block nodes.
858-
block,
859-
860-
/// The parser is currently looking for inline nodes.
861-
inline,
862-
}
863-
864-
/// Parser for a complete piece of Zulip HTML content, a [ZulipContent].
855+
/// Parser for the inline-content subtrees within Zulip content HTML.
865856
///
866-
/// The only entry point to this class is [parse].
867-
class _ZulipContentParser {
868-
/// The current state of what sort of nodes the parser is looking for.
869-
///
870-
/// This exists for the sake of debug-mode checks,
871-
/// and should be read or updated only inside an assertion.
872-
_ParserContext _debugParserContext = _ParserContext.block;
873-
857+
/// The only entry point to this class is [parseBlockInline].
858+
///
859+
/// After a call to [parseBlockInline] returns, the [_ZulipInlineContentParser]
860+
/// instance has been reset to its starting state, and can be re-used for
861+
/// parsing other subtrees.
862+
class _ZulipInlineContentParser {
874863
String? parseInlineMath(dom.Element element) {
875-
assert(_debugParserContext == _ParserContext.inline);
876864
return _parseMath(element, block: false);
877865
}
878866

879867
UserMentionNode? parseUserMention(dom.Element element) {
880-
assert(_debugParserContext == _ParserContext.inline);
881868
assert(element.localName == 'span');
882869
final debugHtmlNode = kDebugMode ? element : null;
883870

@@ -951,7 +938,6 @@ class _ZulipContentParser {
951938
static final _emojiCodeFromClassNameRegexp = RegExp(r"emoji-([^ ]+)");
952939

953940
InlineContentNode parseInlineContent(dom.Node node) {
954-
assert(_debugParserContext == _ParserContext.inline);
955941
final debugHtmlNode = kDebugMode ? node : null;
956942
InlineContentNode unimplemented() => UnimplementedInlineContentNode(htmlNode: node);
957943

@@ -1041,33 +1027,38 @@ class _ZulipContentParser {
10411027
}
10421028

10431029
List<InlineContentNode> parseInlineContentList(List<dom.Node> nodes) {
1044-
assert(_debugParserContext == _ParserContext.inline);
10451030
return nodes.map(parseInlineContent).toList(growable: false);
10461031
}
10471032

10481033
/// Parse the children of a [BlockInlineContainerNode], making up a
10491034
/// complete subtree of inline content with no further inline ancestors.
10501035
({List<InlineContentNode> nodes, List<LinkNode>? links}) parseBlockInline(List<dom.Node> nodes) {
1051-
assert(_debugParserContext == _ParserContext.block);
1052-
assert(() {
1053-
_debugParserContext = _ParserContext.inline;
1054-
return true;
1055-
}());
10561036
final resultNodes = parseInlineContentList(nodes);
1057-
assert(() {
1058-
_debugParserContext = _ParserContext.block;
1059-
return true;
1060-
}());
10611037
return (nodes: resultNodes, links: _takeLinkNodes());
10621038
}
1039+
}
1040+
1041+
/// Parser for a complete piece of Zulip HTML content, a [ZulipContent].
1042+
///
1043+
/// The only entry point to this class is [parse].
1044+
class _ZulipContentParser {
1045+
/// The single inline-content parser used and re-used throughout parsing of
1046+
/// a complete piece of Zulip HTML content.
1047+
///
1048+
/// Because block content can never appear nested inside inline content,
1049+
/// there's never a need for more than one of these at a time,
1050+
/// so we can allocate just one up front.
1051+
final inlineParser = _ZulipInlineContentParser();
1052+
1053+
({List<InlineContentNode> nodes, List<LinkNode>? links}) parseBlockInline(List<dom.Node> nodes) {
1054+
return inlineParser.parseBlockInline(nodes);
1055+
}
10631056

10641057
String? parseMathBlock(dom.Element element) {
1065-
assert(_debugParserContext == _ParserContext.block);
10661058
return _parseMath(element, block: true);
10671059
}
10681060

10691061
BlockContentNode parseListNode(dom.Element element) {
1070-
assert(_debugParserContext == _ParserContext.block);
10711062
ListStyle? listStyle;
10721063
switch (element.localName) {
10731064
case 'ol': listStyle = ListStyle.ordered; break;
@@ -1090,7 +1081,6 @@ class _ZulipContentParser {
10901081
}
10911082

10921083
BlockContentNode parseSpoilerNode(dom.Element divElement) {
1093-
assert(_debugParserContext == _ParserContext.block);
10941084
assert(divElement.localName == 'div'
10951085
&& divElement.className == 'spoiler-block');
10961086

@@ -1110,7 +1100,6 @@ class _ZulipContentParser {
11101100
}
11111101

11121102
BlockContentNode parseCodeBlock(dom.Element divElement) {
1113-
assert(_debugParserContext == _ParserContext.block);
11141103
final mainElement = () {
11151104
assert(divElement.localName == 'div'
11161105
&& divElement.className == "codehilite");
@@ -1193,7 +1182,6 @@ class _ZulipContentParser {
11931182
static final _imageDimensionsRegExp = RegExp(r'^(\d+)x(\d+)$');
11941183

11951184
BlockContentNode parseImageNode(dom.Element divElement) {
1196-
assert(_debugParserContext == _ParserContext.block);
11971185
final elements = () {
11981186
assert(divElement.localName == 'div'
11991187
&& divElement.className == 'message_inline_image');
@@ -1285,7 +1273,6 @@ class _ZulipContentParser {
12851273
}();
12861274

12871275
BlockContentNode parseInlineVideoNode(dom.Element divElement) {
1288-
assert(_debugParserContext == _ParserContext.block);
12891276
assert(divElement.localName == 'div'
12901277
&& _videoClassNameRegexp.hasMatch(divElement.className));
12911278

@@ -1318,7 +1305,6 @@ class _ZulipContentParser {
13181305
}
13191306

13201307
BlockContentNode parseEmbedVideoNode(dom.Element divElement) {
1321-
assert(_debugParserContext == _ParserContext.block);
13221308
assert(divElement.localName == 'div'
13231309
&& _videoClassNameRegexp.hasMatch(divElement.className));
13241310

@@ -1357,7 +1343,6 @@ class _ZulipContentParser {
13571343
}
13581344

13591345
BlockContentNode parseTableContent(dom.Element tableElement) {
1360-
assert(_debugParserContext == _ParserContext.block);
13611346
assert(tableElement.localName == 'table'
13621347
&& tableElement.className.isEmpty);
13631348

@@ -1465,7 +1450,6 @@ class _ZulipContentParser {
14651450
}
14661451

14671452
BlockContentNode parseBlockContent(dom.Node node) {
1468-
assert(_debugParserContext == _ParserContext.block);
14691453
final debugHtmlNode = kDebugMode ? node : null;
14701454
if (node is! dom.Element) {
14711455
return UnimplementedBlockContentNode(htmlNode: node);
@@ -1592,7 +1576,6 @@ class _ZulipContentParser {
15921576
///
15931577
/// See [ParagraphNode].
15941578
List<BlockContentNode> parseImplicitParagraphBlockContentList(dom.NodeList nodes) {
1595-
assert(_debugParserContext == _ParserContext.block);
15961579
final List<BlockContentNode> result = [];
15971580
final List<dom.Node> currentParagraph = [];
15981581
List<ImageNode> imageNodes = [];
@@ -1641,7 +1624,6 @@ class _ZulipContentParser {
16411624
static final _redundantLineBreaksRegexp = RegExp(r'^\n+$');
16421625

16431626
List<BlockContentNode> parseBlockContentList(dom.NodeList nodes) {
1644-
assert(_debugParserContext == _ParserContext.block);
16451627
final List<BlockContentNode> result = [];
16461628
List<ImageNode> imageNodes = [];
16471629
for (final node in nodes) {

0 commit comments

Comments
 (0)