@cocreate/file-server 1.18.7 → 1.18.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.18.9](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.8...v1.18.9) (2025-10-11)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add theme detection and handling for preferred color scheme in responses ([484a37c](https://github.com/CoCreate-app/CoCreate-file-server/commit/484a37c3f35b397a3baff0d9dc62c338a0135903))
7
+
8
+ ## [1.18.8](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.7...v1.18.8) (2025-10-11)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * improve file content decoding and enhance font handling logic ([8bddb02](https://github.com/CoCreate-app/CoCreate-file-server/commit/8bddb0249c9748a90ac1442073ba464a053d9074))
14
+
1
15
  ## [1.18.7](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.6...v1.18.7) (2025-10-08)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/file-server",
3
- "version": "1.18.7",
3
+ "version": "1.18.9",
4
4
  "description": "A simple file-server component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "file-server",
package/src/index.js CHANGED
@@ -30,6 +30,24 @@ class CoCreateFileSystem {
30
30
  try {
31
31
  const hostname = urlObject.hostname;
32
32
 
33
+ // --- determine preferred color scheme from browser headers ---
34
+ let theme;
35
+ const headerValue =
36
+ (req && req.headers && (
37
+ req.headers["sec-ch-prefers-color-scheme"] ||
38
+ req.headers["prefers-color-scheme"] ||
39
+ req.headers["x-prefers-color-scheme"] ||
40
+ req.headers["x-color-scheme"]
41
+ ));
42
+ if (typeof headerValue === "string") {
43
+ // take first token, strip quotes, normalize
44
+ const token = headerValue.split(",")[0].trim().replace(/^"|"$/g, "").toLowerCase();
45
+ if (token === "dark" || token === "light") theme = token;
46
+ }
47
+ // optional: expose detected theme to clients / downstream code
48
+ if (theme) res.setHeader("X-Preferred-Color-Scheme", theme);
49
+ // --- end theme detection ---
50
+
33
51
  let data = {
34
52
  method: "object.read",
35
53
  host: hostname,
@@ -199,35 +217,13 @@ class CoCreateFileSystem {
199
217
 
200
218
  let contentType = file["content-type"] || "text/html";
201
219
 
202
- try {
203
- if (typeof src === "string") {
204
- // Decode the file content based on its MIME type
205
- if (/^(image|audio|video|font|application\/octet-stream|application\/x-font-ttf|application\/x-font-woff|application\/x-font-woff2|application\/x-font-opentype|application\/x-font-truetype|application\/x-font-eot)/.test(contentType)) {
206
- src = Buffer.from(src, "base64");
207
- } else if (/^(application\/zip|application\/x-7z-compressed|application\/x-rar-compressed|application\/pdf)/.test(contentType)) {
208
- src = Buffer.from(src, "binary");
209
- } else {
210
- src = Buffer.from(src, "utf8");
211
- }
212
- } else {
213
- throw new Error("File content is not in a valid format");
214
- }
215
- } catch (err) {
216
- console.error("Error decoding file content:", {
217
- message: err.message,
218
- contentType,
219
- srcType: typeof src
220
- });
221
- let pageNotFound = await getDefaultFile("/404.html");
222
- return sendResponse(pageNotFound.object[0].src, 404, {
223
- "Content-Type": "text/html"
224
- });
225
- }
226
-
227
220
  // Remove redundant handling for `src.src` in font file processing
228
221
  if (contentType.startsWith("font/") || /\.(woff2?|ttf|otf)$/i.test(pathname)) {
229
222
  try {
230
223
  if (typeof src === "string") {
224
+ if (src.startsWith("data:font/")) {
225
+ src = src.substring(src.indexOf(",") + 1);
226
+ }
231
227
  if (/^([A-Za-z0-9+/]+={0,2})$/.test(src)) {
232
228
  // Decode base64-encoded font data
233
229
  src = Buffer.from(src, "base64");
@@ -261,12 +257,14 @@ class CoCreateFileSystem {
261
257
  try {
262
258
  let data = {};
263
259
 
260
+ // pass detected theme (may be undefined) into server-side renderer
264
261
  src = await this.render.HTML(
265
262
  file,
266
263
  organization,
267
264
  urlObject,
268
265
  langRegion,
269
- lang
266
+ lang,
267
+ theme
270
268
  );
271
269
  } catch (err) {
272
270
  console.warn("server-side-render: " + err.message);
@@ -275,10 +273,10 @@ class CoCreateFileSystem {
275
273
  contentType === "text/xml" ||
276
274
  contentType === "application/xml"
277
275
  ) {
278
- const protocol = "https://"; // || req.headers['x-forwarded-proto'] || req.protocol;
276
+ const protocol = "https://";
279
277
  src = src.replaceAll("{{$host}}", `${protocol}${hostname}`);
280
- } else {
281
- // Log unknown file types
278
+ } else if (contentType !== "text/javascript" || contentType === "text/css") {
279
+
282
280
  console.warn(`Unknown content type: ${contentType}`);
283
281
  }
284
282
 
@@ -311,6 +309,16 @@ class CoCreateFileSystem {
311
309
 
312
310
  // Always override/set Cache-Control header so the response aligns with the file metadata/defaults
313
311
  headers["Cache-Control"] = cacheControl;
312
+ // Advertise that we accept the Sec-CH-Prefers-Color-Scheme client hint.
313
+ // After the browser sees this in a response it may include
314
+ // the Sec-CH-Prefers-Color-Scheme header on subsequent requests.
315
+ headers["Accept-CH"] = "Sec-CH-Prefers-Color-Scheme";
316
+ // optional: tell browser how long to remember this preference (seconds)
317
+ headers["Accept-CH-Lifetime"] = "86400";
318
+ // ensure caches/proxies vary responses by this hint
319
+ headers["Vary"] = headers["Vary"]
320
+ ? headers["Vary"] + ", Sec-CH-Prefers-Color-Scheme"
321
+ : "Sec-CH-Prefers-Color-Scheme";
314
322
 
315
323
  if (src instanceof Uint8Array || Buffer.isBuffer(src)) {
316
324
  // Ensure binary data is sent as-is