@@ -437,8 +437,8 @@ public static string GenerateHtml(CssBox root, HtmlGenerationStyle styleGen = Ht
437437 var sb = new StringBuilder ( ) ;
438438 if ( root != null )
439439 {
440- CssBox selectionRoot = null ;
441- var selectedBoxes = onlySelected ? CollectSelectedBoxes ( root , out selectionRoot ) : null ;
440+ var selectedBoxes = onlySelected ? CollectSelectedBoxes ( root ) : null ;
441+ var selectionRoot = onlySelected ? GetSelectionRoot ( root , selectedBoxes ) : null ;
442442 WriteHtml ( sb , root , styleGen , selectedBoxes , selectionRoot ) ;
443443 }
444444 return sb . ToString ( ) ;
@@ -537,39 +537,12 @@ private static int GetSelectedPlainText(StringBuilder sb, CssBox box)
537537 /// Collect the boxes that have at least one word down the hierarchy that is selected recursively.<br/>
538538 /// </summary>
539539 /// <param name="root">the box to check its sub-tree</param>
540- /// <param name="selectionRoot">return the box the is the root of selected boxes (the first box to contain multiple selected boxes)</param>
541540 /// <returns>the collection to add the selected tags to</returns>
542- private static Dictionary < CssBox , bool > CollectSelectedBoxes ( CssBox root , out CssBox selectionRoot )
541+ private static Dictionary < CssBox , bool > CollectSelectedBoxes ( CssBox root )
543542 {
544543 var selectedBoxes = new Dictionary < CssBox , bool > ( ) ;
545544 var maybeBoxes = new Dictionary < CssBox , bool > ( ) ;
546545 CollectSelectedBoxes ( root , selectedBoxes , maybeBoxes ) ;
547-
548- // find the box the is the root of selected boxes (the first box to contain multiple selected boxes)
549- selectionRoot = root ;
550- while ( true )
551- {
552- bool foundRoot = false ;
553- CssBox selectedChild = null ;
554- foreach ( var childBox in selectionRoot . Boxes )
555- {
556- if ( selectedBoxes . ContainsKey ( childBox ) )
557- {
558- if ( selectedChild != null )
559- {
560- foundRoot = true ;
561- break ;
562- }
563- selectedChild = childBox ;
564- }
565- }
566-
567- if ( foundRoot || selectedChild == null )
568- break ;
569-
570- selectionRoot = selectedChild ;
571- }
572-
573546 return selectedBoxes ;
574547 }
575548
@@ -614,6 +587,72 @@ private static bool CollectSelectedBoxes(CssBox box, Dictionary<CssBox, bool> se
614587 return isInSelection ;
615588 }
616589
590+ /// <summary>
591+ /// find the box the is the root of selected boxes (the first box to contain multiple selected boxes)
592+ /// </summary>
593+ /// <param name="root">the root of the boxes tree</param>
594+ /// <param name="selectedBoxes">the selected boxes to find selection root in</param>
595+ /// <returns>the box that is the root of selected boxes</returns>
596+ private static CssBox GetSelectionRoot ( CssBox root , Dictionary < CssBox , bool > selectedBoxes )
597+ {
598+ var selectionRoot = root ;
599+ var selectionRootRun = root ;
600+ while ( true )
601+ {
602+ bool foundRoot = false ;
603+ CssBox selectedChild = null ;
604+ foreach ( var childBox in selectionRootRun . Boxes )
605+ {
606+ if ( selectedBoxes . ContainsKey ( childBox ) )
607+ {
608+ if ( selectedChild != null )
609+ {
610+ foundRoot = true ;
611+ break ;
612+ }
613+ selectedChild = childBox ;
614+ }
615+ }
616+
617+ if ( foundRoot || selectedChild == null )
618+ break ;
619+
620+ selectionRootRun = selectedChild ;
621+
622+ // the actual selection root must be a box with html tag
623+ if ( selectionRootRun . HtmlTag != null )
624+ selectionRoot = selectionRootRun ;
625+ }
626+
627+ // if the selection root doesn't contained any named boxes in it then we must go one level up, otherwise we will miss the selection root box formatting
628+ if ( ! ContainsNamedBox ( selectionRoot ) )
629+ {
630+ selectionRootRun = selectionRoot . ParentBox ;
631+ while ( selectionRootRun . ParentBox != null && selectionRootRun . HtmlTag == null )
632+ selectionRootRun = selectionRootRun . ParentBox ;
633+
634+ if ( selectionRootRun . HtmlTag != null )
635+ selectionRoot = selectionRootRun ;
636+ }
637+
638+ return selectionRoot ;
639+ }
640+
641+ /// <summary>
642+ /// Check if the given box has a names child box (has html tag) recursively.
643+ /// </summary>
644+ /// <param name="box">the box to check</param>
645+ /// <returns>true - in sub-tree there is a named box, false - otherwise</returns>
646+ private static bool ContainsNamedBox ( CssBox box )
647+ {
648+ foreach ( var childBox in box . Boxes )
649+ {
650+ if ( childBox . HtmlTag != null || ContainsNamedBox ( childBox ) )
651+ return true ;
652+ }
653+ return false ;
654+ }
655+
617656 /// <summary>
618657 /// Write the given html DOM sub-tree into the given string builder.<br/>
619658 /// If <paramref name="selectedBoxes"/> are given write html only from those tags.
@@ -633,7 +672,7 @@ private static void WriteHtml(StringBuilder sb, CssBox box, HtmlGenerationStyle
633672 ( ! box . HtmlTag . Attributes [ "href" ] . StartsWith ( "property" ) && ! box . HtmlTag . Attributes [ "href" ] . StartsWith ( "method" ) ) )
634673 {
635674 WriteHtmlTag ( sb , box , styleGen ) ;
636- if ( box == selectionRoot )
675+ if ( box == selectionRoot )
637676 sb . Append ( "<!--StartFragment-->" ) ;
638677 }
639678
0 commit comments