@@ -6,7 +6,7 @@ class CoCreateServerSideRender {
66 this . crud = crud ;
77 }
88
9- async HTML ( html , organization_id , url ) {
9+ async HTML ( file ) {
1010 const self = this ;
1111 let ignoreElement = {
1212 INPUT : true ,
@@ -20,9 +20,7 @@ class CoCreateServerSideRender {
2020 let dep = [ ] ;
2121 let dbCache = new Map ( ) ;
2222
23- async function render ( html , lastKey ) {
24- const dom = parse ( html ) ;
25-
23+ async function render ( dom , lastKey ) {
2624 // Handle elements with [array][key][object]
2725 for ( let el of dom . querySelectorAll ( "[array][key][object]" ) ) {
2826 let meta = el . attributes ;
@@ -32,14 +30,7 @@ class CoCreateServerSideRender {
3230 if ( el . closest ( ".template, [template], template, [render]" ) )
3331 continue ;
3432
35- if (
36- el . hasAttribute ( "render-selector" ) ||
37- el . hasAttribute ( "render-closest" ) ||
38- el . hasAttribute ( "render-parent" ) ||
39- el . hasAttribute ( "render-next" ) ||
40- el . hasAttribute ( "render-previous" )
41- )
42- continue ;
33+ if ( el . hasAttribute ( "render-query" ) ) continue ;
4334
4435 if ( el . hasAttribute ( "component" ) || el . hasAttribute ( "plugin" ) )
4536 continue ;
@@ -149,10 +140,91 @@ class CoCreateServerSideRender {
149140 return dom ;
150141 }
151142
152- let result = await render ( html , "root" ) ;
143+ let dom = parse ( file . src ) ;
144+ dom = await render ( dom , "root" ) ;
145+ if ( file . langRegion || file . lang ) {
146+ dom = translate ( dom , file ) ;
147+ let langLinkTags = createLanguageLinkTags ( file ) ;
148+ const head = dom . querySelector ( "head" ) ;
149+ if ( head && langLinkTags ) {
150+ const linksFragment = parse (
151+ `<fragment>${ langLinkTags } </fragment>`
152+ ) ;
153+ for ( const link of linksFragment . childNodes ) {
154+ head . appendChild ( link ) ;
155+ }
156+ }
157+ }
153158 dep = [ ] ;
154159 dbCache . clear ( ) ;
155- return result . toString ( ) ;
160+ return dom . toString ( ) ;
161+ }
162+
163+ createLanguageLinkTags ( file ) {
164+ let xDefault = file . path ;
165+
166+ if ( file . name !== "index.html" ) {
167+ if ( xDefault . endsWith ( "/" ) ) {
168+ xDefault += file . name ;
169+ } else {
170+ xDefault += "/" + file . name ;
171+ }
172+ }
173+ let generatedLinksString = `<link rel="alternate" hreflang="x-default" href="${ xDefault } ">\n` ;
174+
175+ // Step 1: Create a lookup object that maps base language to its path.
176+ // This is done once for efficiency.
177+ const paths = { } ;
178+ for ( const p of file . pathname ) {
179+ const secondSlashIndex = p . indexOf ( "/" , 1 ) ;
180+ const langKey = p . substring ( 1 , secondSlashIndex ) ; // e.g., 'en', 'es', 'pt'
181+ const restOfPath = p . substring ( secondSlashIndex ) ;
182+ paths [ langKey ] = restOfPath ;
183+ }
184+
185+ // Step 2: Iterate through all supported languages and build the HTML string.
186+ for ( const language of file . languages ) {
187+ // Use the base language to find the correct path in our map
188+ const path = paths [ language ] || paths [ language . split ( "-" ) [ 0 ] ] ;
189+
190+ // If a valid path exists, construct the full link
191+ if ( path ) {
192+ // Construct the full href URL using the full language code from the array
193+ const hrefUrl = `https://${ file . urlObject . hostname } /${ language } ${ path } ` ;
194+
195+ // Append the HTML string. The hreflang and the URL path are now in sync.
196+ generatedLinksString += `<link rel="alternate" hreflang="${ language } " href="${ hrefUrl } ">\n` ;
197+ }
198+ }
199+ return generatedLinksString ;
200+ }
201+
202+ async translate ( dom , file ) {
203+ let langRegion = file . langRegion ;
204+ let lang = file . lang ;
205+ if ( file . translations & ( langRegion || lang ) ) {
206+ for ( let translation of file . translations ) {
207+ let el = dom . querySelectorAll ( translation . selector ) ;
208+ if ( translation . innerHTML ) {
209+ let content =
210+ translation . innerHTML [ langRegion ] ||
211+ translation . innerHTML [ lang ] ;
212+ if ( content ) {
213+ el . innerHTML = content ;
214+ }
215+ }
216+ if ( translation . attributes ) {
217+ for ( let [ key , language ] of Object . entries (
218+ translation . attributes
219+ ) ) {
220+ let value = language [ langRegion ] || language [ lang ] ;
221+ if ( value ) {
222+ el . setAttribute ( key , value ) ;
223+ }
224+ }
225+ }
226+ }
227+ }
156228 }
157229}
158230
0 commit comments