diff --git a/docs/manifest/writing/assertions-actions.md b/docs/manifest/writing/assertions-actions.md index 219c670..b46c09d 100644 --- a/docs/manifest/writing/assertions-actions.md +++ b/docs/manifest/writing/assertions-actions.md @@ -280,11 +280,6 @@ The [C2PA Technical Specification](https://c2pa.org/specifications/specification V1 actions are fully specified in the `actions` array. However, a v2 action may either be fully specified in an element of the `actions` array or it may be derived from an element in the `templates` array with the same action name. -
-The CAI APIs can read all v2 actions and write **most** v2 actions. -We should document v2 actions that can it NOT write. -
- ### Action names The value of the `action` property must be either one of the pre-defined [standard C2PA action strings](https://c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_actions) of the form `c2pa.*` or a custom action name. The set of standard C2PA actions includes fundamental ones as `c2pa.created` for when an asset is first created, and others (`c2pa.cropped`, `c2pa.resized`, and so on) for when an asset's content is modified in some way. diff --git a/docusaurus.config.js b/docusaurus.config.js index d7f9f01..5fce0ea 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -9,6 +9,7 @@ const darkCodeTheme = require('prism-react-renderer').themes.dracula; const remoteDocs = require('./remote-docs.json'); const { readFileSync } = require('fs'); const { resolve } = require('path'); +const remarkStripHiddenLinks = require('./src/remark/remark-strip-hidden-links'); const copyright = `
@@ -164,7 +165,10 @@ async function createConfig() { /** @type {import('@docusaurus/preset-classic').Options} */ ({ docs: { - beforeDefaultRemarkPlugins: [remarkGithubAdmonitionsToDirectives], + beforeDefaultRemarkPlugins: [ + remarkGithubAdmonitionsToDirectives, + remarkStripHiddenLinks, + ], sidebarPath: require.resolve('./sidebars.js'), editUrl: ({ docPath, versionDocsDirPath }) => { const normalizedDocPath = docPath.toLowerCase(); diff --git a/remote-docs.json b/remote-docs.json index c53b850..c11d739 100644 --- a/remote-docs.json +++ b/remote-docs.json @@ -167,11 +167,20 @@ "dest": "docs/rust-sdk/docs/release-notes.md", "sidebar": { "category": "rust-sdk", - "label": "Release notes", + "label": "Release notes (Rust)", "order": 10 } }, - + { + "repo": "contentauth/c2pa-rs", + "path": "docs/instanceid_behavior.md", + "dest": "docs/rust-sdk/docs/instanceid-behavior.md", + "sidebar": { + "category": "rust-sdk", + "label": "InstanceID behavior", + "order": 11 + } + }, { "_comment": "Working with the SDK" }, { "repo": "contentauth/c2pa-rs", @@ -278,7 +287,7 @@ "dest": "docs/c2pa-python/docs/release-notes.md", "sidebar": { "category": "c2pa-python", - "label": "Release notes", + "label": "Release notes (Python)", "order": 9 } }, @@ -326,7 +335,7 @@ "dest": "docs/c2pa-cpp/docs/context-settings.md", "sidebar": { "category": "c2pa-cpp", - "label": "Configuring the SDK", + "label": "Configuring SDK settings", "order": 3 } }, @@ -376,7 +385,7 @@ "dest": "docs/c2pa-cpp/docs/release-notes.md", "sidebar": { "category": "c2pa-cpp", - "label": "Release notes", + "label": "Release notes (C++", "order": 8 } }, diff --git a/src/remark/remark-strip-hidden-links.js b/src/remark/remark-strip-hidden-links.js new file mode 100644 index 0000000..6ebf80b --- /dev/null +++ b/src/remark/remark-strip-hidden-links.js @@ -0,0 +1,72 @@ +/** + * Docusaurus's broken-link checker collects links from rendered elements + * regardless of CSS visibility, so links inside GitHub-only content (hidden on + * this site via the "github-only" class or a display:none style, but meant to + * work when the source markdown is viewed on GitHub) get flagged as broken. + * + * This plugin unwraps markdown links found inside such hidden containers, + * before they become elements, so they're never collected. + */ + +const CLASS_RE = /(^|\s)github-only(\s|$)/; +const DISPLAY_NONE_RE = /display\s*:\s*['"]none['"]/; + +function isHiddenDiv(node) { + if ( + !node || + (node.type !== 'mdxJsxFlowElement' && node.type !== 'mdxJsxTextElement') || + node.name !== 'div' + ) { + return false; + } + const attributes = node.attributes || []; + return attributes.some((attr) => { + if (attr.type !== 'mdxJsxAttribute') return false; + if ( + (attr.name === 'class' || attr.name === 'className') && + typeof attr.value === 'string' + ) { + return CLASS_RE.test(attr.value); + } + if (attr.name === 'style') { + const raw = + attr.value && typeof attr.value === 'object' + ? attr.value.value + : attr.value; + return typeof raw === 'string' && DISPLAY_NONE_RE.test(raw); + } + return false; + }); +} + +// Replace link/linkReference nodes with their child content, in place. +function stripLinks(node) { + if (!node || !Array.isArray(node.children)) return; + node.children = node.children.flatMap((child) => { + stripLinks(child); + if (child.type === 'link' || child.type === 'linkReference') { + return child.children || []; + } + return [child]; + }); +} + +function visit(node) { + if (!node) return; + if (isHiddenDiv(node)) { + // stripLinks recurses through the whole hidden subtree itself. + stripLinks(node); + return; + } + if (Array.isArray(node.children)) { + node.children.forEach((child) => visit(child)); + } +} + +function remarkStripHiddenLinks() { + return (tree) => { + visit(tree); + }; +} + +module.exports = remarkStripHiddenLinks;