Skip to content

Commit 1dc2bb6

Browse files
committed
fix: enhance src handling and language link tag creation in HTML rendering
1 parent 0429a37 commit 1dc2bb6

File tree

1 file changed

+80
-58
lines changed

1 file changed

+80
-58
lines changed

src/index.js

Lines changed: 80 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { parse } = require("node-html-parser");
2-
const { checkValue } = require("@cocreate/utils");
2+
const { checkValue, ObjectId } = require("@cocreate/utils");
3+
const path = require("path");
34

45
class 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(/\$relativePath\/?/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

Comments
 (0)