@@ -219,149 +219,167 @@ class _KatexParser {
219219 return resultSpans;
220220 }
221221
222- static final _resetSizeClassRegExp = RegExp (r'^reset-size(\d\d?)$' );
223- static final _sizeClassRegExp = RegExp (r'^size(\d\d?)$' );
224-
225222 KatexNode _parseSpan (dom.Element element) {
223+ assert (element.localName == 'span' );
226224 // TODO maybe check if the sequence of ancestors matter for spans.
227225
228- final debugHtmlNode = kDebugMode ? element : null ;
229-
230226 if (element.className == 'strut' ) {
231- if (element.nodes.isNotEmpty) throw _KatexHtmlParseError ();
232-
233- final styles = _parseInlineStyles (element);
234- if (styles == null ) throw _KatexHtmlParseError ();
235- final heightEm = _takeStyleEm (styles, 'height' );
236- if (heightEm == null ) throw _KatexHtmlParseError ();
237- final verticalAlignEm = _takeStyleEm (styles, 'vertical-align' );
238- if (styles.isNotEmpty) throw _KatexHtmlParseError ();
239-
240- return KatexStrutNode (
241- heightEm: heightEm,
242- verticalAlignEm: verticalAlignEm,
243- debugHtmlNode: debugHtmlNode);
227+ return _parseStrut (element);
244228 }
245229
246230 if (element.className == 'vlist-t'
247231 || element.className == 'vlist-t vlist-t2' ) {
248- final vlistT = element;
249- if (vlistT.nodes.isEmpty) throw _KatexHtmlParseError ();
250- if (vlistT.attributes.containsKey ('style' )) throw _KatexHtmlParseError ();
251-
252- final hasTwoVlistR = vlistT.className == 'vlist-t vlist-t2' ;
253- if (! hasTwoVlistR && vlistT.nodes.length != 1 ) throw _KatexHtmlParseError ();
254-
255- if (hasTwoVlistR) {
256- if (vlistT.nodes case [
257- _,
258- dom.Element (localName: 'span' , className: 'vlist-r' , nodes: [
259- dom.Element (localName: 'span' , className: 'vlist' , nodes: [
260- dom.Element (localName: 'span' , className: '' , nodes: []),
261- ]) && final vlist,
262- ]),
263- ]) {
264- // In the generated HTML the .vlist in second .vlist-r span will have
265- // a "height" inline style which we ignore, because it doesn't seem
266- // to have any effect in rendering on the web.
267- // But also make sure there aren't any other inline styles present.
268- final vlistStyles = _parseInlineStyles (vlist);
269- if (vlistStyles != null && vlistStyles.keys.any ((p) => p != 'height' )) {
270- throw _KatexHtmlParseError ();
271- }
272- } else {
232+ return _parseVlist (element);
233+ }
234+
235+ return _parseGenericSpan (element);
236+ }
237+
238+ KatexNode _parseStrut (dom.Element element) {
239+ assert (element.localName == 'span' );
240+ assert (element.className == 'strut' );
241+ if (element.nodes.isNotEmpty) throw _KatexHtmlParseError ();
242+
243+ final styles = _parseInlineStyles (element);
244+ if (styles == null ) throw _KatexHtmlParseError ();
245+ final heightEm = _takeStyleEm (styles, 'height' );
246+ if (heightEm == null ) throw _KatexHtmlParseError ();
247+ final verticalAlignEm = _takeStyleEm (styles, 'vertical-align' );
248+ if (styles.isNotEmpty) throw _KatexHtmlParseError ();
249+
250+ return KatexStrutNode (
251+ heightEm: heightEm,
252+ verticalAlignEm: verticalAlignEm,
253+ debugHtmlNode: kDebugMode ? element : null );
254+ }
255+
256+ KatexNode _parseVlist (dom.Element element) {
257+ assert (element.localName == 'span' );
258+ assert (element.className == 'vlist-t'
259+ || element.className == 'vlist-t vlist-t2' );
260+ final vlistT = element;
261+ if (vlistT.nodes.isEmpty) throw _KatexHtmlParseError ();
262+ if (vlistT.attributes.containsKey ('style' )) throw _KatexHtmlParseError ();
263+
264+ final hasTwoVlistR = vlistT.className == 'vlist-t vlist-t2' ;
265+ if (! hasTwoVlistR && vlistT.nodes.length != 1 ) throw _KatexHtmlParseError ();
266+
267+ if (hasTwoVlistR) {
268+ if (vlistT.nodes case [
269+ _,
270+ dom.Element (localName: 'span' , className: 'vlist-r' , nodes: [
271+ dom.Element (localName: 'span' , className: 'vlist' , nodes: [
272+ dom.Element (localName: 'span' , className: '' , nodes: []),
273+ ]) && final vlist,
274+ ]),
275+ ]) {
276+ // In the generated HTML the .vlist in second .vlist-r span will have
277+ // a "height" inline style which we ignore, because it doesn't seem
278+ // to have any effect in rendering on the web.
279+ // But also make sure there aren't any other inline styles present.
280+ final vlistStyles = _parseInlineStyles (vlist);
281+ if (vlistStyles != null && vlistStyles.keys.any ((p) => p != 'height' )) {
273282 throw _KatexHtmlParseError ();
274283 }
284+ } else {
285+ throw _KatexHtmlParseError ();
275286 }
287+ }
276288
277- if (vlistT.nodes.first
278- case dom.Element (localName: 'span' , className: 'vlist-r' ) &&
279- final vlistR) {
280- if (vlistR.attributes.containsKey ('style' )) throw _KatexHtmlParseError ();
281-
282- if (vlistR.nodes.first
283- case dom.Element (localName: 'span' , className: 'vlist' ) &&
284- final vlist) {
285- // Same as above for the second .vlist-r span, .vlist span in first
286- // .vlist-r span will have "height" inline style which we ignore,
287- // because it doesn't seem to have any effect in rendering on
288- // the web.
289- // But also make sure there aren't any other inline styles present.
290- final vlistStyles = _parseInlineStyles (vlist);
291- if (vlistStyles != null && vlistStyles.keys.any ((p) => p != 'height' )) {
292- throw _KatexHtmlParseError ();
293- }
289+ if (vlistT.nodes.first
290+ case dom.Element (localName: 'span' , className: 'vlist-r' ) &&
291+ final vlistR) {
292+ if (vlistR.attributes.containsKey ('style' )) throw _KatexHtmlParseError ();
293+
294+ if (vlistR.nodes.first
295+ case dom.Element (localName: 'span' , className: 'vlist' ) &&
296+ final vlist) {
297+ // Same as above for the second .vlist-r span, .vlist span in first
298+ // .vlist-r span will have "height" inline style which we ignore,
299+ // because it doesn't seem to have any effect in rendering on
300+ // the web.
301+ // But also make sure there aren't any other inline styles present.
302+ final vlistStyles = _parseInlineStyles (vlist);
303+ if (vlistStyles != null && vlistStyles.keys.any ((p) => p != 'height' )) {
304+ throw _KatexHtmlParseError ();
305+ }
306+
307+ final rows = < KatexVlistRowNode > [];
308+
309+ for (final innerSpan in vlist.nodes) {
310+ if (innerSpan case dom.Element (
311+ localName: 'span' ,
312+ nodes: [
313+ dom.Element (localName: 'span' , className: 'pstrut' ) &&
314+ final pstrutSpan,
315+ ...final otherSpans,
316+ ],
317+ )) {
318+ if (innerSpan.className != '' ) {
319+ throw _KatexHtmlParseError ('unexpected CSS class for '
320+ 'vlist inner span: ${innerSpan .className }' );
321+ }
294322
295- final rows = < KatexVlistRowNode > [];
296-
297- for (final innerSpan in vlist.nodes) {
298- if (innerSpan case dom.Element (
299- localName: 'span' ,
300- nodes: [
301- dom.Element (localName: 'span' , className: 'pstrut' ) &&
302- final pstrutSpan,
303- ...final otherSpans,
304- ],
305- )) {
306- if (innerSpan.className != '' ) {
307- throw _KatexHtmlParseError ('unexpected CSS class for '
308- 'vlist inner span: ${innerSpan .className }' );
309- }
310-
311- final inlineStyles = _parseInlineStyles (innerSpan);
312- if (inlineStyles == null ) throw _KatexHtmlParseError ();
313- final marginLeftEm = _takeStyleEm (inlineStyles, 'margin-left' );
314- final marginLeftIsNegative = marginLeftEm? .isNegative ?? false ;
315- final marginRightEm = _takeStyleEm (inlineStyles, 'margin-right' );
316- if (marginRightEm? .isNegative ?? false ) throw _KatexHtmlParseError ();
317- final styles = KatexSpanStyles (
318- marginLeftEm: marginLeftIsNegative ? null : marginLeftEm,
319- marginRightEm: marginRightEm,
320- );
321- final topEm = _takeStyleEm (inlineStyles, 'top' );
322- if (inlineStyles.isNotEmpty) throw _KatexHtmlParseError ();
323-
324- final pstrutStyles = _parseInlineStyles (pstrutSpan);
325- if (pstrutStyles == null ) throw _KatexHtmlParseError ();
326- final pstrutHeightEm = _takeStyleEm (pstrutStyles, 'height' );
327- if (pstrutHeightEm == null ) throw _KatexHtmlParseError ();
328- if (pstrutStyles.isNotEmpty) throw _KatexHtmlParseError ();
329-
330- KatexSpanNode child = KatexSpanNode (
331- styles: styles,
323+ final inlineStyles = _parseInlineStyles (innerSpan);
324+ if (inlineStyles == null ) throw _KatexHtmlParseError ();
325+ final marginLeftEm = _takeStyleEm (inlineStyles, 'margin-left' );
326+ final marginLeftIsNegative = marginLeftEm? .isNegative ?? false ;
327+ final marginRightEm = _takeStyleEm (inlineStyles, 'margin-right' );
328+ if (marginRightEm? .isNegative ?? false ) throw _KatexHtmlParseError ();
329+ final styles = KatexSpanStyles (
330+ marginLeftEm: marginLeftIsNegative ? null : marginLeftEm,
331+ marginRightEm: marginRightEm,
332+ );
333+ final topEm = _takeStyleEm (inlineStyles, 'top' );
334+ if (inlineStyles.isNotEmpty) throw _KatexHtmlParseError ();
335+
336+ final pstrutStyles = _parseInlineStyles (pstrutSpan);
337+ if (pstrutStyles == null ) throw _KatexHtmlParseError ();
338+ final pstrutHeightEm = _takeStyleEm (pstrutStyles, 'height' );
339+ if (pstrutHeightEm == null ) throw _KatexHtmlParseError ();
340+ if (pstrutStyles.isNotEmpty) throw _KatexHtmlParseError ();
341+
342+ KatexSpanNode child = KatexSpanNode (
343+ styles: styles,
344+ text: null ,
345+ nodes: _parseChildSpans (otherSpans));
346+
347+ if (marginLeftIsNegative) {
348+ child = KatexSpanNode (
349+ styles: KatexSpanStyles (),
332350 text: null ,
333- nodes: _parseChildSpans (otherSpans));
334-
335- if (marginLeftIsNegative) {
336- child = KatexSpanNode (
337- styles: KatexSpanStyles (),
338- text: null ,
339- nodes: [KatexNegativeMarginNode (
340- leftOffsetEm: marginLeftEm! ,
341- nodes: [child])]);
342- }
343-
344- rows.add (KatexVlistRowNode (
345- verticalOffsetEm: (topEm ?? 0 ) + pstrutHeightEm,
346- debugHtmlNode: kDebugMode ? innerSpan : null ,
347- node: child));
348- } else {
349- throw _KatexHtmlParseError ();
351+ nodes: [KatexNegativeMarginNode (
352+ leftOffsetEm: marginLeftEm! ,
353+ nodes: [child])]);
350354 }
351- }
352355
353- // TODO(#1716) Handle styling for .vlist-t2 spans
354- return KatexVlistNode (
355- rows : rows ,
356- debugHtmlNode : debugHtmlNode,
357- );
358- } else {
359- throw _KatexHtmlParseError ();
356+ rows. add ( KatexVlistRowNode (
357+ verticalOffsetEm : (topEm ?? 0 ) + pstrutHeightEm,
358+ debugHtmlNode : kDebugMode ? innerSpan : null ,
359+ node : child));
360+ } else {
361+ throw _KatexHtmlParseError ();
362+ }
360363 }
364+
365+ // TODO(#1716) Handle styling for .vlist-t2 spans
366+ return KatexVlistNode (
367+ rows: rows,
368+ debugHtmlNode: kDebugMode ? element : null ,
369+ );
361370 } else {
362371 throw _KatexHtmlParseError ();
363372 }
373+ } else {
374+ throw _KatexHtmlParseError ();
364375 }
376+ }
377+
378+ static final _resetSizeClassRegExp = RegExp (r'^reset-size(\d\d?)$' );
379+ static final _sizeClassRegExp = RegExp (r'^size(\d\d?)$' );
380+
381+ KatexNode _parseGenericSpan (dom.Element element) {
382+ assert (element.localName == 'span' );
365383
366384 // Aggregate the CSS styles that apply, in the same order as the CSS
367385 // classes specified for this span, mimicking the behaviour on web.
@@ -646,7 +664,7 @@ class _KatexParser {
646664 styles: styles,
647665 text: text,
648666 nodes: spans,
649- debugHtmlNode: debugHtmlNode );
667+ debugHtmlNode: kDebugMode ? element : null );
650668 }
651669
652670 /// Parse the inline CSS styles from the given element.
0 commit comments