@@ -437,7 +437,9 @@ public static string GenerateHtml(CssBox root, HtmlGenerationStyle styleGen = Ht
437437 var sb = new StringBuilder ( ) ;
438438 if ( root != null )
439439 {
440- WriteHtml ( sb , root , styleGen , onlySelected ? CollectSelectedBoxes ( root ) : null ) ;
440+ CssBox selectionRoot = null ;
441+ var selectedBoxes = onlySelected ? CollectSelectedBoxes ( root , out selectionRoot ) : null ;
442+ WriteHtml ( sb , root , styleGen , selectedBoxes , selectionRoot ) ;
441443 }
442444 return sb . ToString ( ) ;
443445 }
@@ -532,20 +534,47 @@ private static int GetSelectedPlainText(StringBuilder sb, CssBox box)
532534 }
533535
534536 /// <summary>
535- /// Collect the html tags that have at least one word down the hierarchy that is selected recursively.<br/>
537+ /// Collect the boxes that have at least one word down the hierarchy that is selected recursively.<br/>
536538 /// </summary>
537539 /// <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>
538541 /// <returns>the collection to add the selected tags to</returns>
539- private static Dictionary < CssBox , bool > CollectSelectedBoxes ( CssBox root )
542+ private static Dictionary < CssBox , bool > CollectSelectedBoxes ( CssBox root , out CssBox selectionRoot )
540543 {
541- var selectedTags = new Dictionary < CssBox , bool > ( ) ;
542- var maybeTags = new Dictionary < CssBox , bool > ( ) ;
543- CollectSelectedBoxes ( root , selectedTags , maybeTags ) ;
544- return selectedTags ;
544+ var selectedBoxes = new Dictionary < CssBox , bool > ( ) ;
545+ var maybeBoxes = new Dictionary < CssBox , bool > ( ) ;
546+ 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+
573+ return selectedBoxes ;
545574 }
546575
547576 /// <summary>
548- /// Collect the html tags that have at least one word down the hierarchy that is selected recursively.<br/>
577+ /// Collect the boxes that have at least one word down the hierarchy that is selected recursively.<br/>
549578 /// Use <paramref name="maybeBoxes"/> to handle boxes that are between selected words but don't have selected word inside.<br/>
550579 /// </summary>
551580 /// <param name="box">the box to check its sub-tree</param>
@@ -559,10 +588,7 @@ private static bool CollectSelectedBoxes(CssBox box, Dictionary<CssBox, bool> se
559588 {
560589 if ( word . Selected )
561590 {
562- if ( box . HtmlTag != null )
563- {
564- selectedBoxes . Add ( box , true ) ;
565- }
591+ selectedBoxes [ box ] = true ;
566592 foreach ( var maybeTag in maybeBoxes )
567593 selectedBoxes [ maybeTag . Key ] = maybeTag . Value ;
568594 maybeBoxes . Clear ( ) ;
@@ -575,10 +601,7 @@ private static bool CollectSelectedBoxes(CssBox box, Dictionary<CssBox, bool> se
575601 var childInSelection = CollectSelectedBoxes ( childBox , selectedBoxes , maybeBoxes ) ;
576602 if ( childInSelection )
577603 {
578- if ( box . HtmlTag != null )
579- {
580- selectedBoxes [ box ] = true ;
581- }
604+ selectedBoxes [ box ] = true ;
582605 isInSelection = true ;
583606 }
584607 }
@@ -599,7 +622,8 @@ private static bool CollectSelectedBoxes(CssBox box, Dictionary<CssBox, bool> se
599622 /// <param name="box">the html sub-tree to write</param>
600623 /// <param name="styleGen">Controls the way styles are generated when html is generated</param>
601624 /// <param name="selectedBoxes">Control if to generate only selected boxes, if given only boxes found in hash will be generated</param>
602- private static void WriteHtml ( StringBuilder sb , CssBox box , HtmlGenerationStyle styleGen , Dictionary < CssBox , bool > selectedBoxes )
625+ /// <param name="selectionRoot">the box the is the root of selected boxes (the first box to contain multiple selected boxes)</param>
626+ private static void WriteHtml ( StringBuilder sb , CssBox box , HtmlGenerationStyle styleGen , Dictionary < CssBox , bool > selectedBoxes , CssBox selectionRoot )
603627 {
604628 if ( box . HtmlTag == null || selectedBoxes == null || selectedBoxes . ContainsKey ( box ) )
605629 {
@@ -609,6 +633,8 @@ private static void WriteHtml(StringBuilder sb, CssBox box, HtmlGenerationStyle
609633 ( ! box . HtmlTag . Attributes [ "href" ] . StartsWith ( "property" ) && ! box . HtmlTag . Attributes [ "href" ] . StartsWith ( "method" ) ) )
610634 {
611635 WriteHtmlTag ( sb , box , styleGen ) ;
636+ if ( box == selectionRoot )
637+ sb . Append ( "<!--StartFragment-->" ) ;
612638 }
613639
614640 if ( styleGen == HtmlGenerationStyle . InHeader && box . HtmlTag . Name == "html" && box . HtmlContainer . CssData != null )
@@ -633,11 +659,13 @@ private static void WriteHtml(StringBuilder sb, CssBox box, HtmlGenerationStyle
633659
634660 foreach ( var childBox in box . Boxes )
635661 {
636- WriteHtml ( sb , childBox , styleGen , selectedBoxes ) ;
662+ WriteHtml ( sb , childBox , styleGen , selectedBoxes , selectionRoot ) ;
637663 }
638664
639665 if ( box . HtmlTag != null && ! box . HtmlTag . IsSingle )
640666 {
667+ if ( box == selectionRoot )
668+ sb . Append ( "<!--EndFragment-->" ) ;
641669 sb . AppendFormat ( "</{0}>" , box . HtmlTag . Name ) ;
642670 }
643671 }
0 commit comments