|
| 1 | +import 'package:collection/collection.dart'; |
1 | 2 | import 'package:csslib/parser.dart' as css_parser; |
2 | 3 | import 'package:csslib/visitor.dart' as css_visitor; |
3 | 4 | import 'package:flutter/foundation.dart'; |
@@ -118,13 +119,39 @@ class _KatexParser { |
118 | 119 | } |
119 | 120 |
|
120 | 121 | List<KatexNode> _parseChildSpans(List<dom.Node> nodes) { |
121 | | - return List.unmodifiable(nodes.map((node) { |
122 | | - if (node case dom.Element(localName: 'span')) { |
123 | | - return _parseSpan(node); |
124 | | - } else { |
| 122 | + var resultSpans = QueueList<KatexNode>(); |
| 123 | + for (final node in nodes.reversed) { |
| 124 | + if (node is! dom.Element || node.localName != 'span') { |
125 | 125 | throw KatexHtmlParseError(); |
126 | 126 | } |
127 | | - })); |
| 127 | + |
| 128 | + final span = _parseSpan(node); |
| 129 | + |
| 130 | + if (span is KatexSpanNode) { |
| 131 | + final marginRightEm = span.styles.marginRightEm; |
| 132 | + if (marginRightEm != null && marginRightEm.isNegative) { |
| 133 | + final previousSpans = resultSpans; |
| 134 | + resultSpans = QueueList<KatexNode>(); |
| 135 | + resultSpans.addFirst(KatexNegativeMarginNode( |
| 136 | + leftOffsetEm: marginRightEm, |
| 137 | + nodes: previousSpans)); |
| 138 | + } |
| 139 | + } |
| 140 | + |
| 141 | + resultSpans.addFirst(span); |
| 142 | + |
| 143 | + if (span is KatexSpanNode) { |
| 144 | + final marginLeftEm = span.styles.marginLeftEm; |
| 145 | + if (marginLeftEm != null && marginLeftEm.isNegative) { |
| 146 | + final previousSpans = resultSpans; |
| 147 | + resultSpans = QueueList<KatexNode>(); |
| 148 | + resultSpans.addFirst(KatexNegativeMarginNode( |
| 149 | + leftOffsetEm: marginLeftEm, |
| 150 | + nodes: previousSpans)); |
| 151 | + } |
| 152 | + } |
| 153 | + } |
| 154 | + return resultSpans; |
128 | 155 | } |
129 | 156 |
|
130 | 157 | static final _resetSizeClassRegExp = RegExp(r'^reset-size(\d\d?)$'); |
@@ -210,13 +237,31 @@ class _KatexParser { |
210 | 237 | final pstrutStyles = _parseSpanInlineStyles(pstrutSpan)!; |
211 | 238 | final pstrutHeight = pstrutStyles.heightEm ?? 0; |
212 | 239 |
|
| 240 | + KatexSpanNode innerSpanNode = KatexSpanNode( |
| 241 | + styles: styles, |
| 242 | + text: null, |
| 243 | + nodes: _parseChildSpans(otherSpans)); |
| 244 | + |
| 245 | + final marginRightEm = styles.marginRightEm; |
| 246 | + final marginLeftEm = styles.marginLeftEm; |
| 247 | + if (marginRightEm != null && marginRightEm.isNegative) { |
| 248 | + throw KatexHtmlParseError(); |
| 249 | + } |
| 250 | + if (marginLeftEm != null && marginLeftEm.isNegative) { |
| 251 | + innerSpanNode = KatexSpanNode( |
| 252 | + styles: KatexSpanStyles(), |
| 253 | + text: null, |
| 254 | + nodes: [ |
| 255 | + KatexNegativeMarginNode( |
| 256 | + leftOffsetEm: marginLeftEm, |
| 257 | + nodes: [innerSpanNode]), |
| 258 | + ]); |
| 259 | + } |
| 260 | + |
213 | 261 | rows.add(KatexVlistRowNode( |
214 | 262 | verticalOffsetEm: topEm + pstrutHeight, |
215 | 263 | debugHtmlNode: kDebugMode ? innerSpan : null, |
216 | | - node: KatexSpanNode( |
217 | | - styles: styles, |
218 | | - text: null, |
219 | | - nodes: _parseChildSpans(otherSpans)))); |
| 264 | + node: innerSpanNode)); |
220 | 265 | } else { |
221 | 266 | throw KatexHtmlParseError(); |
222 | 267 | } |
@@ -532,17 +577,11 @@ class _KatexParser { |
532 | 577 |
|
533 | 578 | case 'margin-right': |
534 | 579 | marginRightEm = _getEm(expression); |
535 | | - if (marginRightEm != null) { |
536 | | - if (marginRightEm < 0) throw KatexHtmlParseError(); |
537 | | - continue; |
538 | | - } |
| 580 | + if (marginRightEm != null) continue; |
539 | 581 |
|
540 | 582 | case 'margin-left': |
541 | 583 | marginLeftEm = _getEm(expression); |
542 | | - if (marginLeftEm != null) { |
543 | | - if (marginLeftEm < 0) throw KatexHtmlParseError(); |
544 | | - continue; |
545 | | - } |
| 584 | + if (marginLeftEm != null) continue; |
546 | 585 | } |
547 | 586 |
|
548 | 587 | // TODO handle more CSS properties |
@@ -596,8 +635,8 @@ enum KatexSpanTextAlign { |
596 | 635 | @immutable |
597 | 636 | class KatexSpanStyles { |
598 | 637 | final double? heightEm; |
599 | | - final double? verticalAlignEm; |
600 | 638 |
|
| 639 | + final double? verticalAlignEm; |
601 | 640 | final double? topEm; |
602 | 641 |
|
603 | 642 | final double? marginRightEm; |
|
0 commit comments