@@ -598,7 +598,10 @@ export const generateFragmentFromHtml = (
598598 // Map of instanceId → resolved class names (for post-processing token assignments)
599599 const instanceTokenClasses = new Map < string , string [ ] > ( ) ;
600600
601- const convertElementToInstance = ( node : ElementNode ) => {
601+ const convertElementToInstance = (
602+ node : ElementNode ,
603+ { preserveLeadingSpace = false } : { preserveLeadingSpace ?: boolean } = { }
604+ ) => {
602605 if ( node . tagName === "script" && node . sourceCodeLocation ) {
603606 const { startCol, startOffset, endOffset } = node . sourceCodeLocation ;
604607 const indent = startCol - 1 ;
@@ -859,7 +862,13 @@ export const generateFragmentFromHtml = (
859862 for ( let index = 0 ; index < node . childNodes . length ; index += 1 ) {
860863 const childNode = node . childNodes [ index ] ;
861864 if ( defaultTreeAdapter . isElementNode ( childNode ) ) {
862- const child = convertElementToInstance ( childNode ) ;
865+ const lastChild = instance . children . at ( - 1 ) ;
866+ const nextPreserveLeadingSpace =
867+ instance . children . length > 0 &&
868+ ! ( lastChild ?. type === "text" && lastChild . value . endsWith ( " " ) ) ;
869+ const child = convertElementToInstance ( childNode , {
870+ preserveLeadingSpace : nextPreserveLeadingSpace ,
871+ } ) ;
863872 if ( child ) {
864873 instance . children . push ( child ) ;
865874 }
@@ -880,7 +889,9 @@ export const generateFragmentFromHtml = (
880889 // collapse spacing characters inside of text to avoid preserved newlines
881890 child . value = child . value . replaceAll ( / \s + / g, " " ) ;
882891 // remove unnecessary spacing in nodes
883- if ( index === 0 ) {
892+ // skip trimStart if the parent signaled that leading space is semantic
893+ // (e.g. `<span> Us</span>` following `About` with no intervening space)
894+ if ( index === 0 && ! preserveLeadingSpace ) {
884895 child . value = child . value . trimStart ( ) ;
885896 }
886897 if ( index === node . childNodes . length - 1 ) {
0 commit comments