diff --git a/package.json b/package.json
index c606b8dde..333d3f24d 100644
--- a/package.json
+++ b/package.json
@@ -154,6 +154,7 @@
"svelte-css-vars": "^0.0.3",
"svelte-focus-trap": "^1.2.0",
"svelte-i18n": "^3.7.4",
+ "intl-messageformat": "9.13.0",
"svelte-meta-tags": "^3.0.4",
"svelte-modals": "^1.3.0",
"tippy.js": "^6.3.7"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b4697719b..743ac479d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -89,6 +89,9 @@ importers:
interactjs:
specifier: ^1.10.19
version: 1.10.27
+ intl-messageformat:
+ specifier: 9.13.0
+ version: 9.13.0
lodash:
specifier: ^4.17.21
version: 4.17.21
@@ -1809,78 +1812,92 @@ packages:
resolution: {integrity: sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linux-arm@1.2.0':
resolution: {integrity: sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linux-ppc64@1.2.0':
resolution: {integrity: sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.2.0':
resolution: {integrity: sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linux-x64@1.2.0':
resolution: {integrity: sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.2.0':
resolution: {integrity: sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.2.0':
resolution: {integrity: sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@img/sharp-linux-arm64@0.34.3':
resolution: {integrity: sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@img/sharp-linux-arm@0.34.3':
resolution: {integrity: sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@img/sharp-linux-ppc64@0.34.3':
resolution: {integrity: sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@img/sharp-linux-s390x@0.34.3':
resolution: {integrity: sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@img/sharp-linux-x64@0.34.3':
resolution: {integrity: sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.34.3':
resolution: {integrity: sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@img/sharp-linuxmusl-x64@0.34.3':
resolution: {integrity: sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@img/sharp-wasm32@0.34.3':
resolution: {integrity: sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==}
@@ -3347,41 +3364,49 @@ packages:
resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
cpu: [riscv64]
os: [linux]
+ libc: [musl]
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
diff --git a/src/components/EmbeddedIcon/EmbeddedIcon.svelte b/src/components/EmbeddedIcon/EmbeddedIcon.svelte
index cf93a929e..6476e0b11 100644
--- a/src/components/EmbeddedIcon/EmbeddedIcon.svelte
+++ b/src/components/EmbeddedIcon/EmbeddedIcon.svelte
@@ -3,18 +3,14 @@
-->
-{#if issuer}{$_('sidebar.verify.about.issuedby')} {issuer}{/if}
+
{#if manifestData.signatureInfo?.common_name || manifestData.signatureInfo?.issuer}
{/if}
diff --git a/src/routes/verify/components/DetailedInfo/AboutSection/IssuedBySection.svelte b/src/routes/verify/components/DetailedInfo/AboutSection/IssuedBySection.svelte
index 21159186c..9f9d060e7 100644
--- a/src/routes/verify/components/DetailedInfo/AboutSection/IssuedBySection.svelte
+++ b/src/routes/verify/components/DetailedInfo/AboutSection/IssuedBySection.svelte
@@ -22,6 +22,7 @@
if (issuer) params.set('o', issuer);
if (organizationalUnit) params.set('ou', organizationalUnit);
if (country) params.set('c', country);
+
return `https://spec.c2pa.org/conformance-explorer/?${params.toString()}`;
})();
@@ -71,6 +72,7 @@
{#if showTooltip}
(showTooltip = !showTooltip)}
>
+
{@html $_('sidebar.verify.about.issuedby.tooltip')}
diff --git a/src/routes/verify/components/TreeView/TreeL1.svelte b/src/routes/verify/components/TreeView/TreeL1.svelte
index 94e0e6902..f8d110f7a 100644
--- a/src/routes/verify/components/TreeView/TreeL1.svelte
+++ b/src/routes/verify/components/TreeView/TreeL1.svelte
@@ -32,7 +32,6 @@
$: removeL1 = transformScale === 0.125 ? true : false;
$: scale = 0.5 / transformScale;
$: L1margin = transformScale >= 0.25 ? 0.5 : transformScale / 0.25;
- $: trustSource = $assetStore.trustSource;
;
export type ReadableSource = Readable;
export interface C2paReaderStore extends Readable {
- read: (source: Blob | File) => Promise;
+ read: (source: Blob | File | string) => Promise;
clear: () => void;
}
@@ -33,32 +33,11 @@ const mimeTypeCorrections = {
'image/dng': 'image/x-adobe-dng',
};
-import { legacyToCrJson, type CrJson } from '$lib/crjson';
-
-// Helper to extract all manifest labels that failed trust validation in a given crJSON store
-function getUntrustedManifestLabels(store: CrJson): Set {
- const untrustedLabels = new Set();
- const isTrustError = (s: any) => s.code.includes('signingCredential');
-
- // 1. Check Root
- const rootFailures = store.validationResults?.activeManifest?.failure || [];
- const activeLabel = store.manifests[0]?.label;
- if (activeLabel && rootFailures.some(isTrustError)) {
- untrustedLabels.add(activeLabel);
- }
-
- // 2. Check EVERY manifest in the store (Active + Ingredients)
- for (const manifest of store.manifests) {
- // Check the manifest object itself
- const mFailures = manifest.validationResults?.failure || [];
- const mStatuses = manifest.validationStatus || [];
- if (mFailures.some(isTrustError) || mStatuses.some(isTrustError)) {
- untrustedLabels.add(manifest.label);
- }
- }
-
- return untrustedLabels;
-}
+type ValidationStatus = { code: string };
+type TrustSource = 'official' | 'legacy' | 'none';
+type TrustedIngredient = { trust_source?: TrustSource; active_manifest?: string; validation_status?: ValidationStatus[] };
+type TrustedManifest = { trust_source?: TrustSource; ingredients?: TrustedIngredient[] };
+type ValidationDelta = { ingredientAssertionURI?: string; validationDeltas?: { failure?: ValidationStatus[] } };
export function createC2paReader(): C2paReaderStore {
let dispose: () => void;
@@ -66,11 +45,16 @@ export function createC2paReader(): C2paReaderStore {
return {
subscribe,
- read: async (source: Blob | File) => {
+ read: async (source: Blob | File | string) => {
set({ state: 'loading' });
dispose?.();
try {
+ if (typeof source === 'string') {
+ const response = await fetch(source);
+ source = await response.blob();
+ }
+
const sdk = await getSdk();
const sourceType = source instanceof Blob ? source.type : '';
const normalizedSourceType = sourceType.toLowerCase().trim();
@@ -112,7 +96,7 @@ export function createC2paReader(): C2paReaderStore {
// PASS 1: Validate against Official Trust List
const officialSettings = await getOfficialToolkitSettings();
- let reader = await sdk.reader.fromBlob(source.type || 'application/octet-stream', source, officialSettings);
+ const reader = await sdk.reader.fromBlob(source.type || 'application/octet-stream', source, officialSettings);
if (!reader) {
throw new Error('No C2PA manifest found in this file');
@@ -130,108 +114,112 @@ export function createC2paReader(): C2paReaderStore {
if (needsLegacyPass) {
const legacySettings = await getLegacyToolkitSettings();
const legacyReader = await sdk.reader.fromBlob(source.type || 'application/octet-stream', source, legacySettings);
- const legacyStore = await legacyReader.manifestStore();
-
- // 3. ONLY ADOPT Pass 2 if it actually solved the problem (State is now Trusted/Valid)
- if (legacyStore.validation_state === 'Trusted' || legacyStore.validation_state === 'Valid') {
- finalStore = legacyStore;
-
- reader.free();
- currentReader = legacyReader;
-
- const isTrustError = (s: any) => s.code.includes('signingCredential.untrusted') || s.code.includes('signingCredential.invalid');
- const isCryptoValid = (s: any) => s.code.includes('signingCredential.trusted') || s.code.includes('claimSignature.validated');
-
- // 4a. Tag the Active Manifest
- const p1ActiveV3 = rawManifestStore.validation_results?.activeManifest?.failure || [];
- const p1ActiveV2 = rawManifestStore.manifests?.[rawManifestStore.active_manifest || '']?.validation_status || [];
- const wasActiveUntrusted = p1ActiveV3.some(isTrustError) || p1ActiveV2.some(isTrustError);
- const isFinalTrusted = finalStore.validation_state === 'Trusted';
-
- if (finalStore.manifests && finalStore.active_manifest && finalStore.manifests[finalStore.active_manifest]) {
- const activeMan = finalStore.manifests[finalStore.active_manifest];
+
+ if (legacyReader) {
+ const legacyStore = await legacyReader.manifestStore();
+
+ // 3. ONLY ADOPT Pass 2 if it actually solved the problem (State is now Trusted/Valid)
+ if (legacyStore.validation_state === 'Trusted' || legacyStore.validation_state === 'Valid') {
+ finalStore = legacyStore;
- // If the root is Trusted, default to official, then downgrade if Pass 1 failed.
- if (isFinalTrusted) {
- activeMan.trust_source = wasActiveUntrusted ? 'legacy' : 'official';
- } else {
- activeMan.trust_source = 'none';
- }
- }
+ reader.free();
+ currentReader = legacyReader;
+
+ const isTrustError = (s: ValidationStatus) => s.code.includes('signingCredential.untrusted') || s.code.includes('signingCredential.invalid');
- // 4b. Tag ALL Ingredients across the entire provenance tree
- const p1Deltas = rawManifestStore.validation_results?.ingredientDeltas || [];
-
- Object.entries(finalStore.manifests || {}).forEach(([label, manifest]: [string, any]) => {
- const p1Manifest = rawManifestStore.manifests?.[label];
+ // 4a. Tag the Active Manifest
+ const p1ActiveV3 = (rawManifestStore.validation_results?.activeManifest?.failure || []) as ValidationStatus[];
+ const p1ActiveV2 = (rawManifestStore.manifests?.[rawManifestStore.active_manifest || '']?.validation_status || []) as ValidationStatus[];
+ const wasActiveUntrusted = p1ActiveV3.some(isTrustError) || p1ActiveV2.some(isTrustError);
+ const isFinalTrusted = finalStore.validation_state === 'Trusted';
- if (manifest.ingredients && p1Manifest?.ingredients) {
- manifest.ingredients.forEach((ingredient: any, index: number) => {
- // ZERO TRUST DEFAULT: Unverified assets get no trust credentials
- ingredient.trust_source = 'none';
-
- if (ingredient.active_manifest) {
- const p1Ing = p1Manifest.ingredients[index];
- const subLabel = ingredient.active_manifest;
- const p1SubManifest = subLabel ? rawManifestStore.manifests?.[subLabel] : null;
-
- // 1. Check the Ingredient Pointer (V2 standard)
- const p1V2_ing = p1Ing?.validation_status || [];
-
- // 2. Check the actual Sub-Manifest directly (V2 + V3 standards)
- // NOTE: In V3, the sub-manifest's own results are stored under .activeManifest
- const p1V2_sub = p1SubManifest?.validation_status || [];
- const p1V3_sub = p1SubManifest?.validation_results?.activeManifest?.failure || [];
-
- // 3. Check the Root Deltas (V3 standard)
- const p1Delta = p1Deltas.find((d: any) =>
- d.ingredientAssertionURI?.includes(label) &&
- d.ingredientAssertionURI?.includes('c2pa.ingredient')
- );
- const p1V3_delta = p1Delta?.validationDeltas?.failure || [];
-
- // AGGREGATE: Did ANY layer in the sub-manifest chain fail Trust in Pass 1?
- const hasTrustError =
- p1V3_delta.some(isTrustError) ||
- p1V2_ing.some(isTrustError) ||
- p1V2_sub.some(isTrustError) ||
- p1V3_sub.some(isTrustError);
-
- if (isFinalTrusted) {
- // If the Root is trusted, the chain is intact.
- // It only earns 'Official' if it explicitly cleared the local error gauntlet.
- ingredient.trust_source = hasTrustError ? 'legacy' : 'official';
- }
- }
- });
+ if (finalStore.manifests && finalStore.active_manifest && finalStore.manifests[finalStore.active_manifest]) {
+ const activeMan = finalStore.manifests[finalStore.active_manifest] as unknown as TrustedManifest;
+
+ // If the root is Trusted, default to official, then downgrade if Pass 1 failed.
+ if (isFinalTrusted) {
+ activeMan.trust_source = wasActiveUntrusted ? 'legacy' : 'official';
+ } else {
+ activeMan.trust_source = 'none';
+ }
}
- });
- } else {
- legacyReader.free();
-
- // Fallback: If root is Trusted, entire tree is official.
- const isTrusted = finalStore.validation_state === 'Trusted';
- Object.entries(finalStore.manifests || {}).forEach(([label, manifest]: [string, any]) => {
- if (label === finalStore.active_manifest) {
- manifest.trust_source = isTrusted ? 'official' : 'none';
- }
- if (manifest.ingredients) {
- manifest.ingredients.forEach((ing: any) => {
- ing.trust_source = (isTrusted && ing.active_manifest) ? 'official' : 'none';
- });
- }
- });
+ // 4b. Tag ALL Ingredients across the entire provenance tree
+ const p1Deltas = (rawManifestStore.validation_results?.ingredientDeltas || []) as ValidationDelta[];
+
+ (Object.entries(finalStore.manifests || {}) as Array<[string, TrustedManifest]>).forEach(([label, manifest]) => {
+ const p1Manifest = rawManifestStore.manifests?.[label];
+
+ if (manifest.ingredients && p1Manifest?.ingredients) {
+ manifest.ingredients.forEach((ingredient, index) => {
+ // ZERO TRUST DEFAULT: Unverified assets get no trust credentials
+ ingredient.trust_source = 'none';
+
+ if (ingredient.active_manifest) {
+ const p1Ing = p1Manifest.ingredients?.[index];
+ const subLabel = ingredient.active_manifest;
+ const p1SubManifest = (subLabel ? rawManifestStore.manifests?.[subLabel] : null) as Record | null;
+
+ // 1. Check the Ingredient Pointer (V2 standard)
+ const p1V2_ing = (p1Ing?.validation_status || []) as ValidationStatus[];
+
+ // 2. Check the actual Sub-Manifest directly (V2 + V3 standards)
+ // NOTE: In V3, the sub-manifest's own results are stored under .activeManifest
+ const p1V2_sub = (p1SubManifest?.validation_status || []) as ValidationStatus[];
+ const p1V3_sub = ((p1SubManifest?.validation_results as Record | undefined)?.activeManifest as Record | undefined)?.failure as ValidationStatus[] | undefined || [];
+
+ // 3. Check the Root Deltas (V3 standard)
+ const p1Delta = p1Deltas.find((d) =>
+ d.ingredientAssertionURI?.includes(label) &&
+ d.ingredientAssertionURI?.includes('c2pa.ingredient')
+ );
+ const p1V3_delta = p1Delta?.validationDeltas?.failure || [];
+
+ // AGGREGATE: Did ANY layer in the sub-manifest chain fail Trust in Pass 1?
+ const hasTrustError =
+ p1V3_delta.some(isTrustError) ||
+ p1V2_ing.some(isTrustError) ||
+ p1V2_sub.some(isTrustError) ||
+ p1V3_sub.some(isTrustError);
+
+ if (isFinalTrusted) {
+ // If the Root is trusted, the chain is intact.
+ // It only earns 'Official' if it explicitly cleared the local error gauntlet.
+ ingredient.trust_source = hasTrustError ? 'legacy' : 'official';
+ }
+ }
+ });
+ }
+ });
+
+ } else {
+ legacyReader.free();
+
+ // Fallback: If root is Trusted, entire tree is official.
+ const isTrusted = finalStore.validation_state === 'Trusted';
+ (Object.entries(finalStore.manifests || {}) as Array<[string, TrustedManifest]>).forEach(([label, manifest]) => {
+ if (label === finalStore.active_manifest) {
+ manifest.trust_source = isTrusted ? 'official' : 'none';
+ }
+
+ if (manifest.ingredients) {
+ manifest.ingredients.forEach((ing) => {
+ ing.trust_source = (isTrusted && ing.active_manifest) ? 'official' : 'none';
+ });
+ }
+ });
+ }
}
} else {
// Pass 1 had no trust issues (Could be Trusted or Hard Invalid)
const isTrusted = finalStore.validation_state === 'Trusted';
- Object.entries(finalStore.manifests || {}).forEach(([label, manifest]: [string, any]) => {
+ (Object.entries(finalStore.manifests || {}) as Array<[string, TrustedManifest]>).forEach(([label, manifest]) => {
if (label === finalStore.active_manifest) {
manifest.trust_source = isTrusted ? 'official' : 'none';
}
+
if (manifest.ingredients) {
- manifest.ingredients.forEach((ing: any) => {
+ manifest.ingredients.forEach((ing) => {
ing.trust_source = (isTrusted && ing.active_manifest) ? 'official' : 'none';
});
}
@@ -239,7 +227,8 @@ export function createC2paReader(): C2paReaderStore {
}
const { assetMap, dispose: assetMapDisposer } =
- await resultToAssetMap({ manifestStore: finalStore, source });
+ await resultToAssetMap({ manifestStore: finalStore, source });
+
dispose = () => {
assetMapDisposer();
currentReader.free();
@@ -258,6 +247,7 @@ export function createC2paReader(): C2paReaderStore {
toast.trigger(unsupportedFileType());
} else if (
(errName === 'C2pa(PrereleaseError)' || errStr.includes('Prerelease')) &&
+ typeof source !== 'string' &&
(await hasLegacyCredentials(source))
) {
openModal(LegacyCredentialModal);
@@ -279,5 +269,6 @@ export function createC2paReader(): C2paReaderStore {
async function hasLegacyCredentials(source: Blob | File): Promise {
const legacySdk = await getLegacySdk();
const legacyResult = await legacySdk.processImage(source);
+
return legacyResult.exists;
}
diff --git a/vite.config.js b/vite.config.js
index 5a29118a2..ed52a5904 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -18,6 +18,11 @@ const config = {
allow: ['assets', 'locales'],
},
},
+ resolve: {
+ alias: {
+ 'intl-messageformat': path.resolve(__dirname, 'node_modules/intl-messageformat/intl-messageformat.esm.js'),
+ },
+ },
build: {
minify: 'terser',
sourcemap: true,
@@ -29,7 +34,7 @@ const config = {
},
},
ssr: {
- noExternal: ['svelte-i18n'],
+ noExternal: ['svelte-i18n', 'intl-messageformat'],
},
define: {
__SUPPORTED_LOCALES__: JSON.stringify(getSupportedLocales()),