@character-foundry/character-foundry 0.4.3-dev.1766019473 → 0.4.3

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/dist/index.cjs CHANGED
@@ -1363,6 +1363,36 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
1363
1363
  "data",
1364
1364
  "unknown"
1365
1365
  ]);
1366
+ var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
1367
+ // Images
1368
+ "png",
1369
+ "jpg",
1370
+ "jpeg",
1371
+ "webp",
1372
+ "gif",
1373
+ "avif",
1374
+ "svg",
1375
+ "bmp",
1376
+ "ico",
1377
+ // Audio
1378
+ "mp3",
1379
+ "wav",
1380
+ "ogg",
1381
+ "flac",
1382
+ "m4a",
1383
+ "aac",
1384
+ "opus",
1385
+ // Video
1386
+ "mp4",
1387
+ "webm",
1388
+ "avi",
1389
+ "mov",
1390
+ "mkv",
1391
+ // Data
1392
+ "json",
1393
+ "txt",
1394
+ "bin"
1395
+ ]);
1366
1396
  function getCharxCategory(mimetype) {
1367
1397
  if (mimetype.startsWith("image/")) return "images";
1368
1398
  if (mimetype.startsWith("audio/")) return "audio";
@@ -1378,20 +1408,11 @@ function sanitizeAssetType(type) {
1378
1408
  return sanitized || "custom";
1379
1409
  }
1380
1410
  function sanitizeExtension(ext) {
1381
- const normalized = ext.trim().replace(/^\./, "").toLowerCase();
1382
- if (!normalized) {
1383
- throw new Error("Invalid asset extension: empty extension");
1384
- }
1385
- if (normalized.length > 64) {
1386
- throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
1387
- }
1388
- if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
1389
- throw new Error("Invalid asset extension: path separators are not allowed");
1390
- }
1391
- if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
1392
- throw new Error(`Invalid asset extension: "${ext}"`);
1411
+ const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
1412
+ if (SAFE_EXTENSIONS.has(normalized)) {
1413
+ return normalized;
1393
1414
  }
1394
- return normalized;
1415
+ return "bin";
1395
1416
  }
1396
1417
  function sanitizeName(name, ext) {
1397
1418
  let safeName = name;
@@ -8173,22 +8194,6 @@ function sanitizeName2(name, ext) {
8173
8194
  if (!safeName) safeName = "asset";
8174
8195
  return safeName;
8175
8196
  }
8176
- function sanitizeExtension2(ext) {
8177
- const normalized = ext.trim().replace(/^\./, "").toLowerCase();
8178
- if (!normalized) {
8179
- throw new Error("Invalid asset extension: empty extension");
8180
- }
8181
- if (normalized.length > 64) {
8182
- throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
8183
- }
8184
- if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
8185
- throw new Error("Invalid asset extension: path separators are not allowed");
8186
- }
8187
- if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
8188
- throw new Error(`Invalid asset extension: "${ext}"`);
8189
- }
8190
- return normalized;
8191
- }
8192
8197
  function writeVoxta(card, assets, options = {}) {
8193
8198
  const { compressionLevel = 6, includePackageJson = false } = options;
8194
8199
  const cardData = card.data;
@@ -8277,9 +8282,8 @@ function writeVoxta(card, assets, options = {}) {
8277
8282
  let assetCount = 0;
8278
8283
  let mainThumbnail;
8279
8284
  for (const asset of assets) {
8280
- const safeExt = sanitizeExtension2(asset.ext);
8281
- const safeName = sanitizeName2(asset.name, safeExt);
8282
- const finalFilename = `${safeName}.${safeExt}`;
8285
+ const safeName = sanitizeName2(asset.name, asset.ext);
8286
+ const finalFilename = `${safeName}.${asset.ext}`;
8283
8287
  let voxtaPath = "";
8284
8288
  const tags = asset.tags || [];
8285
8289
  const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);