Skip to content

Commit d874ce0

Browse files
committed
Initial impl of displaying c2pa sba algo list.
1 parent a964d56 commit d874ce0

File tree

2 files changed

+93
-59
lines changed

2 files changed

+93
-59
lines changed

docs/soft-bindings.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ title: Soft binding algorithm list
44
hide_table_of_contents: true
55
---
66

7-
C2PA specifies a mechanism for recovering a C2PA Manifest for an asset, for example when the metadata containing the C2PA Manifest has been stripped. This mechanism is a [soft binding](https://c2pa.org/specifications/specifications/2.0/specs/C2PA_Specification.html#_soft_binding) (for example an invisible watermark or content fingerprint). The soft binding is used to look-up the C2PA Manifest within a Manifest Repository. The soft binding is described by the [soft binding assertion](https://c2pa.org/specifications/specifications/2.0/specs/C2PA_Specification.html#_soft_bindings).
7+
Durable Content Credentials is a concept that allows for the use of a variety of watermarking and fingerprinting approaches.
88

9-
The soft binding assertion contains a field `alg` that serves to uniquely identify the algorithm used to compute the soft binding. The Soft Binding Algorithm List is an authoritative list of soft binding algorithm names that may be used as identifiers within the `alg` field. Entries in the list also contain additional information on the algorithms.
9+
As described in the C2PA specification, a [soft binding](https://c2pa.org/specifications/specifications/2.0/specs/C2PA_Specification.html#_soft_bindings) such as an invisible watermark or content fingerprint provides a mechanism to recover an asset's manifest if the metadata containing the manifest has been stripped. The soft binding is used to look up the manifest within a manifest repository. The soft binding is described by the [soft binding assertion](https://c2pa.org/specifications/specifications/2.0/specs/C2PA_Specification.html#_soft_bindings).
1010

11-
import JSONToTable from '@site/src/components/JSONToTable';
11+
The information below is from [C2PA's authoritative list of soft binding algorithms](https://github.com/c2pa-org/softbinding-algorithm-list).
1212

13-
This table is generated from a static JSON file.
13+
import JSONToTable from '@site/src/components/JSONToTable';
1414

1515
<JSONToTable />

src/components/JSONToTable.js

Lines changed: 89 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,47 @@
11
import React, { useState, useEffect } from 'react';
22

3-
// Helper function to flatten nested objects
4-
const flattenObject = (obj, prefix = '') => {
5-
let result = {};
6-
for (const key in obj) {
7-
if (obj.hasOwnProperty(key)) {
8-
const newKey = prefix ? `${prefix}.${key}` : key;
3+
// Define the fields to display and their custom headers
4+
const DISPLAY_FIELDS = {
5+
alg: 'Algorithm Name',
6+
decodedMediaTypes: 'Media Types',
7+
'entryMetadata.informationalUrl': 'URL',
8+
'entryMetadata.contact': 'Contact',
9+
};
910

10-
// Handle nested objects
11-
if (typeof obj[key] === 'object' && obj[key] !== null) {
12-
if (Array.isArray(obj[key])) {
13-
// If it's an array, join its elements into a comma-delimited string
14-
result[newKey] = obj[key].join(', ');
15-
} else {
16-
// If it's an object, recurse to flatten it
17-
Object.assign(result, flattenObject(obj[key], newKey));
18-
}
19-
} else {
20-
result[newKey] = obj[key];
21-
}
22-
}
11+
// Helper function to safely extract nested values and flatten arrays
12+
const getNestedValue = (obj, path) => {
13+
const value = path
14+
.split('.')
15+
.reduce(
16+
(acc, key) => (acc && acc[key] !== undefined ? acc[key] : 'N/A'),
17+
obj,
18+
);
19+
return Array.isArray(value) ? value.join(', ') : value; // Flatten arrays into a comma-separated string
20+
};
21+
22+
// Function to extract and filter only the required fields
23+
const extractAndFilterObject = (obj) => {
24+
let result = {};
25+
for (const key in DISPLAY_FIELDS) {
26+
result[key] = getNestedValue(obj, key);
2327
}
2428
return result;
2529
};
2630

31+
// Helper function to capitalize each word in a string
32+
const capitalizeWords = (str) => {
33+
return str
34+
.split(' ')
35+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
36+
.join(' ');
37+
};
38+
2739
const JSONToTable = () => {
2840
const [jsonData, setJsonData] = useState(null);
2941
const [error, setError] = useState(null);
3042

31-
// Fetch the JSON data when the component mounts
3243
useEffect(() => {
33-
fetch('/sb-alg-list.json') // Path to the JSON file in the static folder
44+
fetch('/sb-alg-list.json')
3445
.then((response) => {
3546
if (!response.ok) {
3647
throw new Error('Failed to fetch the JSON file');
@@ -39,56 +50,79 @@ const JSONToTable = () => {
3950
})
4051
.then((data) => {
4152
setJsonData(data);
42-
setError(null); // Clear any previous errors
53+
setError(null);
4354
})
4455
.catch((err) => {
4556
setError(err.message);
46-
setJsonData(null); // Reset data in case of error
57+
setJsonData(null);
4758
});
4859
}, []);
4960

50-
// Function to generate table headers dynamically
51-
const generateTableHeaders = (data) => {
52-
if (data && Array.isArray(data)) {
53-
const flattenedData = data.map((item) => flattenObject(item));
54-
const keys = Array.from(new Set(flattenedData.flatMap(Object.keys)));
55-
return keys.map((key) => <th key={key}>{key}</th>);
56-
}
57-
return [];
61+
// Function to group data by the 'type' field
62+
const groupDataByType = (data) => {
63+
return data.reduce((acc, item) => {
64+
const type = getNestedValue(item, 'type');
65+
if (!acc[type]) acc[type] = [];
66+
acc[type].push(item);
67+
return acc;
68+
}, {});
69+
};
70+
71+
const generateTableHeaders = () => {
72+
return Object.keys(DISPLAY_FIELDS).map((key) => (
73+
<th key={key}>{DISPLAY_FIELDS[key]}</th>
74+
));
5875
};
5976

60-
// Function to generate table rows dynamically
6177
const generateTableRows = (data) => {
62-
console.log(data);
63-
if (data && Array.isArray(data)) {
64-
const flattenedData = data.map((item) => flattenObject(item));
65-
return flattenedData.map((row, rowIndex) => (
78+
return data.map((item, rowIndex) => {
79+
const filteredData = extractAndFilterObject(item);
80+
const url = filteredData['entryMetadata.informationalUrl'];
81+
const description = getNestedValue(item, 'entryMetadata.description');
82+
83+
return (
6684
<tr key={rowIndex}>
67-
{Object.values(row).map((value, index) => (
68-
<td key={index}>{value}</td>
85+
{Object.keys(DISPLAY_FIELDS).map((key, index) => (
86+
<td key={index}>
87+
{key === 'entryMetadata.informationalUrl' ? (
88+
url !== 'N/A' && description !== 'N/A' ? (
89+
<a href={url} target="_blank" rel="noopener noreferrer">
90+
{description}
91+
</a>
92+
) : (
93+
'N/A'
94+
)
95+
) : (
96+
filteredData[key]
97+
)}
98+
</td>
6999
))}
70100
</tr>
71-
));
72-
}
73-
return [];
101+
);
102+
});
74103
};
75104

76-
return (
77-
<div>
78-
{error && <p style={{ color: 'red' }}>{error}</p>}
105+
if (error) return <p style={{ color: 'red' }}>{error}</p>;
79106

80-
{jsonData && Array.isArray(jsonData) && (
81-
<table border="1" style={{ width: '100%', borderCollapse: 'collapse' }}>
82-
<thead>
83-
<tr>{generateTableHeaders(jsonData)}</tr>
84-
</thead>
85-
<tbody>{generateTableRows(jsonData)}</tbody>
86-
</table>
87-
)}
107+
if (!jsonData || !Array.isArray(jsonData)) {
108+
return <p>No data found in the JSON. Expected an array of objects.</p>;
109+
}
110+
111+
const groupedData = groupDataByType(jsonData);
88112

89-
{jsonData && !Array.isArray(jsonData) && (
90-
<p>No data found in the JSON. Expected an array of objects.</p>
91-
)}
113+
return (
114+
<div>
115+
{Object.entries(groupedData).map(([type, data]) => (
116+
<div key={type} style={{ marginBottom: '30px' }}>
117+
<h2>{capitalizeWords(type)} algorithms</h2>
118+
<table style={{ borderCollapse: 'collapse' }}>
119+
<thead>
120+
<tr>{generateTableHeaders()}</tr>
121+
</thead>
122+
<tbody>{generateTableRows(data)}</tbody>
123+
</table>
124+
</div>
125+
))}
92126
</div>
93127
);
94128
};

0 commit comments

Comments
 (0)