diff --git a/lib/model/content.dart b/lib/model/content.dart index 99f18efde9..1a919d942d 100644 --- a/lib/model/content.dart +++ b/lib/model/content.dart @@ -1023,9 +1023,17 @@ class _ZulipContentParser { span = CodeBlockSpanNode(text: text, type: CodeBlockSpanType.text); case dom.Element(localName: 'span', :final text, :final className): - final CodeBlockSpanType type = codeBlockSpanTypeFromClassName(className); - switch (type) { - case CodeBlockSpanType.unknown: + // Empirically, when a Pygments node has multiple classes, the first + // class names a standard token type and the rest are for non-standard + // token types specific to the language. Zulip web only styles the + // standard token classes and ignores the others, so we do the same. + // See: https://github.com/zulip/zulip-flutter/issues/933 + final spanType = className.split(' ') + .map(codeBlockSpanTypeFromClassName) + .firstWhereOrNull((e) => e != CodeBlockSpanType.unknown); + + switch (spanType) { + case null: // TODO(#194): Show these as un-syntax-highlighted code, in production. return UnimplementedBlockContentNode(htmlNode: divElement); case CodeBlockSpanType.highlightedLines: @@ -1033,7 +1041,7 @@ class _ZulipContentParser { // inherited styles for `span.hll` nodes. return UnimplementedBlockContentNode(htmlNode: divElement); default: - span = CodeBlockSpanNode(text: text, type: type); + span = CodeBlockSpanNode(text: text, type: spanType); } default: diff --git a/test/model/content_test.dart b/test/model/content_test.dart index 4aef38d5cc..d06d414916 100644 --- a/test/model/content_test.dart +++ b/test/model/content_test.dart @@ -344,6 +344,23 @@ class ContentExample { ]), ]); + static const codeBlockSpansWithMultipleClasses = ContentExample( + 'code block spans with multiple CSS classes', + '```yaml\n- item\n```', + expectedText: '- item', + // https://chat.zulip.org/#narrow/channel/7-test-here/topic/Greg/near/1949014 + '
' + '
-'
+        ' '
+        'item\n'
+        '
', [ + CodeBlockNode([ + CodeBlockSpanNode(text: "-", type: CodeBlockSpanType.punctuation), + CodeBlockSpanNode(text: " ", type: CodeBlockSpanType.whitespace), + CodeBlockSpanNode(text: "item", type: CodeBlockSpanType.literal) + ]), + ]); + // Current servers no longer produce this, but it can be found in ancient // messages. For example: // https://chat.zulip.org/#narrow/stream/2-general/topic/Error.20in.20dev.20server/near/18765 @@ -1160,6 +1177,7 @@ void main() { testParseExample(ContentExample.codeBlockPlain); testParseExample(ContentExample.codeBlockHighlightedShort); testParseExample(ContentExample.codeBlockHighlightedMultiline); + testParseExample(ContentExample.codeBlockSpansWithMultipleClasses); testParseExample(ContentExample.codeBlockWithEmptyBody); testParseExample(ContentExample.codeBlockWithHighlightedLines); testParseExample(ContentExample.codeBlockWithUnknownSpanType); diff --git a/test/widgets/content_test.dart b/test/widgets/content_test.dart index 76fecc0f10..df40fa47d2 100644 --- a/test/widgets/content_test.dart +++ b/test/widgets/content_test.dart @@ -480,6 +480,7 @@ void main() { testContentSmoke(ContentExample.codeBlockPlain); testContentSmoke(ContentExample.codeBlockHighlightedShort); testContentSmoke(ContentExample.codeBlockHighlightedMultiline); + testContentSmoke(ContentExample.codeBlockSpansWithMultipleClasses); testFontWeight('syntax highlighting: non-bold span', expectedWght: 400,