@@ -826,38 +826,58 @@ component extends="wheels.Controller" {
826826
827827 /**
828828 * Converts plain text URLs and embeddable links into HTML
829- * For embeddable URLs (YouTube, Vimeo, etc.), creates embed iframes
829+ * Extracts embeddable URLs to the top, then handles remaining links
830+ * For embeddable URLs (YouTube, etc.), creates embed iframes at top
830831 * For other URLs, creates anchor tags
831832 */
832833 string function embedAndAutoLink (required string content , string class = " text--primary" , string target = " _blank" ) {
833- var result = arguments .content ;
834834 var urlPattern = " (https?://[^\s<"" '`]+)" ;
835- var matches = reMatch (urlPattern , result );
835+ var matches = reMatch (urlPattern , arguments . content );
836836
837837 // Remove duplicates
838838 var uniqueUrls = {};
839839 for (var match in matches ) {
840840 var cleanUrl = trim (match );
841841 // Skip if it's already part of an href or src
842- if (! findNoCase (" href='#cleanUrl #" , result ) && ! findNoCase (' href="' & cleanUrl & ' "' , result ) && ! findNoCase (" src='#cleanUrl #" , result ) && ! findNoCase (' src="' & cleanUrl & ' "' , result )) {
842+ if (! findNoCase (" href='#cleanUrl #" , arguments . content ) && ! findNoCase (' href="' & cleanUrl & ' "' , arguments . content ) && ! findNoCase (" src='#cleanUrl #" , arguments . content ) && ! findNoCase (' src="' & cleanUrl & ' "' , arguments . content )) {
843843 uniqueUrls [cleanUrl ] = cleanUrl ;
844844 }
845845 }
846846
847- // Replace each unique URL
847+ // Separate embeddable and regular URLs
848+ var embeddedHtml = " " ;
849+ var bodyContent = arguments .content ;
850+ var embeddableUrls = [];
851+
848852 for (var link in uniqueUrls ) {
849853 if (isEmbeddableUrl (link )) {
850- var embedCode = getEmbedHtml (link );
854+ var embedCode = getEmbedHtml (link , " 100% " , " 600 " );
851855 if (len (embedCode )) {
852- result = replace (result , link , embedCode , " all" );
856+ arrayAppend (embeddableUrls , embedCode );
857+ // Remove the URL from body content
858+ bodyContent = replace (bodyContent , link , " " , " all" );
853859 }
854- } else {
860+ }
861+ }
862+
863+ // Build embedded content section at top
864+ if (arrayLen (embeddableUrls ) > 0 ) {
865+ embeddedHtml = ' <div class="embedded-media-section" style="margin-bottom: 2rem; border-bottom: 2px solid ## e9ecef; padding-bottom: 1.5rem;">' ;
866+ for (var embed in embeddableUrls ) {
867+ embeddedHtml & = ' <div class="embedded-media-item" style="margin-bottom: 1.5rem;">' & embed & ' </div>' ;
868+ }
869+ embeddedHtml & = ' </div>' ;
870+ }
871+
872+ // Process remaining regular URLs in body content
873+ for (var link in uniqueUrls ) {
874+ if (! isEmbeddableUrl (link )) {
855875 // Regular link
856876 var linkHtml = ' <a href="' & link & ' " class="' & arguments .class & ' " target="' & arguments .target & ' ">' & link & ' </a>' ;
857- result = replace (result , link , linkHtml , " all" );
877+ bodyContent = replace (bodyContent , link , linkHtml , " all" );
858878 }
859879 }
860880
861- return result ;
881+ return embeddedHtml & bodyContent ;
862882 }
863883}
0 commit comments