Skip to content

Commit 1fe817c

Browse files
rajveermalviyagnprice
authored andcommitted
content: Handle positive margin-right and margin-left in KaTeX spans
1 parent 85f4ecf commit 1fe817c

File tree

4 files changed

+122
-3
lines changed

4 files changed

+122
-3
lines changed

lib/model/katex.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,8 @@ class _KatexParser {
492492
if (stylesheet.topLevels case [css_visitor.RuleSet() && final rule]) {
493493
double? heightEm;
494494
double? verticalAlignEm;
495+
double? marginRightEm;
496+
double? marginLeftEm;
495497

496498
for (final declaration in rule.declarationGroup.declarations) {
497499
if (declaration case css_visitor.Declaration(
@@ -507,6 +509,20 @@ class _KatexParser {
507509
case 'vertical-align':
508510
verticalAlignEm = _getEm(expression);
509511
if (verticalAlignEm != null) continue;
512+
513+
case 'margin-right':
514+
marginRightEm = _getEm(expression);
515+
if (marginRightEm != null) {
516+
if (marginRightEm < 0) throw _KatexHtmlParseError();
517+
continue;
518+
}
519+
520+
case 'margin-left':
521+
marginLeftEm = _getEm(expression);
522+
if (marginLeftEm != null) {
523+
if (marginLeftEm < 0) throw _KatexHtmlParseError();
524+
continue;
525+
}
510526
}
511527

512528
// TODO handle more CSS properties
@@ -522,6 +538,8 @@ class _KatexParser {
522538
return KatexSpanStyles(
523539
heightEm: heightEm,
524540
verticalAlignEm: verticalAlignEm,
541+
marginRightEm: marginRightEm,
542+
marginLeftEm: marginLeftEm,
525543
);
526544
} else {
527545
throw _KatexHtmlParseError();
@@ -560,6 +578,9 @@ class KatexSpanStyles {
560578
final double? heightEm;
561579
final double? verticalAlignEm;
562580

581+
final double? marginRightEm;
582+
final double? marginLeftEm;
583+
563584
final String? fontFamily;
564585
final double? fontSizeEm;
565586
final KatexSpanFontWeight? fontWeight;
@@ -569,6 +590,8 @@ class KatexSpanStyles {
569590
const KatexSpanStyles({
570591
this.heightEm,
571592
this.verticalAlignEm,
593+
this.marginRightEm,
594+
this.marginLeftEm,
572595
this.fontFamily,
573596
this.fontSizeEm,
574597
this.fontWeight,
@@ -581,6 +604,8 @@ class KatexSpanStyles {
581604
'KatexSpanStyles',
582605
heightEm,
583606
verticalAlignEm,
607+
marginRightEm,
608+
marginLeftEm,
584609
fontFamily,
585610
fontSizeEm,
586611
fontWeight,
@@ -593,6 +618,8 @@ class KatexSpanStyles {
593618
return other is KatexSpanStyles &&
594619
other.heightEm == heightEm &&
595620
other.verticalAlignEm == verticalAlignEm &&
621+
other.marginRightEm == marginRightEm &&
622+
other.marginLeftEm == marginLeftEm &&
596623
other.fontFamily == fontFamily &&
597624
other.fontSizeEm == fontSizeEm &&
598625
other.fontWeight == fontWeight &&
@@ -605,6 +632,8 @@ class KatexSpanStyles {
605632
final args = <String>[];
606633
if (heightEm != null) args.add('heightEm: $heightEm');
607634
if (verticalAlignEm != null) args.add('verticalAlignEm: $verticalAlignEm');
635+
if (marginRightEm != null) args.add('marginRightEm: $marginRightEm');
636+
if (marginLeftEm != null) args.add('marginLeftEm: $marginLeftEm');
608637
if (fontFamily != null) args.add('fontFamily: $fontFamily');
609638
if (fontSizeEm != null) args.add('fontSizeEm: $fontSizeEm');
610639
if (fontWeight != null) args.add('fontWeight: $fontWeight');
@@ -624,6 +653,8 @@ class KatexSpanStyles {
624653
return KatexSpanStyles(
625654
heightEm: other.heightEm ?? heightEm,
626655
verticalAlignEm: other.verticalAlignEm ?? verticalAlignEm,
656+
marginRightEm: other.marginRightEm ?? marginRightEm,
657+
marginLeftEm: other.marginLeftEm ?? marginLeftEm,
627658
fontFamily: other.fontFamily ?? fontFamily,
628659
fontSizeEm: other.fontSizeEm ?? fontSizeEm,
629660
fontStyle: other.fontStyle ?? fontStyle,
@@ -635,6 +666,8 @@ class KatexSpanStyles {
635666
KatexSpanStyles filter({
636667
bool heightEm = true,
637668
bool verticalAlignEm = true,
669+
bool marginRightEm = true,
670+
bool marginLeftEm = true,
638671
bool fontFamily = true,
639672
bool fontSizeEm = true,
640673
bool fontWeight = true,
@@ -644,6 +677,8 @@ class KatexSpanStyles {
644677
return KatexSpanStyles(
645678
heightEm: heightEm ? this.heightEm : null,
646679
verticalAlignEm: verticalAlignEm ? this.verticalAlignEm : null,
680+
marginRightEm: marginRightEm ? this.marginRightEm : null,
681+
marginLeftEm: marginLeftEm ? this.marginLeftEm : null,
647682
fontFamily: fontFamily ? this.fontFamily : null,
648683
fontSizeEm: fontSizeEm ? this.fontSizeEm : null,
649684
fontWeight: fontWeight ? this.fontWeight : null,

lib/widgets/content.dart

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ class _KatexSpan extends StatelessWidget {
909909

910910
@override
911911
Widget build(BuildContext context) {
912-
final em = DefaultTextStyle.of(context).style.fontSize!;
912+
var em = DefaultTextStyle.of(context).style.fontSize!;
913913

914914
Widget widget = const SizedBox.shrink();
915915
if (node.text != null) {
@@ -929,6 +929,8 @@ class _KatexSpan extends StatelessWidget {
929929
double fontSizeEm => fontSizeEm * em,
930930
null => null,
931931
};
932+
if (fontSize != null) em = fontSize;
933+
932934
final fontWeight = switch (styles.fontWeight) {
933935
KatexSpanFontWeight.bold => FontWeight.bold,
934936
null => null,
@@ -973,11 +975,28 @@ class _KatexSpan extends StatelessWidget {
973975
child: widget);
974976
}
975977

976-
return SizedBox(
978+
widget = SizedBox(
977979
height: styles.heightEm != null
978-
? styles.heightEm! * (fontSize ?? em)
980+
? styles.heightEm! * em
979981
: null,
980982
child: widget);
983+
984+
final margin = switch ((styles.marginLeftEm, styles.marginRightEm)) {
985+
(null, null) => null,
986+
(null, final marginRightEm?) =>
987+
EdgeInsets.only(right: marginRightEm * em),
988+
(final marginLeftEm?, null) =>
989+
EdgeInsets.only(left: marginLeftEm * em),
990+
(final marginLeftEm?, final marginRightEm?) =>
991+
EdgeInsets.only(left: marginLeftEm * em, right: marginRightEm * em),
992+
};
993+
994+
if (margin != null) {
995+
assert(margin.isNonNegative);
996+
widget = Padding(padding: margin, child: widget);
997+
}
998+
999+
return widget;
9811000
}
9821001
}
9831002

test/model/content_test.dart

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,65 @@ class ContentExample {
884884
]),
885885
]);
886886

887+
static const mathBlockKatexSpace = ContentExample(
888+
'math block; KaTeX space',
889+
// https://chat.zulip.org/#narrow/channel/7-test-here/topic/Rajesh/near/2214883
890+
'```math\n1:2\n```',
891+
'<p>'
892+
'<span class="katex-display"><span class="katex">'
893+
'<span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>1</mn><mo>:</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">1:2</annotation></semantics></math></span>'
894+
'<span class="katex-html" aria-hidden="true">'
895+
'<span class="base">'
896+
'<span class="strut" style="height:0.6444em;"></span>'
897+
'<span class="mord">1</span>'
898+
'<span class="mspace" style="margin-right:0.2778em;"></span>'
899+
'<span class="mrel">:</span>'
900+
'<span class="mspace" style="margin-right:0.2778em;"></span></span>'
901+
'<span class="base">'
902+
'<span class="strut" style="height:0.6444em;"></span>'
903+
'<span class="mord">2</span></span></span></span></span></p>', [
904+
MathBlockNode(
905+
texSource: '1:2',
906+
nodes: [
907+
KatexSpanNode(
908+
styles: KatexSpanStyles(),
909+
text: null,
910+
nodes: [
911+
KatexStrutNode(
912+
heightEm: 0.6444,
913+
verticalAlignEm: null),
914+
KatexSpanNode(
915+
styles: KatexSpanStyles(),
916+
text: '1',
917+
nodes: null),
918+
KatexSpanNode(
919+
styles: KatexSpanStyles(marginRightEm: 0.2778),
920+
text: null,
921+
nodes: []),
922+
KatexSpanNode(
923+
styles: KatexSpanStyles(),
924+
text: ':',
925+
nodes: null),
926+
KatexSpanNode(
927+
styles: KatexSpanStyles(marginRightEm: 0.2778),
928+
text: null,
929+
nodes: []),
930+
]),
931+
KatexSpanNode(
932+
styles: KatexSpanStyles(),
933+
text: null,
934+
nodes: [
935+
KatexStrutNode(
936+
heightEm: 0.6444,
937+
verticalAlignEm: null),
938+
KatexSpanNode(
939+
styles: KatexSpanStyles(),
940+
text: '2',
941+
nodes: null),
942+
]),
943+
]),
944+
]);
945+
887946
static const imageSingle = ContentExample(
888947
'single image',
889948
// https://chat.zulip.org/#narrow/stream/7-test-here/topic/Thumbnails/near/1900103
@@ -1973,6 +2032,7 @@ void main() async {
19732032
testParseExample(ContentExample.mathBlockKatexSizing);
19742033
testParseExample(ContentExample.mathBlockKatexNestedSizing);
19752034
testParseExample(ContentExample.mathBlockKatexDelimSizing);
2035+
testParseExample(ContentExample.mathBlockKatexSpace);
19762036

19772037
testParseExample(ContentExample.imageSingle);
19782038
testParseExample(ContentExample.imageSingleNoDimensions);

test/widgets/content_test.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,11 @@ void main() {
597597
('⌈', Offset(27.12, 20.14), Size(11.99, 25.00)),
598598
('⌊', Offset(39.11, 20.14), Size(13.14, 25.00)),
599599
]),
600+
(ContentExample.mathBlockKatexSpace, skip: false, [
601+
('1', Offset(0.00, 2.24), Size(10.28, 25.00)),
602+
(':', Offset(16.00, 2.24), Size(5.72, 25.00)),
603+
('2', Offset(27.43, 2.24), Size(10.28, 25.00)),
604+
]),
600605
];
601606

602607
for (final testCase in testCases) {

0 commit comments

Comments
 (0)