diff --git a/lib/model/content.dart b/lib/model/content.dart index f27753327c..c22970a1aa 100644 --- a/lib/model/content.dart +++ b/lib/model/content.dart @@ -927,11 +927,10 @@ class _ZulipContentParser { case 'h5': headingLevel = HeadingLevel.h5; break; case 'h6': headingLevel = HeadingLevel.h6; break; } - if (headingLevel == HeadingLevel.h6 && classes.isEmpty) { - // TODO(#192) handle h1, h2, h3, h4, h5 + if (headingLevel != null && classes.isEmpty) { final parsed = parseBlockInline(element.nodes); return HeadingNode(debugHtmlNode: debugHtmlNode, - level: headingLevel!, + level: headingLevel, links: parsed.links, nodes: parsed.nodes); } diff --git a/lib/widgets/content.dart b/lib/widgets/content.dart index 3b83e21131..1954b3931f 100644 --- a/lib/widgets/content.dart +++ b/lib/widgets/content.dart @@ -136,12 +136,22 @@ class Heading extends StatelessWidget { @override Widget build(BuildContext context) { - // TODO(#192) h1, h2, h3, h4, h5 -- same as h6 except font size - assert(node.level == HeadingLevel.h6); + // Em-heights taken from zulip:web/styles/rendered_markdown.css . + final emHeight = switch(node.level) { + HeadingLevel.h1 => 1.4, + HeadingLevel.h2 => 1.3, + HeadingLevel.h3 => 1.2, + HeadingLevel.h4 => 1.1, + HeadingLevel.h5 => 1.05, + HeadingLevel.h6 => 1.0, + }; return Padding( padding: const EdgeInsets.only(top: 15, bottom: 5), child: _buildBlockInlineContainer( - style: const TextStyle(fontWeight: FontWeight.w600, height: 1.4), + style: TextStyle( + fontSize: kBaseFontSize * emHeight, + fontWeight: FontWeight.w600, + height: 1.4), node: node)); } } diff --git a/test/model/content_test.dart b/test/model/content_test.dart index e0ed1dc61c..87c6c182e6 100644 --- a/test/model/content_test.dart +++ b/test/model/content_test.dart @@ -219,14 +219,14 @@ void main() { ParagraphNode(links: null, nodes: [TextNode('text')]), ]); - testParse('h1, h2, h3, h4, h5 unimplemented', + testParse('h1, h2, h3, h4, h5', // "# one\n## two\n### three\n#### four\n##### five" - '

one

\n

two

\n

three

\n

four

\n
five
', [ - blockUnimplemented('

one

'), - blockUnimplemented('

two

'), - blockUnimplemented('

three

'), - blockUnimplemented('

four

'), - blockUnimplemented('
five
'), + '

one

\n

two

\n

three

\n

four

\n
five
', const [ + HeadingNode(level: HeadingLevel.h1, links: null, nodes: [TextNode('one')]), + HeadingNode(level: HeadingLevel.h2, links: null, nodes: [TextNode('two')]), + HeadingNode(level: HeadingLevel.h3, links: null, nodes: [TextNode('three')]), + HeadingNode(level: HeadingLevel.h4, links: null, nodes: [TextNode('four')]), + HeadingNode(level: HeadingLevel.h5, links: null, nodes: [TextNode('five')]), ]); }); diff --git a/test/widgets/content_test.dart b/test/widgets/content_test.dart index 82bc600c2c..21f23b967c 100644 --- a/test/widgets/content_test.dart +++ b/test/widgets/content_test.dart @@ -24,6 +24,26 @@ import 'page_checks.dart'; void main() { TestZulipBinding.ensureInitialized(); + group('Heading', () { + Future prepareContent(WidgetTester tester, String html) async { + await tester.pumpWidget(MaterialApp(home: BlockContentList(nodes: parseContent(html).nodes))); + } + + testWidgets('plain h6', (tester) async { + await prepareContent(tester, + // "###### six" + '
six
'); + tester.widget(find.text('six')); + }); + + testWidgets('smoke test for h1, h2, h3, h4, h5', (tester) async { + await prepareContent(tester, + // "# one\n## two\n### three\n#### four\n##### five" + '

one

\n

two

\n

three

\n

four

\n
five
'); + check(find.byType(Heading).evaluate()).length.equals(5); + }); + }); + group("CodeBlock", () { Future prepareContent(WidgetTester tester, String html) async { await tester.pumpWidget(MaterialApp(home: BlockContentList(nodes: parseContent(html).nodes)));