@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.js CHANGED
@@ -104,7 +104,23 @@ function streamingUnzipSync(data, limits = DEFAULT_ZIP_LIMITS) {
104
104
  if (unsafePathHandling === "warn" && limits.onUnsafePath) {
105
105
  limits.onUnsafePath(file.name, reason);
106
106
  }
107
- file.ondata = () => {
107
+ file.ondata = (err, chunk, _final) => {
108
+ if (error) return;
109
+ if (err) {
110
+ error = err;
111
+ return;
112
+ }
113
+ if (chunk && chunk.length > 0) {
114
+ totalBytes += chunk.length;
115
+ if (totalBytes > limits.maxTotalSize) {
116
+ error = new ZipPreflightError(
117
+ `Total actual size ${totalBytes} exceeds limit ${limits.maxTotalSize}`,
118
+ totalBytes,
119
+ limits.maxTotalSize
120
+ );
121
+ file.terminate();
122
+ }
123
+ }
108
124
  };
109
125
  file.start();
110
126
  return;
@@ -8152,6 +8168,43 @@ var DEFAULT_OPTIONS3 = {
8152
8168
  maxTotalSize: 500 * 1024 * 1024,
8153
8169
  extractAssets: true
8154
8170
  };
8171
+ var ASSET_PREFIX_VARIANTS = [
8172
+ { prefix: "__asset:", format: "CCv3 (SillyTavern)" },
8173
+ { prefix: "asset:", format: "CCv2/CCv3 common" },
8174
+ { prefix: "pngchunk:", format: "Explicit PNG chunk" },
8175
+ { prefix: "chara-ext-asset_:", format: "RisuAI (with colon)" },
8176
+ { prefix: "chara-ext-asset_", format: "RisuAI" },
8177
+ { prefix: "__asset_", format: "Legacy underscore variant" }
8178
+ ];
8179
+ function isChunkReference(uri) {
8180
+ return ASSET_PREFIX_VARIANTS.some(({ prefix }) => uri.startsWith(prefix)) || !uri.includes(":");
8181
+ }
8182
+ function stripAssetPrefix(uri) {
8183
+ for (const { prefix } of ASSET_PREFIX_VARIANTS) {
8184
+ if (uri.startsWith(prefix)) {
8185
+ return uri.substring(prefix.length);
8186
+ }
8187
+ }
8188
+ return uri;
8189
+ }
8190
+ function generateChunkKeyCandidates(assetId, originalUri) {
8191
+ return [
8192
+ assetId,
8193
+ // Plain ID: "0"
8194
+ originalUri,
8195
+ // Original URI: "__asset:0"
8196
+ `asset:${assetId}`,
8197
+ // Common format
8198
+ `__asset:${assetId}`,
8199
+ // CCv3 format
8200
+ `__asset_${assetId}`,
8201
+ // Legacy underscore variant
8202
+ `chara-ext-asset_${assetId}`,
8203
+ // RisuAI format
8204
+ `chara-ext-asset_:${assetId}`
8205
+ // RisuAI format with colon
8206
+ ];
8207
+ }
8155
8208
  function estimateBase64DecodedSize(base64Length) {
8156
8209
  return Math.ceil(base64Length * 0.75);
8157
8210
  }
@@ -8219,39 +8272,22 @@ function parsePng(data, options) {
8219
8272
  if (extracted.extraChunks && options.extractAssets && card.data.assets) {
8220
8273
  const usedChunks = /* @__PURE__ */ new Set();
8221
8274
  const chunkMap = /* @__PURE__ */ new Map();
8275
+ const risuIndexPrefixes = ASSET_PREFIX_VARIANTS.filter((v) => v.prefix.startsWith("chara-ext-asset_"));
8222
8276
  for (const chunk of extracted.extraChunks) {
8223
8277
  chunkMap.set(chunk.keyword, chunk);
8224
- if (chunk.keyword.startsWith("chara-ext-asset_")) {
8225
- const suffix = chunk.keyword.replace("chara-ext-asset_", "");
8226
- chunkMap.set(suffix, chunk);
8227
- if (suffix.startsWith(":")) {
8228
- chunkMap.set(suffix.substring(1), chunk);
8278
+ for (const { prefix } of risuIndexPrefixes) {
8279
+ if (chunk.keyword.startsWith(prefix)) {
8280
+ const suffix = chunk.keyword.substring(prefix.length);
8281
+ chunkMap.set(suffix, chunk);
8282
+ break;
8229
8283
  }
8230
8284
  }
8231
8285
  }
8232
8286
  for (const descriptor of card.data.assets) {
8233
8287
  if (!descriptor.uri) continue;
8234
- if (descriptor.uri.startsWith("__asset:") || descriptor.uri.startsWith("asset:") || descriptor.uri.startsWith("pngchunk:") || !descriptor.uri.includes(":")) {
8235
- let assetId = descriptor.uri;
8236
- if (assetId.startsWith("__asset:")) assetId = assetId.substring(8);
8237
- else if (assetId.startsWith("asset:")) assetId = assetId.substring(6);
8238
- else if (assetId.startsWith("pngchunk:")) assetId = assetId.substring(9);
8239
- const candidates = [
8240
- assetId,
8241
- // "0"
8242
- descriptor.uri,
8243
- // "__asset:0"
8244
- `asset:${assetId}`,
8245
- // "asset:0"
8246
- `__asset:${assetId}`,
8247
- // "__asset:0"
8248
- `__asset_${assetId}`,
8249
- // "__asset_0"
8250
- `chara-ext-asset_${assetId}`,
8251
- // "chara-ext-asset_0"
8252
- `chara-ext-asset_:${assetId}`
8253
- // "chara-ext-asset_:0"
8254
- ];
8288
+ if (isChunkReference(descriptor.uri)) {
8289
+ const assetId = stripAssetPrefix(descriptor.uri);
8290
+ const candidates = generateChunkKeyCandidates(assetId, descriptor.uri);
8255
8291
  let chunk;
8256
8292
  for (const candidate of candidates) {
8257
8293
  chunk = chunkMap.get(candidate);
@@ -8298,13 +8334,15 @@ function parsePng(data, options) {
8298
8334
  }
8299
8335
  }
8300
8336
  }
8337
+ const risuPrefixes = ASSET_PREFIX_VARIANTS.filter((v) => v.prefix.startsWith("chara-ext-asset_"));
8301
8338
  for (const chunk of extracted.extraChunks) {
8302
8339
  if (!usedChunks.has(chunk.keyword)) {
8303
8340
  let assetId = null;
8304
- if (chunk.keyword.startsWith("chara-ext-asset_:")) {
8305
- assetId = chunk.keyword.substring("chara-ext-asset_:".length);
8306
- } else if (chunk.keyword.startsWith("chara-ext-asset_")) {
8307
- assetId = chunk.keyword.substring("chara-ext-asset_".length);
8341
+ for (const { prefix } of risuPrefixes) {
8342
+ if (chunk.keyword.startsWith(prefix)) {
8343
+ assetId = chunk.keyword.substring(prefix.length);
8344
+ break;
8345
+ }
8308
8346
  }
8309
8347
  if (assetId) {
8310
8348
  try {