@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.js CHANGED
@@ -514,6 +514,36 @@ var SAFE_ASSET_TYPES = /* @__PURE__ */ new Set([
514
514
  "data",
515
515
  "unknown"
516
516
  ]);
517
+ var SAFE_EXTENSIONS = /* @__PURE__ */ new Set([
518
+ // Images
519
+ "png",
520
+ "jpg",
521
+ "jpeg",
522
+ "webp",
523
+ "gif",
524
+ "avif",
525
+ "svg",
526
+ "bmp",
527
+ "ico",
528
+ // Audio
529
+ "mp3",
530
+ "wav",
531
+ "ogg",
532
+ "flac",
533
+ "m4a",
534
+ "aac",
535
+ "opus",
536
+ // Video
537
+ "mp4",
538
+ "webm",
539
+ "avi",
540
+ "mov",
541
+ "mkv",
542
+ // Data
543
+ "json",
544
+ "txt",
545
+ "bin"
546
+ ]);
517
547
  function getCharxCategory(mimetype) {
518
548
  if (mimetype.startsWith("image/")) return "images";
519
549
  if (mimetype.startsWith("audio/")) return "audio";
@@ -529,20 +559,11 @@ function sanitizeAssetType(type) {
529
559
  return sanitized || "custom";
530
560
  }
531
561
  function sanitizeExtension(ext) {
532
- const normalized = ext.trim().replace(/^\./, "").toLowerCase();
533
- if (!normalized) {
534
- throw new Error("Invalid asset extension: empty extension");
535
- }
536
- if (normalized.length > 64) {
537
- throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
538
- }
539
- if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
540
- throw new Error("Invalid asset extension: path separators are not allowed");
541
- }
542
- if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
543
- throw new Error(`Invalid asset extension: "${ext}"`);
562
+ const normalized = ext.replace(/^\./, "").toLowerCase().replace(/[^a-z0-9]/g, "");
563
+ if (SAFE_EXTENSIONS.has(normalized)) {
564
+ return normalized;
544
565
  }
545
- return normalized;
566
+ return "bin";
546
567
  }
547
568
  function sanitizeName(name, ext) {
548
569
  let safeName = name;
@@ -6993,22 +7014,6 @@ function sanitizeName2(name, ext) {
6993
7014
  if (!safeName) safeName = "asset";
6994
7015
  return safeName;
6995
7016
  }
6996
- function sanitizeExtension2(ext) {
6997
- const normalized = ext.trim().replace(/^\./, "").toLowerCase();
6998
- if (!normalized) {
6999
- throw new Error("Invalid asset extension: empty extension");
7000
- }
7001
- if (normalized.length > 64) {
7002
- throw new Error(`Invalid asset extension: too long (${normalized.length} chars)`);
7003
- }
7004
- if (normalized.includes("/") || normalized.includes("\\") || normalized.includes("\0")) {
7005
- throw new Error("Invalid asset extension: path separators are not allowed");
7006
- }
7007
- if (!/^[a-z0-9][a-z0-9._-]*$/.test(normalized)) {
7008
- throw new Error(`Invalid asset extension: "${ext}"`);
7009
- }
7010
- return normalized;
7011
- }
7012
7017
  function writeVoxta(card, assets, options = {}) {
7013
7018
  const { compressionLevel = 6, includePackageJson = false } = options;
7014
7019
  const cardData = card.data;
@@ -7097,9 +7102,8 @@ function writeVoxta(card, assets, options = {}) {
7097
7102
  let assetCount = 0;
7098
7103
  let mainThumbnail;
7099
7104
  for (const asset of assets) {
7100
- const safeExt = sanitizeExtension2(asset.ext);
7101
- const safeName = sanitizeName2(asset.name, safeExt);
7102
- const finalFilename = `${safeName}.${safeExt}`;
7105
+ const safeName = sanitizeName2(asset.name, asset.ext);
7106
+ const finalFilename = `${safeName}.${asset.ext}`;
7103
7107
  let voxtaPath = "";
7104
7108
  const tags = asset.tags || [];
7105
7109
  const isMainIcon = asset.type === "icon" && (tags.includes("portrait-override") || asset.name === "main" || asset.isMain);