@@ -20,14 +20,16 @@ class KatexParser {
2020 final span = _parseSpan (node);
2121 resultSpans.add (span);
2222
23- final marginRightEm = span.styles.marginRightEm;
24- if (marginRightEm != null && marginRightEm.isNegative) {
25- final previousSpansReversed =
26- resultSpans.reversed.toList (growable: false );
27- resultSpans = [];
28- resultSpans.add (KatexNegativeMarginNode (
29- marginRightEm: marginRightEm,
30- nodes: previousSpansReversed));
23+ if (span is KatexSpanNode ) {
24+ final marginRightEm = span.styles.marginRightEm;
25+ if (marginRightEm != null && marginRightEm.isNegative) {
26+ final previousSpansReversed =
27+ resultSpans.reversed.toList (growable: false );
28+ resultSpans = [];
29+ resultSpans.add (KatexNegativeMarginNode (
30+ marginRightEm: marginRightEm,
31+ nodes: previousSpansReversed));
32+ }
3133 }
3234 }
3335
@@ -37,9 +39,111 @@ class KatexParser {
3739 static final _resetSizeClassRegExp = RegExp (r'^reset-size(\d\d?)$' );
3840 static final _sizeClassRegExp = RegExp (r'^size(\d\d?)$' );
3941
40- KatexSpanNode _parseSpan (dom.Element element) {
42+ KatexNode _parseSpan (dom.Element element) {
4143 final spanClasses = List <String >.unmodifiable (element.className.split (' ' ));
4244
45+ if (element case dom.Element (localName: 'span' , : final className)
46+ when className.startsWith ('vlist' )) {
47+ switch (element) {
48+ case dom.Element (
49+ localName: 'span' ,
50+ className: 'vlist-t' ,
51+ attributes: final attributesVlistT,
52+ nodes: [
53+ dom.Element (
54+ localName: 'span' ,
55+ className: 'vlist-r' ,
56+ attributes: final attributesVlistR,
57+ nodes: [
58+ dom.Element (
59+ localName: 'span' ,
60+ className: 'vlist' ,
61+ nodes: [
62+ dom.Element (
63+ localName: 'span' ,
64+ className: '' ,
65+ nodes: [
66+ dom.Element (localName: 'span' , className: 'pstrut' )
67+ && final pstrutSpan,
68+ ...,
69+ ]) && final innerSpan,
70+ ]),
71+ ]),
72+ ])
73+ when ! attributesVlistT.containsKey ('style' ) &&
74+ ! attributesVlistR.containsKey ('style' ):
75+ // TODO vlist element should only have `height` style, which we ignore.
76+
77+ var styles = _parseSpanInlineStyles (innerSpan)! ;
78+ final topEm = styles.topEm ?? 0 ;
79+
80+ final pstrutStyles = _parseSpanInlineStyles (pstrutSpan)! ;
81+ final pstrutHeight = pstrutStyles.heightEm ?? 0 ;
82+
83+ // TODO handle negative right-margin inline style on row nodes.
84+ return KatexVlistNode (rows: [
85+ KatexVlistRowNode (
86+ verticalOffsetEm: topEm + pstrutHeight,
87+ nodes: _parseChildSpans (innerSpan)),
88+ ]);
89+
90+ case dom.Element (
91+ localName: 'span' ,
92+ className: 'vlist-t vlist-t2' ,
93+ attributes: final attributesVlistT,
94+ nodes: [
95+ dom.Element (
96+ localName: 'span' ,
97+ className: 'vlist-r' ,
98+ attributes: final attributesVlistR,
99+ nodes: [
100+ dom.Element (
101+ localName: 'span' ,
102+ className: 'vlist' ,
103+ nodes: [...]) && final vlist1,
104+ dom.Element (localName: 'span' , className: 'vlist-s' ),
105+ ]),
106+ dom.Element (localName: 'span' , className: 'vlist-r' , nodes: [
107+ dom.Element (localName: 'span' , className: 'vlist' , nodes: [
108+ dom.Element (localName: 'span' , className: '' , nodes: []),
109+ ])
110+ ]),
111+ ])
112+ when ! attributesVlistT.containsKey ('style' ) &&
113+ ! attributesVlistR.containsKey ('style' ):
114+ // TODO Ensure both should only have a `height` style.
115+
116+ final rows = < KatexVlistRowNode > [];
117+
118+ for (final innerSpan in vlist1.nodes) {
119+ if (innerSpan case dom.Element (
120+ localName: 'span' ,
121+ className: '' ,
122+ nodes: [
123+ dom.Element (localName: 'span' , className: 'pstrut' ) &&
124+ final pstrutSpan,
125+ ...,
126+ ])) {
127+ final styles = _parseSpanInlineStyles (innerSpan)! ;
128+ final topEm = styles.topEm ?? 0 ;
129+
130+ final pstrutStyles = _parseSpanInlineStyles (pstrutSpan)! ;
131+ final pstrutHeight = pstrutStyles.heightEm ?? 0 ;
132+
133+ // TODO handle negative right-margin inline style on row nodes.
134+ rows.add (KatexVlistRowNode (
135+ verticalOffsetEm: topEm + pstrutHeight,
136+ nodes: _parseChildSpans (innerSpan)));
137+ }
138+ }
139+
140+ return KatexVlistNode (rows: rows);
141+
142+ default :
143+ throw KatexHtmlParseError ();
144+ }
145+ }
146+
43147 var styles = KatexSpanStyles ();
44148 var index = 0 ;
45149 while (index < spanClasses.length) {
@@ -261,9 +365,12 @@ class KatexParser {
261365 if (topLevel is ! css_visitor.RuleSet ) throw KatexHtmlParseError ();
262366 final rule = topLevel;
263367
368+ double ? heightEm;
264369 double ? marginLeftEm;
265370 double ? marginRightEm;
266371 double ? paddingLeftEm;
372+ double ? topEm;
373+ double ? widthEm;
267374
268375 for (final declaration in rule.declarationGroup.declarations) {
269376 if (declaration is ! css_visitor.Declaration ) throw KatexHtmlParseError ();
@@ -275,6 +382,10 @@ class KatexParser {
275382 final expression = expressions.expressions.single;
276383
277384 switch (property) {
385+ case 'height' :
386+ heightEm = _getEm (expression);
387+ if (heightEm != null ) continue ;
388+
278389 case 'margin-left' :
279390 marginLeftEm = _getEm (expression);
280391 if (marginLeftEm != null ) continue ;
@@ -287,16 +398,27 @@ class KatexParser {
287398 paddingLeftEm = _getEm (expression);
288399 if (paddingLeftEm != null ) continue ;
289400
401+ case 'top' :
402+ topEm = _getEm (expression);
403+ if (topEm != null ) continue ;
404+
405+ case 'width' :
406+ widthEm = _getEm (expression);
407+ if (widthEm != null ) continue ;
408+
290409 default :
291410 // TODO handle more CSS properties
292411 assert (debugLog ('Unsupported CSS property: $property of type ${expression .runtimeType }' ));
293412 }
294413 }
295414
296415 return KatexSpanStyles (
416+ heightEm: heightEm,
297417 marginLeftEm: marginLeftEm,
298418 marginRightEm: marginRightEm,
299419 paddingLeftEm: paddingLeftEm,
420+ topEm: topEm,
421+ widthEm: widthEm,
300422 );
301423 }
302424 return null ;
@@ -326,9 +448,12 @@ enum KatexSpanTextAlign {
326448}
327449
328450class KatexSpanStyles {
451+ double ? heightEm;
329452 double ? marginLeftEm;
330453 double ? marginRightEm;
331454 double ? paddingLeftEm;
455+ double ? topEm;
456+ double ? widthEm;
332457
333458 String ? fontFamily;
334459 double ? fontSizeEm;
@@ -337,9 +462,12 @@ class KatexSpanStyles {
337462 KatexSpanTextAlign ? textAlign;
338463
339464 KatexSpanStyles ({
465+ this .heightEm,
340466 this .marginLeftEm,
341467 this .marginRightEm,
342468 this .paddingLeftEm,
469+ this .topEm,
470+ this .widthEm,
343471 this .fontFamily,
344472 this .fontSizeEm,
345473 this .fontStyle,
@@ -350,9 +478,12 @@ class KatexSpanStyles {
350478 @override
351479 int get hashCode => Object .hash (
352480 'KatexSpanStyles' ,
481+ heightEm,
353482 marginLeftEm,
354483 marginRightEm,
355484 paddingLeftEm,
485+ topEm,
486+ widthEm,
356487 fontFamily,
357488 fontSizeEm,
358489 fontStyle,
@@ -363,9 +494,12 @@ class KatexSpanStyles {
363494 @override
364495 bool operator == (Object other) {
365496 return other is KatexSpanStyles &&
497+ other.heightEm == heightEm &&
366498 other.marginLeftEm == marginLeftEm &&
367499 other.marginRightEm == marginRightEm &&
368500 other.paddingLeftEm == paddingLeftEm &&
501+ other.topEm == topEm &&
502+ other.widthEm == widthEm &&
369503 other.fontFamily == fontFamily &&
370504 other.fontSizeEm == fontSizeEm &&
371505 other.fontStyle == fontStyle &&
@@ -380,9 +514,12 @@ class KatexSpanStyles {
380514 if (this == _zero) return '${objectRuntimeType (this , 'KatexSpanStyles' )}()' ;
381515
382516 final args = < String > [];
517+ if (heightEm != null ) args.add ('heightEm: $heightEm ' );
383518 if (marginLeftEm != null ) args.add ('marginLeftEm: $marginLeftEm ' );
384519 if (marginRightEm != null ) args.add ('marginRightEm: $marginRightEm ' );
385520 if (paddingLeftEm != null ) args.add ('paddingLeftEm: $paddingLeftEm ' );
521+ if (topEm != null ) args.add ('topEm: $topEm ' );
522+ if (widthEm != null ) args.add ('width: $widthEm ' );
386523 if (fontFamily != null ) args.add ('fontFamily: $fontFamily ' );
387524 if (fontSizeEm != null ) args.add ('fontSizeEm: $fontSizeEm ' );
388525 if (fontStyle != null ) args.add ('fontStyle: $fontStyle ' );
@@ -393,9 +530,12 @@ class KatexSpanStyles {
393530
394531 KatexSpanStyles merge (KatexSpanStyles other) {
395532 return KatexSpanStyles (
533+ heightEm: other.heightEm ?? heightEm,
396534 marginLeftEm: other.marginLeftEm ?? marginLeftEm,
397535 marginRightEm: other.marginRightEm ?? marginRightEm,
398536 paddingLeftEm: other.paddingLeftEm ?? paddingLeftEm,
537+ topEm: other.topEm ?? topEm,
538+ widthEm: other.widthEm ?? widthEm,
399539 fontFamily: other.fontFamily ?? fontFamily,
400540 fontSizeEm: other.fontSizeEm ?? fontSizeEm,
401541 fontStyle: other.fontStyle ?? fontStyle,
0 commit comments