@character-foundry/character-foundry 0.1.8 → 0.1.9-dev.1765913722

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/loader.cjs CHANGED
@@ -134,7 +134,23 @@ function streamingUnzipSync(data, limits = DEFAULT_ZIP_LIMITS) {
134
134
  if (unsafePathHandling === "warn" && limits.onUnsafePath) {
135
135
  limits.onUnsafePath(file.name, reason);
136
136
  }
137
- file.ondata = () => {
137
+ file.ondata = (err, chunk, _final) => {
138
+ if (error) return;
139
+ if (err) {
140
+ error = err;
141
+ return;
142
+ }
143
+ if (chunk && chunk.length > 0) {
144
+ totalBytes += chunk.length;
145
+ if (totalBytes > limits.maxTotalSize) {
146
+ error = new ZipPreflightError(
147
+ `Total actual size ${totalBytes} exceeds limit ${limits.maxTotalSize}`,
148
+ totalBytes,
149
+ limits.maxTotalSize
150
+ );
151
+ file.terminate();
152
+ }
153
+ }
138
154
  };
139
155
  file.start();
140
156
  return;
@@ -8182,6 +8198,43 @@ var DEFAULT_OPTIONS3 = {
8182
8198
  maxTotalSize: 500 * 1024 * 1024,
8183
8199
  extractAssets: true
8184
8200
  };
8201
+ var ASSET_PREFIX_VARIANTS = [
8202
+ { prefix: "__asset:", format: "CCv3 (SillyTavern)" },
8203
+ { prefix: "asset:", format: "CCv2/CCv3 common" },
8204
+ { prefix: "pngchunk:", format: "Explicit PNG chunk" },
8205
+ { prefix: "chara-ext-asset_:", format: "RisuAI (with colon)" },
8206
+ { prefix: "chara-ext-asset_", format: "RisuAI" },
8207
+ { prefix: "__asset_", format: "Legacy underscore variant" }
8208
+ ];
8209
+ function isChunkReference(uri) {
8210
+ return ASSET_PREFIX_VARIANTS.some(({ prefix }) => uri.startsWith(prefix)) || !uri.includes(":");
8211
+ }
8212
+ function stripAssetPrefix(uri) {
8213
+ for (const { prefix } of ASSET_PREFIX_VARIANTS) {
8214
+ if (uri.startsWith(prefix)) {
8215
+ return uri.substring(prefix.length);
8216
+ }
8217
+ }
8218
+ return uri;
8219
+ }
8220
+ function generateChunkKeyCandidates(assetId, originalUri) {
8221
+ return [
8222
+ assetId,
8223
+ // Plain ID: "0"
8224
+ originalUri,
8225
+ // Original URI: "__asset:0"
8226
+ `asset:${assetId}`,
8227
+ // Common format
8228
+ `__asset:${assetId}`,
8229
+ // CCv3 format
8230
+ `__asset_${assetId}`,
8231
+ // Legacy underscore variant
8232
+ `chara-ext-asset_${assetId}`,
8233
+ // RisuAI format
8234
+ `chara-ext-asset_:${assetId}`
8235
+ // RisuAI format with colon
8236
+ ];
8237
+ }
8185
8238
  function estimateBase64DecodedSize(base64Length) {
8186
8239
  return Math.ceil(base64Length * 0.75);
8187
8240
  }
@@ -8249,39 +8302,22 @@ function parsePng(data, options) {
8249
8302
  if (extracted.extraChunks && options.extractAssets && card.data.assets) {
8250
8303
  const usedChunks = /* @__PURE__ */ new Set();
8251
8304
  const chunkMap = /* @__PURE__ */ new Map();
8305
+ const risuIndexPrefixes = ASSET_PREFIX_VARIANTS.filter((v) => v.prefix.startsWith("chara-ext-asset_"));
8252
8306
  for (const chunk of extracted.extraChunks) {
8253
8307
  chunkMap.set(chunk.keyword, chunk);
8254
- if (chunk.keyword.startsWith("chara-ext-asset_")) {
8255
- const suffix = chunk.keyword.replace("chara-ext-asset_", "");
8256
- chunkMap.set(suffix, chunk);
8257
- if (suffix.startsWith(":")) {
8258
- chunkMap.set(suffix.substring(1), chunk);
8308
+ for (const { prefix } of risuIndexPrefixes) {
8309
+ if (chunk.keyword.startsWith(prefix)) {
8310
+ const suffix = chunk.keyword.substring(prefix.length);
8311
+ chunkMap.set(suffix, chunk);
8312
+ break;
8259
8313
  }
8260
8314
  }
8261
8315
  }
8262
8316
  for (const descriptor of card.data.assets) {
8263
8317
  if (!descriptor.uri) continue;
8264
- if (descriptor.uri.startsWith("__asset:") || descriptor.uri.startsWith("asset:") || descriptor.uri.startsWith("pngchunk:") || !descriptor.uri.includes(":")) {
8265
- let assetId = descriptor.uri;
8266
- if (assetId.startsWith("__asset:")) assetId = assetId.substring(8);
8267
- else if (assetId.startsWith("asset:")) assetId = assetId.substring(6);
8268
- else if (assetId.startsWith("pngchunk:")) assetId = assetId.substring(9);
8269
- const candidates = [
8270
- assetId,
8271
- // "0"
8272
- descriptor.uri,
8273
- // "__asset:0"
8274
- `asset:${assetId}`,
8275
- // "asset:0"
8276
- `__asset:${assetId}`,
8277
- // "__asset:0"
8278
- `__asset_${assetId}`,
8279
- // "__asset_0"
8280
- `chara-ext-asset_${assetId}`,
8281
- // "chara-ext-asset_0"
8282
- `chara-ext-asset_:${assetId}`
8283
- // "chara-ext-asset_:0"
8284
- ];
8318
+ if (isChunkReference(descriptor.uri)) {
8319
+ const assetId = stripAssetPrefix(descriptor.uri);
8320
+ const candidates = generateChunkKeyCandidates(assetId, descriptor.uri);
8285
8321
  let chunk;
8286
8322
  for (const candidate of candidates) {
8287
8323
  chunk = chunkMap.get(candidate);
@@ -8328,13 +8364,15 @@ function parsePng(data, options) {
8328
8364
  }
8329
8365
  }
8330
8366
  }
8367
+ const risuPrefixes = ASSET_PREFIX_VARIANTS.filter((v) => v.prefix.startsWith("chara-ext-asset_"));
8331
8368
  for (const chunk of extracted.extraChunks) {
8332
8369
  if (!usedChunks.has(chunk.keyword)) {
8333
8370
  let assetId = null;
8334
- if (chunk.keyword.startsWith("chara-ext-asset_:")) {
8335
- assetId = chunk.keyword.substring("chara-ext-asset_:".length);
8336
- } else if (chunk.keyword.startsWith("chara-ext-asset_")) {
8337
- assetId = chunk.keyword.substring("chara-ext-asset_".length);
8371
+ for (const { prefix } of risuPrefixes) {
8372
+ if (chunk.keyword.startsWith(prefix)) {
8373
+ assetId = chunk.keyword.substring(prefix.length);
8374
+ break;
8375
+ }
8338
8376
  }
8339
8377
  if (assetId) {
8340
8378
  try {