@cocreate/file-server 1.18.5 → 1.18.6

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,16 @@
1
+ ## [1.18.6](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.5...v1.18.6) (2025-10-08)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add handling for font files and improve error processing in CoCreateFileSystem ([de3c618](https://github.com/CoCreate-app/CoCreate-file-server/commit/de3c6186eebef00bfb6c237dc6d5c7435773ba41))
7
+ * correct pathname handling by ensuring language region is prefixed with a slash ([680832b](https://github.com/CoCreate-app/CoCreate-file-server/commit/680832b7cf710f48afd28a2fe2b425c7eb41d4b1))
8
+ * enhance language detection in pathname processing and support Accept-Language header ([cccc35d](https://github.com/CoCreate-app/CoCreate-file-server/commit/cccc35dc68107a5f39fbf2af053181825eb252fa))
9
+ * enhance language handling in pathname processing and improve file retrieval logic ([b499141](https://github.com/CoCreate-app/CoCreate-file-server/commit/b499141fe599e095a3d0a051ccede4b6131d3fa7))
10
+ * simplify pathname query handling in CoCreateFileSystem ([1632670](https://github.com/CoCreate-app/CoCreate-file-server/commit/1632670b17b7c76775094b2726178248e4e903d6))
11
+ * streamline HTML rendering logic by removing unnecessary language handling ([924041b](https://github.com/CoCreate-app/CoCreate-file-server/commit/924041bc4fba30fbeef5bcd85b6fe42f811af695))
12
+ * streamline language handling in pathname processing and simplify file retrieval logic ([fd43225](https://github.com/CoCreate-app/CoCreate-file-server/commit/fd432258880c33ba9f417d7a0d40eba8a9997863))
13
+
1
14
  ## [1.18.5](https://github.com/CoCreate-app/CoCreate-file-server/compare/v1.18.4...v1.18.5) (2025-09-02)
2
15
 
3
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/file-server",
3
- "version": "1.18.5",
3
+ "version": "1.18.6",
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
@@ -86,15 +86,32 @@ class CoCreateFileSystem {
86
86
  if (!directory.includes(".")) pathname += "/index.html";
87
87
  }
88
88
 
89
- const bcp47Regex = /^\/([a-zA-Z]{2,3}(?:-[a-zA-Z0-9]{2,8})+)\//;
90
- const match = pathname.match(bcp47Regex);
89
+ // Match both /en/ and /en-US/ style URLs
90
+ const bcp47Regex = /^\/([a-zA-Z]{2,3}(?:-[a-zA-Z0-9]{2,8})?)\//;
91
+ const langMatch = pathname.match(bcp47Regex);
91
92
  let lang, langRegion;
92
- if (match) {
93
- langRegion = match[1];
93
+ if (langMatch) {
94
+ langRegion = langMatch[1];
94
95
  lang = langRegion.split("-")[0]; // Get just the base language (e.g., 'en', 'es', 'fr')
95
- let newPathname = pathname.replace(langRegion, lang);
96
- data.$filter.query.pathname = { $in: [newPathname, pathname] };
96
+ let basePathname = pathname.replace("/" + langRegion, "");
97
+ data.$filter.query.pathname = basePathname;
97
98
  } else {
99
+ // No language in URL, try Accept-Language header
100
+ let acceptLang = req.headers && req.headers["accept-language"];
101
+ if (acceptLang) {
102
+ // Parse the Accept-Language header, get the first language
103
+ let preferred = acceptLang.split(",")[0].trim();
104
+ if (preferred) {
105
+ lang = preferred.split("-")[0];
106
+ langRegion = preferred;
107
+ // --- BEGIN OPTIONAL REDIRECT ---
108
+ // Uncomment to enable automatic redirect to language-specific path
109
+ // let newPath = `/${preferred}${pathname.startsWith('/') ? '' : '/'}${pathname.replace(/^\//, '')}`;
110
+ // res.writeHead(302, { Location: newPath });
111
+ // return res.end();
112
+ // --- END OPTIONAL REDIRECT ---
113
+ }
114
+ }
98
115
  data.$filter.query.pathname = pathname;
99
116
  }
100
117
 
@@ -182,7 +199,39 @@ class CoCreateFileSystem {
182
199
 
183
200
  let contentType = file["content-type"] || "text/html";
184
201
 
185
- if (
202
+ // Add handling for font files
203
+ if (contentType.startsWith("font/") || /\.(woff2?|ttf|otf)$/i.test(pathname)) {
204
+ try {
205
+ if (typeof src === "string") {
206
+ if (/^([A-Za-z0-9+/]+={0,2})$/.test(src)) {
207
+ // Decode base64-encoded font data
208
+ src = Buffer.from(src, "base64");
209
+ } else {
210
+ throw new Error("Font data is not valid base64");
211
+ }
212
+ } else if (typeof src === "object" && src.src) {
213
+ // Handle case where src is an object containing base64 data
214
+ if (/^([A-Za-z0-9+/]+={0,2})$/.test(src.src)) {
215
+ src = Buffer.from(src.src, "base64");
216
+ } else {
217
+ throw new Error("Font data inside object is not valid base64");
218
+ }
219
+ } else {
220
+ throw new Error("Font data is not a valid base64 string or object");
221
+ }
222
+ } catch (err) {
223
+ console.error("Error processing font file:", {
224
+ message: err.message,
225
+ contentType,
226
+ srcType: typeof src,
227
+ srcPreview: typeof src === "string" ? src.slice(0, 50) : null
228
+ });
229
+ let pageNotFound = await getDefaultFile("/404.html");
230
+ return sendResponse(pageNotFound.object[0].src, 404, {
231
+ "Content-Type": "text/html"
232
+ });
233
+ }
234
+ } else if (
186
235
  /^data:image\/[a-zA-Z0-9+.-]+;base64,([A-Za-z0-9+/]+={0,2})$/.test(
187
236
  src
188
237
  )
@@ -193,14 +242,15 @@ class CoCreateFileSystem {
193
242
  src = Buffer.from(src, "base64");
194
243
  } else if (contentType === "text/html") {
195
244
  try {
196
- file.urlObject = urlObject;
197
- if (langRegion) {
198
- file.langRegion = langRegion;
199
- }
200
- if (lang) {
201
- file.lang = lang;
202
- }
203
- src = await this.render.HTML(file);
245
+ let data = {};
246
+
247
+ src = await this.render.HTML(
248
+ file,
249
+ organization,
250
+ urlObject,
251
+ langRegion,
252
+ lang
253
+ );
204
254
  } catch (err) {
205
255
  console.warn("server-side-render: " + err.message);
206
256
  }
@@ -226,10 +276,7 @@ class CoCreateFileSystem {
226
276
  file["cache-control"] !== null
227
277
  ) {
228
278
  const val = file["cache-control"];
229
- if (
230
- typeof val === "number" ||
231
- /^\s*\d+\s*$/.test(val)
232
- ) {
279
+ if (typeof val === "number" || /^\s*\d+\s*$/.test(val)) {
233
280
  // If it's numeric (number or numeric string) treat it as max-age.
234
281
  cacheControl = `public, max-age=${String(
235
282
  val
@@ -239,19 +286,14 @@ class CoCreateFileSystem {
239
286
  cacheControl = val;
240
287
  }
241
288
  } else {
242
- cacheControl =
243
- organization["cache-control"] ||
244
- "public, max-age=3600";
289
+ cacheControl = organization["cache-control"] || "public, max-age=3600";
245
290
  }
246
291
 
247
292
  // Always override/set Cache-Control header so the response aligns with the file metadata/defaults
248
293
  headers["Cache-Control"] = cacheControl;
249
294
 
250
- if (src instanceof Uint8Array) {
251
- src = Buffer.from(src);
252
- } else if (Buffer.isBuffer(src)) {
253
- // Buffer is fine to send — don't bail out here (previous code returned early)
254
- // keep src as-is
295
+ if (src instanceof Uint8Array || Buffer.isBuffer(src)) {
296
+ // Ensure binary data is sent as-is
255
297
  } else if (typeof src === "object") {
256
298
  src = JSON.stringify(src);
257
299
  }