11const { parse } = require ( "node-html-parser" ) ;
2- const { checkValue } = require ( "@cocreate/utils" ) ;
2+ const { checkValue, ObjectId } = require ( "@cocreate/utils" ) ;
3+ const path = require ( "path" ) ;
34
45class CoCreateServerSideRender {
56 constructor ( crud ) {
@@ -90,53 +91,64 @@ class CoCreateServerSideRender {
9091
9192 // ToDo: Fetch and render src, update relativePath. must have similar functionality to @cocreate/elements/fetch-src
9293 // Handle elements with [src]
93- // for (let el of dom.querySelectorAll(
94- // "[src]:not(script, img, iframe, audio, video, source, track, input, embed, frame)"
95- // )) {
96- // let src = el.getAttribute("src");
97- // if (!src) continue;
98-
99- // // Construct actual pathname using src and the original URL
100- // let basePath = new URL(url).pathname;
101- // let resolvedPathname = new URL(
102- // src,
103- // `http://localhost${basePath}`
104- // ).pathname;
105-
106- // if (resolvedPathname.endsWith("/")) {
107- // resolvedPathname += "index.html";
108- // }
109- // let $filter = {
110- // query: {
111- // pathname: resolvedPathname
112- // }
113- // }; // Use filter to structure query
114-
115- // let data = await self.crud.send({
116- // method: "object.read",
117- // array: "files",
118- // object: "",
119- // $filter,
120- // organization_id
121- // });
122-
123- // if (
124- // data &&
125- // data.object &&
126- // data.object[0] &&
127- // data.object[0].src
128- // ) {
129- // let chunk = data.object[0].src;
130- // let path = el.getAttribute("path");
131- // if (path) chunk = chunk.replaceAll("{{path}}", path);
132-
133- // chunk = await render(chunk);
134-
135- // el.setAttribute("rendered", "");
136- // el.innerHTML = "";
137- // el.appendChild(chunk);
138- // }
139- // }
94+ for ( let el of dom . querySelectorAll (
95+ "[src]:not(script, img, iframe, audio, video, source, track, input, embed, frame)"
96+ ) ) {
97+ let src = el . getAttribute ( "src" ) ;
98+ if ( ! src ) continue ;
99+
100+ // Construct actual pathname using src and the original URL
101+ let basePath = new URL ( url ) . pathname ;
102+ let resolvedPathname = new URL (
103+ src ,
104+ `http://localhost${ basePath } `
105+ ) . pathname ;
106+
107+ if ( resolvedPathname . endsWith ( "/" ) ) {
108+ resolvedPathname += "index.html" ;
109+ }
110+ let $filter = {
111+ query : {
112+ pathname : resolvedPathname
113+ }
114+ } ; // Use filter to structure query
115+
116+ let data = await self . crud . send ( {
117+ method : "object.read" ,
118+ array : "files" ,
119+ object : "" ,
120+ $filter,
121+ organization_id
122+ } ) ;
123+
124+ if (
125+ data &&
126+ data . object &&
127+ data . object [ 0 ] &&
128+ data . object [ 0 ] . src
129+ ) {
130+ let chunk = data . object [ 0 ] . src ;
131+
132+ // Replace $relativePath in the fetched chunk
133+ let path =
134+ el . getAttribute ( "path" ) || getRelativePath ( file . path ) ;
135+ if ( path ) {
136+ chunk = chunk . replaceAll ( / \$ r e l a t i v e P a t h \/ ? / g, path ) ;
137+ }
138+
139+ // Replace ObjectId() with a new ObjectId
140+ chunk = chunk . replaceAll ( "ObjectId()" , ( ) => {
141+ // Generate a NEW ObjectId inside the function
142+ return ObjectId ( ) . toString ( ) ; // Return its string representation
143+ } ) ;
144+
145+ chunk = await render ( chunk ) ;
146+
147+ el . setAttribute ( "rendered" , "" ) ;
148+ el . innerHTML = "" ;
149+ el . appendChild ( chunk ) ;
150+ }
151+ }
140152
141153 return dom ;
142154 }
@@ -145,16 +157,18 @@ class CoCreateServerSideRender {
145157 dom = await render ( dom , "root" ) ;
146158 if ( file . langRegion || file . lang ) {
147159 dom = await this . translate ( dom , file ) ;
148- // ToDo: Off by default. some attribute to activate language links. For performance use src to fetch a pre-rendered version
149- // <link rel="alternate" hreflang="x-default" href="https://example.com/en/index.html">
150- let langLinkTags = this . createLanguageLinkTags ( file ) ;
151- const head = dom . querySelector ( "head" ) ;
152- if ( head && langLinkTags ) {
153- const linksFragment = parse (
154- `<fragment>${ langLinkTags } </fragment>`
155- ) ;
156- for ( const link of linksFragment . childNodes ) {
157- head . appendChild ( link ) ;
160+ // <link rel="alternate" hreflang="x-default" href="https://example.com/en/index.html" language-links>
161+ let isLangLinkTags = dom . querySelector ( "[language-links]" ) ;
162+ if ( isLangLinkTags ) {
163+ let langLinkTags = this . createLanguageLinkTags ( file ) ;
164+ const head = dom . querySelector ( "head" ) ;
165+ if ( head && langLinkTags ) {
166+ const linksFragment = parse (
167+ `<fragment>${ langLinkTags } </fragment>`
168+ ) ;
169+ for ( const link of linksFragment . childNodes ) {
170+ head . appendChild ( link ) ;
171+ }
158172 }
159173 }
160174 }
@@ -163,6 +177,14 @@ class CoCreateServerSideRender {
163177 return dom . toString ( ) ;
164178 }
165179
180+ getRelativePath ( path ) {
181+ if ( ! path . endsWith ( "/" ) ) {
182+ path += "/" ;
183+ }
184+ let depth = path . split ( "/" ) . filter ( Boolean ) . length ;
185+ return depth > 0 ? "../" . repeat ( depth ) : "./" ;
186+ }
187+
166188 createLanguageLinkTags ( file ) {
167189 let xDefault = file . path ;
168190
0 commit comments