diff --git a/docs/manifest/json-ref/index.md b/docs/manifest/json-ref/index.md index f6b850e6..f7f46fec 100644 --- a/docs/manifest/json-ref/index.md +++ b/docs/manifest/json-ref/index.md @@ -5,7 +5,7 @@ hide_table_of_contents: true --- :::note -This is a beta release of these references. It is a work in progress and may have issues or errors. +These references are generated from the Rust library but apply to all the language bindings (libraries). But note that not all languages may be up-to-date with the latest changes in the Rust library. ::: The [C2PA specification](https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_manifests) describes a manifest with a binary structure in JPEG universal metadata box format ([JUMBF](https://www.iso.org/standard/84635.html)) that includes JSON as well as binary data for things like encryption keys and thumbnail images. Because the binary structure is hard to understand and program to, the SDK defines a JSON manifest structure that's a declarative language for representing and creating a binary manifest. diff --git a/docs/manifest/writing/writing.md b/docs/manifest/writing/writing.md index 24cc505b..6a7eb950 100644 --- a/docs/manifest/writing/writing.md +++ b/docs/manifest/writing/writing.md @@ -3,8 +3,8 @@ id: writing-index title: Building and writing manifest data --- -Use a [ManifestDefinition](../json-ref/manifest-def.mdx) structure to define and construct manifest data for writing. The Rust library and other language libraries provide methods and objects for working with this structure. +Use a [Builder](../json-ref/builder-ref.mdx) structure to define and construct manifest data for writing. The Rust library and other language libraries provide methods and objects for working with this structure. - [Writing ingredients](ingredients.md) - [Writing assertions and actions](assertions-actions.md) -- [ManifestDefinition JSON reference](manifest/json-ref/manifest-def.mdx) generated from the JSON schema for the [ManifestDefinition](https://docs.rs/c2pa/latest/c2pa/struct.ManifestDefinition.html) object (_struct_ in Rust terminology). +- [Builder](../json-ref/builder-ref.mdx) generated from the JSON schema for the [Builder](https://docs.rs/c2pa/latest/c2pa/struct.Builder.html) object (_struct_ in Rust terminology). diff --git a/sidebars.js b/sidebars.js index b3c72808..9e096525 100644 --- a/sidebars.js +++ b/sidebars.js @@ -103,18 +103,6 @@ const sidebars = { }, ], }, - { - type: 'category', - label: 'C2PA conformance program', - link: { type: 'doc', id: 'conformance/index' }, - collapsed: true, - items: [ - { - type: 'doc', - id: 'conformance/trust-lists', - }, - ], - }, { type: 'category', label: 'C2PA Tool', @@ -410,6 +398,18 @@ const sidebars = { }, ], }, + { + type: 'category', + label: 'C2PA conformance program', + link: { type: 'doc', id: 'conformance/index' }, + collapsed: true, + items: [ + { + type: 'doc', + id: 'conformance/trust-lists', + }, + ], + }, { type: 'category', label: 'Durable Content Credentials', diff --git a/src/components/SchemaReference.js b/src/components/SchemaReference.js index ba65edfa..e474dcff 100644 --- a/src/components/SchemaReference.js +++ b/src/components/SchemaReference.js @@ -93,6 +93,25 @@ function markdownToHtml(text) { if (!text) return ''; let html = String(text); + // Parse reference-style link definitions like: + // [`Builder`]: crate::Builder + // [Actions]: crate::assertions::Actions + const refDefs = (() => { + const map = {}; + const defRe = /^\s*\[([^\]]+)\]:\s*(\S+)\s*$/gm; + let m; + while ((m = defRe.exec(html)) !== null) { + const rawLabel = m[1]; + const target = m[2]; + map[rawLabel] = target; + const normalized = rawLabel.replace(/`/g, ''); + if (!Object.prototype.hasOwnProperty.call(map, normalized)) { + map[normalized] = target; + } + } + return map; + })(); + const escapeHtml = (s) => String(s) .replace(/&/g, '&') @@ -121,8 +140,25 @@ function markdownToHtml(text) { BmffHash: 'assertions', Builder: '', }; + // Known struct field names for better anchor selection (fields vs methods) + const TYPE_FIELD_HINTS = { + Settings: new Set([ + 'builder', + 'cawg_trust', + 'cawg_x509_signer', + 'core', + 'signer', + 'trust', + 'verify', + 'version', + ]), + }; + // Known type kinds to choose docs page prefix (struct vs trait) + const TYPE_KIND_HINTS = { + Signer: 'trait', + }; const resolveDocsUrl = (codeRef) => { - let refStr = codeRef.replace(/^crate::/, ''); + let refStr = codeRef.replace(/^(?:crate|c2pa)::/, ''); const parts = refStr.split('::'); let moduleParts = []; @@ -158,25 +194,64 @@ function markdownToHtml(text) { } const modulePath = moduleParts.length ? moduleParts.join('/') + '/' : ''; - let url = `https://docs.rs/c2pa/latest/c2pa/${modulePath}struct.${typeName}.html`; + const kind = TYPE_KIND_HINTS[typeName] || 'struct'; + let url = `https://docs.rs/c2pa/latest/c2pa/${modulePath}${kind}.${typeName}.html`; if (member) { - const anchor = /_/.test(member) - ? `structfield.${member}` - : `method.${member}`; + const isField = + TYPE_FIELD_HINTS[typeName] && TYPE_FIELD_HINTS[typeName].has(member); + const anchor = isField ? `structfield.${member}` : `method.${member}`; url += `#${anchor}`; } return url; }; // Convert [`CodeRef`] to links to docs.rs, preserving code formatting - html = html.replace(/\[`([^`]+)`\]/g, (m, codeRef) => { - const url = resolveDocsUrl(codeRef); + html = html.replace(/\[`([^`]+)`\](?!\(|:)/g, (m, codeRef) => { + const mapped = + (Object.prototype.hasOwnProperty.call(refDefs, '`' + codeRef + '`') && + refDefs['`' + codeRef + '`']) || + (Object.prototype.hasOwnProperty.call(refDefs, codeRef) && + refDefs[codeRef]) || + null; + const url = + mapped && /^https?:\/\//.test(mapped) + ? mapped + : resolveDocsUrl(mapped || codeRef); return `${escapeHtml( codeRef, )}`; }); + // Convert reference-style links: [Label][CodeRef] into docs.rs links + // Keep the label as the link text, resolve the second bracket as a Rust code ref. + html = html.replace( + /\[([^\]]+)\]\s*\[\s*((?:crate::|c2pa::)?[A-Za-z][A-Za-z0-9_]*(?:::[A-Za-z0-9_]+)*)\s*\]/g, + (m, label, codeRef) => { + const url = resolveDocsUrl(codeRef); + return `${escapeHtml(label)}`; + }, + ); + + // Convert [CodeRef] (non-markdown-link, no backticks) to docs.rs links. + // Avoid interfering with [text](url) by ensuring no '(' follows the ']'. + // Also avoid reference definition lines (followed by ':'). + // Accept optional crate:: prefix and Type paths with ::member. + html = html.replace( + /\[((?:crate::|c2pa::)?[A-Z][A-Za-z0-9_]*(?:::[A-Za-z0-9_]+)*)\](?!\(|:)/g, + (m, labelOrCodeRef) => { + const mapped = + (Object.prototype.hasOwnProperty.call(refDefs, labelOrCodeRef) && + refDefs[labelOrCodeRef]) || + null; + const url = + mapped && /^https?:\/\//.test(mapped) + ? mapped + : resolveDocsUrl(mapped || labelOrCodeRef); + return `${escapeHtml(labelOrCodeRef)}`; + }, + ); + // Links: [text](url) html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (m, label, url) => { const safeUrl = url.replace(/"/g, '"'); @@ -251,70 +326,78 @@ function PropertiesTable({ - {Object.entries(properties).map(([name, schema]) => { - const typeHtml = formatType(schema); - const isRequired = Array.isArray(required) - ? required.includes(name) - : false; - const explicitDefault = - schema && Object.prototype.hasOwnProperty.call(schema, 'default') - ? schema.default - : undefined; - const inferredDefault = - defaults && Object.prototype.hasOwnProperty.call(defaults, name) - ? defaults[name] - : undefined; - const chosenDefault = - explicitDefault !== undefined - ? explicitDefault - : inferredDefault !== undefined - ? inferredDefault - : undefined; - - // Link to the referenced definition for non-primitive defaults (objects/arrays) when possible - let defaultCell; - if (chosenDefault === undefined) { - defaultCell = 'N/A'; - } else if ( - typeof chosenDefault === 'object' && - chosenDefault !== null - ) { - const defName = schema ? refToDefName(schema.$ref) : null; - if (defName) { - defaultCell = ( - <> - See {defName} - - ); + {Object.entries(properties) + .sort(([aName], [bName]) => + String(aName).localeCompare(String(bName), undefined, { + sensitivity: 'base', + numeric: true, + }), + ) + .map(([name, schema]) => { + const typeHtml = formatType(schema); + const isRequired = Array.isArray(required) + ? required.includes(name) + : false; + const explicitDefault = + schema && + Object.prototype.hasOwnProperty.call(schema, 'default') + ? schema.default + : undefined; + const inferredDefault = + defaults && Object.prototype.hasOwnProperty.call(defaults, name) + ? defaults[name] + : undefined; + const chosenDefault = + explicitDefault !== undefined + ? explicitDefault + : inferredDefault !== undefined + ? inferredDefault + : undefined; + + // Link to the referenced definition for non-primitive defaults (objects/arrays) when possible + let defaultCell; + if (chosenDefault === undefined) { + defaultCell = 'N/A'; + } else if ( + typeof chosenDefault === 'object' && + chosenDefault !== null + ) { + const defName = schema ? refToDefName(schema.$ref) : null; + if (defName) { + defaultCell = ( + <> + See {defName} + + ); + } else { + defaultCell = JSON.stringify(chosenDefault); + } } else { defaultCell = JSON.stringify(chosenDefault); } - } else { - defaultCell = JSON.stringify(chosenDefault); - } - - return ( - - {name} - - - - - {schema && schema.description ? ( -
- -
- ) : ( - N/A - )} - - - {isRequired ? 'YES' : 'NO'} - - {defaultCell} - - ); - })} + + return ( + + {name} + + + + + {schema && schema.description ? ( +
+ +
+ ) : ( + N/A + )} + + + {isRequired ? 'YES' : 'NO'} + + {defaultCell} + + ); + })} @@ -596,21 +679,28 @@ export default function SchemaReference({ schemaUrl }) { - {Object.entries(defs).map(([name, defSchema]) => { - const schemaWithDefaults = - (defSchema && { - ...defSchema, - __inferredDefaults: inferredDefaults[name], - }) || - defSchema; - return ( - - ); - })} + {Object.entries(defs) + .sort(([aName], [bName]) => + String(aName).localeCompare(String(bName), undefined, { + sensitivity: 'base', + numeric: true, + }), + ) + .map(([name, defSchema]) => { + const schemaWithDefaults = + (defSchema && { + ...defSchema, + __inferredDefaults: inferredDefaults[name], + }) || + defSchema; + return ( + + ); + })} ); }