@@ -322,6 +322,173 @@ describe('m:bar converter', () => {
322322 } ) ;
323323} ) ;
324324
325+ describe ( 'm:d converter' , ( ) => {
326+ it ( 'converts m:d to delimiters around the expression' , ( ) => {
327+ const omml = {
328+ name : 'm:oMath' ,
329+ elements : [
330+ {
331+ name : 'm:d' ,
332+ elements : [
333+ {
334+ name : 'm:dPr' ,
335+ elements : [
336+ { name : 'm:begChr' , attributes : { 'm:val' : '(' } } ,
337+ { name : 'm:endChr' , attributes : { 'm:val' : ')' } } ,
338+ ] ,
339+ } ,
340+ {
341+ name : 'm:e' ,
342+ elements : [
343+ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'x' } ] } ] } ,
344+ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : '+' } ] } ] } ,
345+ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'y' } ] } ] } ,
346+ ] ,
347+ } ,
348+ ] ,
349+ } ,
350+ ] ,
351+ } ;
352+
353+ const result = convertOmmlToMathml ( omml , doc ) ;
354+ expect ( result ) . not . toBeNull ( ) ;
355+ expect ( result ! . textContent ) . toBe ( '(x+y)' ) ;
356+
357+ const outerRow = result ! . querySelector ( 'mrow' ) ;
358+ expect ( outerRow ) . not . toBeNull ( ) ;
359+ expect ( outerRow ! . children [ 0 ] ! . textContent ) . toBe ( '(' ) ;
360+ expect ( outerRow ! . children [ 1 ] ! . textContent ) . toBe ( 'x+y' ) ;
361+ expect ( outerRow ! . children [ 2 ] ! . textContent ) . toBe ( ')' ) ;
362+ } ) ;
363+
364+ it ( 'defaults to parentheses and pipe separators when dPr is missing' , ( ) => {
365+ const omml = {
366+ name : 'm:oMath' ,
367+ elements : [
368+ {
369+ name : 'm:d' ,
370+ elements : [
371+ {
372+ name : 'm:e' ,
373+ elements : [ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'x' } ] } ] } ] ,
374+ } ,
375+ {
376+ name : 'm:e' ,
377+ elements : [ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'y' } ] } ] } ] ,
378+ } ,
379+ ] ,
380+ } ,
381+ ] ,
382+ } ;
383+
384+ const result = convertOmmlToMathml ( omml , doc ) ;
385+ expect ( result ) . not . toBeNull ( ) ;
386+ expect ( result ! . textContent ) . toBe ( '(x|y)' ) ;
387+ } ) ;
388+
389+ it ( 'uses custom delimiter and separator characters for multiple expressions' , ( ) => {
390+ const omml = {
391+ name : 'm:oMath' ,
392+ elements : [
393+ {
394+ name : 'm:d' ,
395+ elements : [
396+ {
397+ name : 'm:dPr' ,
398+ elements : [
399+ { name : 'm:begChr' , attributes : { 'm:val' : '[' } } ,
400+ { name : 'm:endChr' , attributes : { 'm:val' : ']' } } ,
401+ { name : 'm:sepChr' , attributes : { 'm:val' : ';' } } ,
402+ ] ,
403+ } ,
404+ {
405+ name : 'm:e' ,
406+ elements : [ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'a' } ] } ] } ] ,
407+ } ,
408+ {
409+ name : 'm:e' ,
410+ elements : [ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'b' } ] } ] } ] ,
411+ } ,
412+ ] ,
413+ } ,
414+ ] ,
415+ } ;
416+
417+ const result = convertOmmlToMathml ( omml , doc ) ;
418+ expect ( result ) . not . toBeNull ( ) ;
419+ expect ( result ! . textContent ) . toBe ( '[a;b]' ) ;
420+
421+ const outerRow = result ! . querySelector ( 'mrow' ) ;
422+ expect ( outerRow ) . not . toBeNull ( ) ;
423+ expect ( outerRow ! . children . length ) . toBe ( 5 ) ;
424+ expect ( outerRow ! . children [ 0 ] ! . textContent ) . toBe ( '[' ) ;
425+ expect ( outerRow ! . children [ 2 ] ! . textContent ) . toBe ( ';' ) ;
426+ expect ( outerRow ! . children [ 4 ] ! . textContent ) . toBe ( ']' ) ;
427+ } ) ;
428+
429+ it ( 'does not render stray separators for empty expressions' , ( ) => {
430+ const omml = {
431+ name : 'm:oMath' ,
432+ elements : [
433+ {
434+ name : 'm:d' ,
435+ elements : [
436+ { name : 'm:e' , elements : [ ] } ,
437+ {
438+ name : 'm:e' ,
439+ elements : [ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'x' } ] } ] } ] ,
440+ } ,
441+ ] ,
442+ } ,
443+ ] ,
444+ } ;
445+
446+ const result = convertOmmlToMathml ( omml , doc ) ;
447+ expect ( result ) . not . toBeNull ( ) ;
448+ expect ( result ! . textContent ) . toBe ( '(x)' ) ;
449+ } ) ;
450+
451+ it ( 'preserves explicit empty delimiter characters' , ( ) => {
452+ const omml = {
453+ name : 'm:oMath' ,
454+ elements : [
455+ {
456+ name : 'm:d' ,
457+ elements : [
458+ {
459+ name : 'm:dPr' ,
460+ elements : [
461+ { name : 'm:begChr' , attributes : { 'm:val' : '' } } ,
462+ { name : 'm:endChr' , attributes : { 'm:val' : '' } } ,
463+ { name : 'm:sepChr' , attributes : { 'm:val' : '' } } ,
464+ ] ,
465+ } ,
466+ {
467+ name : 'm:e' ,
468+ elements : [ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'x' } ] } ] } ] ,
469+ } ,
470+ {
471+ name : 'm:e' ,
472+ elements : [ { name : 'm:r' , elements : [ { name : 'm:t' , elements : [ { type : 'text' , text : 'y' } ] } ] } ] ,
473+ } ,
474+ ] ,
475+ } ,
476+ ] ,
477+ } ;
478+
479+ const result = convertOmmlToMathml ( omml , doc ) ;
480+ expect ( result ) . not . toBeNull ( ) ;
481+ expect ( result ! . textContent ) . toBe ( 'xy' ) ;
482+
483+ const outerRow = result ! . querySelector ( 'mrow' ) ;
484+ expect ( outerRow ) . not . toBeNull ( ) ;
485+ expect ( outerRow ! . children . length ) . toBe ( 5 ) ;
486+ expect ( outerRow ! . children [ 0 ] ! . textContent ) . toBe ( '' ) ;
487+ expect ( outerRow ! . children [ 2 ] ! . textContent ) . toBe ( '' ) ;
488+ expect ( outerRow ! . children [ 4 ] ! . textContent ) . toBe ( '' ) ;
489+ } ) ;
490+ } ) ;
491+
325492describe ( 'm:sSub converter' , ( ) => {
326493 it ( 'converts m:sSub to <msub> with base and subscript' , ( ) => {
327494 const omml = {
0 commit comments