@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/exporter.cjs CHANGED
@@ -546,6 +546,36 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
546
546
  "data",
547
547
  "unknown"
548
548
  ]);
549
+ var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
550
+ // Images
551
+ "png",
552
+ "jpg",
553
+ "jpeg",
554
+ "webp",
555
+ "gif",
556
+ "avif",
557
+ "svg",
558
+ "bmp",
559
+ "ico",
560
+ // Audio
561
+ "mp3",
562
+ "wav",
563
+ "ogg",
564
+ "flac",
565
+ "m4a",
566
+ "aac",
567
+ "opus",
568
+ // Video
569
+ "mp4",
570
+ "webm",
571
+ "avi",
572
+ "mov",
573
+ "mkv",
574
+ // Data
575
+ "json",
576
+ "txt",
577
+ "bin"
578
+ ]);
549
579
  function getCharxCategory(mimetype) {
550
580
  if (mimetype.startsWith("image/")) return "images";
551
581
  if (mimetype.startsWith("audio/")) return "audio";
@@ -561,20 +591,11 @@ function sanitizeAssetType(type) {
561
591
  return sanitized || "custom";
562
592
  }
563
593
  function sanitizeExtension(ext) {
564
- const normalized = ext.trim().replace(/^\./, "").toLowerCase();
565
- if (!normalized) {
566
- throw new Error("Invalid asset extension: empty extension");
567
- }
568
- if (normalized.length > 64) {
569
- throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
570
- }
571
- if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
572
- throw new Error("Invalid asset extension: path separators are not allowed");
573
- }
574
- if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
575
- throw new Error(`Invalid asset extension: "${ext}"`);
594
+ const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
595
+ if (SAFE_EXTENSIONS.has(normalized)) {
596
+ return normalized;
576
597
  }
577
- return normalized;
598
+ return "bin";
578
599
  }
579
600
  function sanitizeName(name, ext) {
580
601
  let safeName = name;
@@ -7025,22 +7046,6 @@ function sanitizeName2(name, ext) {
7025
7046
  if (!safeName) safeName = "asset";
7026
7047
  return safeName;
7027
7048
  }
7028
- function sanitizeExtension2(ext) {
7029
- const normalized = ext.trim().replace(/^\./, "").toLowerCase();
7030
- if (!normalized) {
7031
- throw new Error("Invalid asset extension: empty extension");
7032
- }
7033
- if (normalized.length > 64) {
7034
- throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
7035
- }
7036
- if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
7037
- throw new Error("Invalid asset extension: path separators are not allowed");
7038
- }
7039
- if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
7040
- throw new Error(`Invalid asset extension: "${ext}"`);
7041
- }
7042
- return normalized;
7043
- }
7044
7049
  function writeVoxta(card, assets, options = {}) {
7045
7050
  const { compressionLevel = 6, includePackageJson = false } = options;
7046
7051
  const cardData = card.data;
@@ -7129,9 +7134,8 @@ function writeVoxta(card, assets, options = {}) {
7129
7134
  let assetCount = 0;
7130
7135
  let mainThumbnail;
7131
7136
  for (const asset of assets) {
7132
- const safeExt = sanitizeExtension2(asset.ext);
7133
- const safeName = sanitizeName2(asset.name, safeExt);
7134
- const finalFilename = `${safeName}.${safeExt}`;
7137
+ const safeName = sanitizeName2(asset.name, asset.ext);
7138
+ const finalFilename = `${safeName}.${asset.ext}`;
7135
7139
  let voxtaPath = "";
7136
7140
  const tags = asset.tags || [];
7137
7141
  const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);