@@ -320,10 +320,6 @@ class _KatexParser {
320
320
// We expect `vertical-align` inline style to be only present on a
321
321
// `strut` span, for which we emit `KatexStrutNode` separately.
322
322
if (inlineStyles.verticalAlignEm != null ) throw _KatexHtmlParseError ();
323
-
324
- // Currently, we expect `top` to only be inside a vlist, and
325
- // we handle that case separately above.
326
- if (inlineStyles.topEm != null ) throw _KatexHtmlParseError ();
327
323
}
328
324
329
325
// Aggregate the CSS styles that apply, in the same order as the CSS
@@ -586,10 +582,21 @@ class _KatexParser {
586
582
}
587
583
if (text == null && spans == null ) throw _KatexHtmlParseError ();
588
584
585
+ final mergedStyles = inlineStyles != null
586
+ ? styles.merge (inlineStyles)
587
+ : styles;
588
+
589
+ // We expect `top` style to be only present if `position: relative`
590
+ // is also present. As both are non-inherited CSS attributes and
591
+ // should only ever be present together.
592
+ // TODO account for other sides (left, right, bottom).
593
+ if (mergedStyles.topEm != null
594
+ && mergedStyles.position != KatexSpanPosition .relative) {
595
+ throw _KatexHtmlParseError ();
596
+ }
597
+
589
598
return KatexSpanNode (
590
- styles: inlineStyles != null
591
- ? styles.merge (inlineStyles)
592
- : styles,
599
+ styles: mergedStyles,
593
600
text: text,
594
601
nodes: spans,
595
602
debugHtmlNode: debugHtmlNode);
@@ -607,6 +614,7 @@ class _KatexParser {
607
614
double ? topEm;
608
615
double ? marginRightEm;
609
616
double ? marginLeftEm;
617
+ KatexSpanPosition ? position;
610
618
611
619
for (final declaration in rule.declarationGroup.declarations) {
612
620
if (declaration case css_visitor.Declaration (
@@ -640,6 +648,13 @@ class _KatexParser {
640
648
if (marginLeftEm < 0 ) throw _KatexHtmlParseError ();
641
649
continue ;
642
650
}
651
+
652
+ case 'position' :
653
+ position = switch (_getLiteral (expression)) {
654
+ 'relative' => KatexSpanPosition .relative,
655
+ _ => null ,
656
+ };
657
+ if (position != null ) continue ;
643
658
}
644
659
645
660
// TODO handle more CSS properties
@@ -658,6 +673,7 @@ class _KatexParser {
658
673
verticalAlignEm: verticalAlignEm,
659
674
marginRightEm: marginRightEm,
660
675
marginLeftEm: marginLeftEm,
676
+ position: position,
661
677
);
662
678
} else {
663
679
throw _KatexHtmlParseError ();
@@ -674,6 +690,17 @@ class _KatexParser {
674
690
}
675
691
return null ;
676
692
}
693
+
694
+ /// Returns the CSS literal string value if the given [expression] is
695
+ /// actually a literal expression, else returns null.
696
+ String ? _getLiteral (css_visitor.Expression expression) {
697
+ if (expression case css_visitor.LiteralTerm (: final value)) {
698
+ if (value case css_visitor.Identifier (: final name)) {
699
+ return name;
700
+ }
701
+ }
702
+ return null ;
703
+ }
677
704
}
678
705
679
706
enum KatexSpanFontWeight {
@@ -691,6 +718,10 @@ enum KatexSpanTextAlign {
691
718
right,
692
719
}
693
720
721
+ enum KatexSpanPosition {
722
+ relative,
723
+ }
724
+
694
725
@immutable
695
726
class KatexSpanStyles {
696
727
final double ? heightEm;
@@ -707,6 +738,8 @@ class KatexSpanStyles {
707
738
final KatexSpanFontStyle ? fontStyle;
708
739
final KatexSpanTextAlign ? textAlign;
709
740
741
+ final KatexSpanPosition ? position;
742
+
710
743
const KatexSpanStyles ({
711
744
this .heightEm,
712
745
this .verticalAlignEm,
@@ -718,6 +751,7 @@ class KatexSpanStyles {
718
751
this .fontWeight,
719
752
this .fontStyle,
720
753
this .textAlign,
754
+ this .position,
721
755
});
722
756
723
757
@override
@@ -733,6 +767,7 @@ class KatexSpanStyles {
733
767
fontWeight,
734
768
fontStyle,
735
769
textAlign,
770
+ position,
736
771
);
737
772
738
773
@override
@@ -747,7 +782,8 @@ class KatexSpanStyles {
747
782
other.fontSizeEm == fontSizeEm &&
748
783
other.fontWeight == fontWeight &&
749
784
other.fontStyle == fontStyle &&
750
- other.textAlign == textAlign;
785
+ other.textAlign == textAlign &&
786
+ other.position == position;
751
787
}
752
788
753
789
@override
@@ -763,6 +799,7 @@ class KatexSpanStyles {
763
799
if (fontWeight != null ) args.add ('fontWeight: $fontWeight ' );
764
800
if (fontStyle != null ) args.add ('fontStyle: $fontStyle ' );
765
801
if (textAlign != null ) args.add ('textAlign: $textAlign ' );
802
+ if (position != null ) args.add ('position: $position ' );
766
803
return '${objectRuntimeType (this , 'KatexSpanStyles' )}(${args .join (', ' )})' ;
767
804
}
768
805
@@ -785,6 +822,7 @@ class KatexSpanStyles {
785
822
fontStyle: other.fontStyle ?? fontStyle,
786
823
fontWeight: other.fontWeight ?? fontWeight,
787
824
textAlign: other.textAlign ?? textAlign,
825
+ position: other.position ?? position,
788
826
);
789
827
}
790
828
@@ -799,6 +837,7 @@ class KatexSpanStyles {
799
837
bool fontWeight = true ,
800
838
bool fontStyle = true ,
801
839
bool textAlign = true ,
840
+ bool position = true ,
802
841
}) {
803
842
return KatexSpanStyles (
804
843
heightEm: heightEm ? this .heightEm : null ,
@@ -811,6 +850,7 @@ class KatexSpanStyles {
811
850
fontWeight: fontWeight ? this .fontWeight : null ,
812
851
fontStyle: fontStyle ? this .fontStyle : null ,
813
852
textAlign: textAlign ? this .textAlign : null ,
853
+ position: position ? this .position : null ,
814
854
);
815
855
}
816
856
}
0 commit comments