@sweberdev/witness 0.0.0-stage → 0.1.1

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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -2
  3. package/dist/ai-sdk.cjs +921 -0
  4. package/dist/ai-sdk.cjs.map +1 -0
  5. package/dist/ai-sdk.d.cts +95 -0
  6. package/dist/ai-sdk.d.ts +95 -0
  7. package/dist/ai-sdk.js +150 -0
  8. package/dist/ai-sdk.js.map +1 -0
  9. package/dist/bin.cjs +944 -0
  10. package/dist/bin.cjs.map +1 -0
  11. package/dist/bin.d.cts +1 -0
  12. package/dist/bin.d.ts +1 -0
  13. package/dist/bin.js +12 -0
  14. package/dist/bin.js.map +1 -0
  15. package/dist/chunk-APXU3MTX.js +958 -0
  16. package/dist/chunk-APXU3MTX.js.map +1 -0
  17. package/dist/chunk-L65R2SM5.js +228 -0
  18. package/dist/chunk-L65R2SM5.js.map +1 -0
  19. package/dist/chunk-O6TADCND.js +317 -0
  20. package/dist/chunk-O6TADCND.js.map +1 -0
  21. package/dist/chunk-UBRK4CTM.js +156 -0
  22. package/dist/chunk-UBRK4CTM.js.map +1 -0
  23. package/dist/chunk-XJOQ5IUT.js +110 -0
  24. package/dist/chunk-XJOQ5IUT.js.map +1 -0
  25. package/dist/cli.cjs +964 -0
  26. package/dist/cli.cjs.map +1 -0
  27. package/dist/cli.d.cts +7 -0
  28. package/dist/cli.d.ts +7 -0
  29. package/dist/cli.js +9 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/disclosure-5a3UIVQZ.d.cts +70 -0
  32. package/dist/disclosure-C7Y_uY73.d.ts +70 -0
  33. package/dist/elements-auto.cjs +649 -0
  34. package/dist/elements-auto.cjs.map +1 -0
  35. package/dist/elements-auto.d.cts +3 -0
  36. package/dist/elements-auto.d.ts +3 -0
  37. package/dist/elements-auto.js +16 -0
  38. package/dist/elements-auto.js.map +1 -0
  39. package/dist/elements.cjs +646 -0
  40. package/dist/elements.cjs.map +1 -0
  41. package/dist/elements.d.cts +47 -0
  42. package/dist/elements.d.ts +47 -0
  43. package/dist/elements.js +13 -0
  44. package/dist/elements.js.map +1 -0
  45. package/dist/image-B7YvdITx.d.ts +49 -0
  46. package/dist/image-BNrEO-hj.d.cts +49 -0
  47. package/dist/index.cjs +1344 -0
  48. package/dist/index.cjs.map +1 -0
  49. package/dist/index.d.cts +124 -0
  50. package/dist/index.d.ts +124 -0
  51. package/dist/index.js +77 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/types-WWHzrNlc.d.cts +90 -0
  54. package/dist/types-WWHzrNlc.d.ts +90 -0
  55. package/package.json +123 -3
  56. package/src/ai-sdk.ts +252 -0
  57. package/src/bin.ts +6 -0
  58. package/src/cli.ts +160 -0
  59. package/src/disclosure.ts +172 -0
  60. package/src/elements-auto.ts +5 -0
  61. package/src/elements.ts +363 -0
  62. package/src/i18n.ts +259 -0
  63. package/src/image.ts +552 -0
  64. package/src/index.ts +66 -0
  65. package/src/inflate.ts +189 -0
  66. package/src/marking.ts +237 -0
  67. package/src/types.ts +115 -0
  68. package/src/watermark.ts +165 -0
  69. package/styles.css +103 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/marking.ts","../src/inflate.ts","../src/image.ts","../src/watermark.ts"],"sourcesContent":["import { format, getMessages } from \"./i18n.js\";\nimport type { ContentKind, LocaleOverride, Marking, MarkingInput, SourceType } from \"./types.js\";\n\nconst IPTC_BASE = \"http://cv.iptc.org/newscodes/digitalsourcetype/\";\n\nconst SCHEMA_ORG: Record<SourceType, string> = {\n trainedAlgorithmicMedia: \"https://schema.org/TrainedAlgorithmicMediaDigitalSource\",\n compositeWithTrainedAlgorithmicMedia:\n \"https://schema.org/CompositeWithTrainedAlgorithmicMediaDigitalSource\",\n algorithmicallyEnhanced: \"https://schema.org/AlgorithmicallyEnhancedDigitalSource\",\n algorithmicMedia: \"https://schema.org/AlgorithmicMediaDigitalSource\",\n compositeSynthetic: \"https://schema.org/CompositeSyntheticDigitalSource\",\n};\n\nconst DEFAULT_SOURCE: Record<ContentKind, SourceType> = {\n generated: \"trainedAlgorithmicMedia\",\n edited: \"compositeWithTrainedAlgorithmicMedia\",\n deepfake: \"trainedAlgorithmicMedia\",\n};\n\n/** The IPTC Digital Source Type URI, e.g. for XMP or `data-ai-source-type`. */\nexport function iptcSourceType(type: SourceType): string {\n return IPTC_BASE + type;\n}\n\n/** The schema.org `IPTCDigitalSourceEnumeration` member for JSON-LD. */\nexport function schemaOrgSourceType(type: SourceType): string {\n return SCHEMA_ORG[type];\n}\n\n/** Reads a source type from an IPTC or schema.org URI, or from the bare name. */\nexport function parseSourceType(value: string | null | undefined): SourceType | undefined {\n if (!value) return undefined;\n const trimmed = value.trim();\n const name = trimmed.startsWith(IPTC_BASE) ? trimmed.slice(IPTC_BASE.length) : trimmed;\n if (name in SCHEMA_ORG) return name as SourceType;\n for (const [type, uri] of Object.entries(SCHEMA_ORG)) {\n if (uri === trimmed) return type as SourceType;\n }\n return undefined;\n}\n\n/** True for source types that mean \"made or changed by a trained AI model\". */\nexport function isAiSourceType(type: SourceType | undefined): boolean {\n return (\n type === \"trainedAlgorithmicMedia\" ||\n type === \"compositeWithTrainedAlgorithmicMedia\" ||\n type === \"algorithmicallyEnhanced\"\n );\n}\n\n/** Applies defaults to a marking. */\nexport function createMarking(input: MarkingInput = {}): Marking {\n const kind = input.kind ?? \"generated\";\n const createdAt =\n input.createdAt instanceof Date\n ? input.createdAt.toISOString()\n : (input.createdAt ?? new Date().toISOString());\n const marking: Marking = {\n kind,\n sourceType: input.sourceType ?? DEFAULT_SOURCE[kind],\n createdAt,\n humanReviewed: input.humanReviewed ?? false,\n };\n if (input.generator) marking.generator = input.generator;\n if (input.generatorVersion) marking.generatorVersion = input.generatorVersion;\n if (input.provider) marking.provider = input.provider;\n if (input.disclosureUrl) marking.disclosureUrl = input.disclosureUrl;\n if (input.description) marking.description = input.description;\n return marking;\n}\n\n/**\n * `data-*` attributes that mark an element's content as AI-generated. Spread them on the\n * element that wraps the content.\n */\nexport function markingAttributes(input: Marking | MarkingInput): Record<string, string> {\n const m = normalise(input);\n const attributes: Record<string, string> = {\n \"data-ai-generated\": \"true\",\n \"data-ai-kind\": m.kind,\n \"data-ai-source-type\": iptcSourceType(m.sourceType),\n \"data-ai-created\": m.createdAt,\n };\n if (m.generator) attributes[\"data-ai-generator\"] = generatorName(m);\n if (m.provider) attributes[\"data-ai-provider\"] = m.provider;\n if (m.humanReviewed) attributes[\"data-ai-reviewed\"] = \"true\";\n return attributes;\n}\n\n/**\n * Page-level `<meta>` tags for a page whose main content is AI-generated. There is no\n * standardised meta tag yet, so these are a convention; pair them with {@link markingJsonLd}.\n */\nexport function markingMetaTags(\n input: Marking | MarkingInput,\n): Array<{ name: string; content: string }> {\n const m = normalise(input);\n const tags = [\n { name: \"ai-generated\", content: m.kind },\n { name: \"ai-source-type\", content: iptcSourceType(m.sourceType) },\n ];\n if (m.generator) tags.push({ name: \"ai-generator\", content: generatorName(m) });\n if (m.humanReviewed) tags.push({ name: \"ai-reviewed\", content: \"true\" });\n return tags;\n}\n\n/** The meta tags as an HTML string. */\nexport function renderMetaTags(input: Marking | MarkingInput): string {\n return markingMetaTags(input)\n .map((tag) => `<meta name=\"${escapeHtml(tag.name)}\" content=\"${escapeHtml(tag.content)}\">`)\n .join(\"\\n\");\n}\n\n/** The meta tags in the shape of Next.js `metadata.other`. */\nexport function nextMetadata(input: Marking | MarkingInput): { other: Record<string, string> } {\n return {\n other: Object.fromEntries(markingMetaTags(input).map((tag) => [tag.name, tag.content])),\n };\n}\n\n/**\n * schema.org JSON-LD for a creative work, with `digitalSourceType` set. Merge `extra` to add\n * your own properties such as `headline` or `@type: \"NewsArticle\"`.\n */\nexport function markingJsonLd(\n input: Marking | MarkingInput,\n extra: Record<string, unknown> = {},\n): Record<string, unknown> {\n const m = normalise(input);\n const data: Record<string, unknown> = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"CreativeWork\",\n digitalSourceType: schemaOrgSourceType(m.sourceType),\n dateCreated: m.createdAt,\n };\n if (m.generator) {\n data.creator = {\n \"@type\": \"SoftwareApplication\",\n name: m.generator,\n ...(m.generatorVersion ? { softwareVersion: m.generatorVersion } : {}),\n };\n }\n if (m.provider) data.publisher = { \"@type\": \"Organization\", name: m.provider };\n if (m.description) data.description = m.description;\n return { ...data, ...extra };\n}\n\n/** The JSON-LD as a `<script type=\"application/ld+json\">` tag. */\nexport function renderJsonLd(\n input: Marking | MarkingInput,\n extra: Record<string, unknown> = {},\n): string {\n const json = JSON.stringify(markingJsonLd(input, extra)).replace(/</g, \"\\\\u003c\");\n return `<script type=\"application/ld+json\">${json}</script>`;\n}\n\nexport interface LabelHtmlOptions {\n locale?: string | readonly string[];\n messages?: LocaleOverride;\n /** Where the visible label goes. Text should be labelled at the top. Default `top`. */\n position?: \"top\" | \"bottom\";\n /** Element that wraps label and content. Default `div`. */\n tag?: \"div\" | \"section\" | \"article\" | \"figure\" | \"aside\";\n}\n\n/**\n * Wraps server-rendered HTML in an element that carries the marking attributes and a visible\n * label. Works without JavaScript; style it with `@sweberdev/witness/styles.css` or your own\n * CSS for `.witness-label`.\n */\nexport function labelHtml(\n html: string,\n input: Marking | MarkingInput,\n options: LabelHtmlOptions = {},\n): string {\n const m = normalise(input);\n const tag = options.tag ?? \"div\";\n const attributes = Object.entries(markingAttributes(m))\n .map(([name, value]) => ` ${name}=\"${escapeHtml(value)}\"`)\n .join(\"\");\n const label = renderLabelLine(m, options);\n const body = options.position === \"bottom\" ? `${html}${label}` : `${label}${html}`;\n return `<${tag} class=\"witness-content\"${attributes}>${body}</${tag}>`;\n}\n\n/** One line of visible label text, e.g. \"KI-generiert · Erzeugt mit Claude\". */\nexport function labelText(\n input: Marking | MarkingInput,\n options: Pick<LabelHtmlOptions, \"locale\" | \"messages\"> = {},\n): string {\n const m = normalise(input);\n const messages = getMessages(options.locale, options.messages);\n const parts = [messages.kinds[m.kind].label];\n if (m.generator) {\n parts.push(format(messages.ui.generatedWith, { generator: generatorName(m) }));\n }\n if (m.humanReviewed) parts.push(messages.ui.humanReviewed);\n return parts.join(\" · \");\n}\n\nfunction renderLabelLine(m: Marking, options: LabelHtmlOptions): string {\n const messages = getMessages(options.locale, options.messages);\n const text = escapeHtml(labelText(m, options));\n const link = m.disclosureUrl\n ? ` <a class=\"witness-label__link\" href=\"${escapeHtml(m.disclosureUrl)}\">${escapeHtml(messages.ui.moreInfo)}</a>`\n : \"\";\n return `<p class=\"witness-label\" role=\"note\"><span class=\"witness-label__icon\" aria-hidden=\"true\">AI</span> <span class=\"witness-label__text\">${text}</span>${link}</p>`;\n}\n\n/** \"Model 1.2\" when a version is known. */\nexport function generatorName(m: Pick<Marking, \"generator\" | \"generatorVersion\">): string {\n if (!m.generator) return \"\";\n return m.generatorVersion ? `${m.generator} ${m.generatorVersion}` : m.generator;\n}\n\nfunction normalise(input: Marking | MarkingInput): Marking {\n return isMarking(input) ? input : createMarking(input);\n}\n\nfunction isMarking(input: Marking | MarkingInput): input is Marking {\n return (\n typeof input.kind === \"string\" &&\n typeof input.sourceType === \"string\" &&\n typeof input.createdAt === \"string\" &&\n typeof input.humanReviewed === \"boolean\"\n );\n}\n\nexport function escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n","/**\n * A small synchronous zlib inflater (RFC 1950/1951), enough to read compressed XMP from PNG\n * zTXt and iTXt chunks in any JavaScript runtime. Based on the structure of tinf by\n * Jørgen Ibsen (zlib licence).\n */\n\ninterface Tree {\n counts: Uint16Array;\n symbols: Uint16Array;\n}\n\nconst LENGTH_BASE = [\n 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,\n 163, 195, 227, 258,\n];\nconst LENGTH_EXTRA = [\n 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,\n];\nconst DIST_BASE = [\n 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049,\n 3073, 4097, 6145, 8193, 12289, 16385, 24577,\n];\nconst DIST_EXTRA = [\n 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,\n];\nconst CODE_LENGTH_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];\n\nfunction buildTree(lengths: ArrayLike<number>, offset: number, count: number): Tree {\n const tree: Tree = { counts: new Uint16Array(16), symbols: new Uint16Array(count) };\n for (let i = 0; i < count; i++) {\n const length = lengths[offset + i] ?? 0;\n tree.counts[length] = (tree.counts[length] ?? 0) + 1;\n }\n tree.counts[0] = 0;\n const offsets = new Uint16Array(16);\n let sum = 0;\n for (let i = 0; i < 16; i++) {\n offsets[i] = sum;\n sum += tree.counts[i] ?? 0;\n }\n for (let i = 0; i < count; i++) {\n const length = lengths[offset + i] ?? 0;\n if (length) {\n const at = offsets[length] ?? 0;\n tree.symbols[at] = i;\n offsets[length] = at + 1;\n }\n }\n return tree;\n}\n\nlet fixed: { lit: Tree; dist: Tree } | null = null;\nfunction fixedTrees(): { lit: Tree; dist: Tree } {\n if (!fixed) {\n const lengths = new Uint8Array(288);\n lengths.fill(8, 0, 144);\n lengths.fill(9, 144, 256);\n lengths.fill(7, 256, 280);\n lengths.fill(8, 280, 288);\n fixed = { lit: buildTree(lengths, 0, 288), dist: buildTree(new Uint8Array(30).fill(5), 0, 30) };\n }\n return fixed;\n}\n\nclass Reader {\n pos = 0;\n bit = 0;\n bits = 0;\n constructor(readonly data: Uint8Array) {}\n\n getBit(): number {\n if (this.bits === 0) {\n if (this.pos >= this.data.length) throw new Error(\"inflate: unexpected end of data\");\n this.bit = this.data[this.pos++] ?? 0;\n this.bits = 8;\n }\n const value = this.bit & 1;\n this.bit >>>= 1;\n this.bits--;\n return value;\n }\n\n read(count: number, base = 0): number {\n let value = 0;\n for (let i = 0; i < count; i++) value |= this.getBit() << i;\n return value + base;\n }\n\n decode(tree: Tree): number {\n let sum = 0;\n let cur = 0;\n let len = 0;\n do {\n cur = 2 * cur + this.getBit();\n len++;\n if (len > 15) throw new Error(\"inflate: invalid code\");\n sum += tree.counts[len] ?? 0;\n cur -= tree.counts[len] ?? 0;\n } while (cur >= 0);\n return tree.symbols[sum + cur] ?? 0;\n }\n}\n\nfunction dynamicTrees(r: Reader): { lit: Tree; dist: Tree } {\n const hlit = r.read(5, 257);\n const hdist = r.read(5, 1);\n const hclen = r.read(4, 4);\n const codeLengths = new Uint8Array(19);\n for (let i = 0; i < hclen; i++) codeLengths[CODE_LENGTH_ORDER[i] ?? 0] = r.read(3);\n const codeTree = buildTree(codeLengths, 0, 19);\n const lengths = new Uint8Array(hlit + hdist);\n for (let n = 0; n < hlit + hdist; ) {\n const sym = r.decode(codeTree);\n if (sym < 16) {\n lengths[n++] = sym;\n continue;\n }\n let repeat: number;\n let value = 0;\n if (sym === 16) {\n if (n === 0) throw new Error(\"inflate: invalid repeat\");\n value = lengths[n - 1] ?? 0;\n repeat = r.read(2, 3);\n } else if (sym === 17) {\n repeat = r.read(3, 3);\n } else {\n repeat = r.read(7, 11);\n }\n while (repeat-- > 0) lengths[n++] = value;\n }\n return { lit: buildTree(lengths, 0, hlit), dist: buildTree(lengths, hlit, hdist) };\n}\n\n/** Inflates zlib-wrapped data. Throws on corrupt input or when `maxLength` is exceeded. */\nexport function inflateZlib(data: Uint8Array, maxLength = 16 * 1024 * 1024): Uint8Array {\n if (\n data.length < 2 ||\n ((data[0] ?? 0) & 0x0f) !== 8 ||\n (((data[0] ?? 0) << 8) | (data[1] ?? 0)) % 31 !== 0\n ) {\n throw new Error(\"inflate: not a zlib stream\");\n }\n const r = new Reader(data);\n r.pos = 2;\n let out = new Uint8Array(Math.max(1024, data.length * 4));\n let length = 0;\n const push = (byte: number) => {\n if (length >= out.length) {\n if (out.length >= maxLength) throw new Error(\"inflate: output too large\");\n const next = new Uint8Array(Math.min(maxLength, out.length * 2));\n next.set(out);\n out = next;\n }\n out[length++] = byte;\n };\n\n let final = 0;\n do {\n final = r.getBit();\n const type = r.read(2);\n if (type === 0) {\n r.bits = 0;\n if (r.pos + 4 > data.length) throw new Error(\"inflate: unexpected end of data\");\n const len = (data[r.pos] ?? 0) | ((data[r.pos + 1] ?? 0) << 8);\n r.pos += 4;\n if (r.pos + len > data.length) throw new Error(\"inflate: unexpected end of data\");\n for (let i = 0; i < len; i++) push(data[r.pos++] ?? 0);\n } else if (type === 1 || type === 2) {\n const { lit, dist } = type === 1 ? fixedTrees() : dynamicTrees(r);\n for (;;) {\n const sym = r.decode(lit);\n if (sym === 256) break;\n if (sym < 256) {\n push(sym);\n continue;\n }\n const index = sym - 257;\n const len = r.read(LENGTH_EXTRA[index] ?? 0, LENGTH_BASE[index] ?? 0);\n const distSym = r.decode(dist);\n const offset = r.read(DIST_EXTRA[distSym] ?? 0, DIST_BASE[distSym] ?? 0);\n if (offset > length) throw new Error(\"inflate: invalid distance\");\n for (let i = 0; i < len; i++) push(out[length - offset] ?? 0);\n }\n } else {\n throw new Error(\"inflate: invalid block type\");\n }\n } while (!final);\n return out.subarray(0, length);\n}\n","/**\n * Machine-readable AI marking for images: an XMP packet with the IPTC Digital Source Type,\n * written into PNG, JPEG and WebP files without re-encoding the pixels.\n *\n * This is unsigned metadata. It is what IPTC, Google and most photo tools read today, but it\n * is not a C2PA manifest and is easy to strip. Files that already carry a C2PA manifest are\n * left untouched by default, because rewriting them would break the manifest's hash binding.\n */\n\nimport { inflateZlib } from \"./inflate.js\";\nimport {\n createMarking,\n generatorName,\n iptcSourceType,\n isAiSourceType,\n parseSourceType,\n} from \"./marking.js\";\nimport type { Marking, MarkingInput, SourceType } from \"./types.js\";\n\nexport type ImageFormat = \"png\" | \"jpeg\" | \"webp\";\n\nexport interface MarkImageOptions {\n /**\n * What to do with files that already carry a C2PA manifest. `skip` (default) returns them\n * unchanged; `overwrite` writes the XMP anyway and breaks the manifest's hash binding.\n */\n c2pa?: \"skip\" | \"overwrite\";\n}\n\nexport interface MarkImageResult {\n bytes: Uint8Array;\n status: \"marked\" | \"skipped-c2pa\" | \"unsupported\";\n format: ImageFormat | null;\n}\n\nexport interface ImageMarkingInfo {\n format: ImageFormat | null;\n /** The XMP packet, if any. */\n xmp: string | null;\n /** IPTC Digital Source Type from the XMP. */\n sourceType?: SourceType;\n /** The source type says the image was made or changed by a trained AI model. */\n aiGenerated: boolean;\n /** `Iptc4xmpExt:AISystemUsed` or `xmp:CreatorTool`. */\n generator?: string;\n /** Written by Witness. */\n witness: boolean;\n /** A C2PA manifest is embedded. Witness does not verify it. */\n c2pa: boolean;\n}\n\nconst XMP_NS = \"http://ns.adobe.com/xap/1.0/\\0\";\nconst WITNESS_NS = \"https://packages.sweber.dev/witness/ns/1.0/\";\n\n/** Detects PNG, JPEG or WebP from the first bytes. */\nexport function detectImageFormat(bytes: Uint8Array): ImageFormat | null {\n if (bytes.length >= 8 && bytes[0] === 0x89 && ascii(bytes, 1, 3) === \"PNG\") return \"png\";\n if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {\n return \"jpeg\";\n }\n if (bytes.length >= 12 && ascii(bytes, 0, 4) === \"RIFF\" && ascii(bytes, 8, 4) === \"WEBP\") {\n return \"webp\";\n }\n return null;\n}\n\n/** Writes the marking as XMP into a PNG, JPEG or WebP file. */\nexport function markImage(\n bytes: Uint8Array,\n input: Marking | MarkingInput = {},\n options: MarkImageOptions = {},\n): MarkImageResult {\n const format = detectImageFormat(bytes);\n if (!format) return { bytes, status: \"unsupported\", format };\n if (options.c2pa !== \"overwrite\" && hasC2pa(bytes, format)) {\n return { bytes, status: \"skipped-c2pa\", format };\n }\n const marking =\n \"sourceType\" in input && \"humanReviewed\" in input ? (input as Marking) : createMarking(input);\n const existing = readXmp(bytes, format);\n const xmp = buildXmp(marking, existing);\n const out =\n format === \"png\"\n ? writePng(bytes, xmp)\n : format === \"jpeg\"\n ? writeJpeg(bytes, xmp)\n : writeWebp(bytes, xmp);\n return { bytes: out, status: \"marked\", format };\n}\n\n/** Reads the AI marking of an image, whoever wrote it. */\nexport function readImageMarking(bytes: Uint8Array): ImageMarkingInfo {\n const format = detectImageFormat(bytes);\n if (!format) return { format, xmp: null, aiGenerated: false, witness: false, c2pa: false };\n const xmp = readXmp(bytes, format);\n const sourceType = xmp\n ? parseSourceType(xmpProperty(xmp, \"Iptc4xmpExt:DigitalSourceType\"))\n : undefined;\n const generator = xmp\n ? (xmpProperty(xmp, \"Iptc4xmpExt:AISystemUsed\") ?? xmpProperty(xmp, \"xmp:CreatorTool\"))\n : undefined;\n const info: ImageMarkingInfo = {\n format,\n xmp,\n aiGenerated: isAiSourceType(sourceType),\n witness: xmp?.includes(WITNESS_NS) ?? false,\n c2pa: hasC2pa(bytes, format),\n };\n if (sourceType) info.sourceType = sourceType;\n if (generator) info.generator = generator;\n return info;\n}\n\n/** The XMP packet Witness writes, merged into an existing packet if there is one. */\nexport function buildXmp(marking: Marking, existing?: string | null): string {\n const description = buildDescription(marking);\n if (existing?.includes(\"</rdf:RDF>\")) {\n // Drop the description an earlier run wrote, in its self-closing or its paired form.\n const cleaned = existing\n .replace(/<rdf:Description\\b[^>]*witness:marker=\"1\"[^>]*\\/>\\s*/g, \"\")\n .replace(\n /<rdf:Description\\b[^>]*witness:marker=\"1\"[^>]*>[\\s\\S]*?<\\/rdf:Description>\\s*/g,\n \"\",\n );\n // Our description declares its own namespaces, so it can sit next to any other.\n return cleaned.replace(\"</rdf:RDF>\", `${description}\\n</rdf:RDF>`);\n }\n return [\n '<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>',\n '<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">',\n '<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">',\n description,\n \"</rdf:RDF>\",\n \"</x:xmpmeta>\",\n '<?xpacket end=\"w\"?>',\n ].join(\"\\n\");\n}\n\nfunction buildDescription(m: Marking): string {\n const attributes: Array<[string, string]> = [\n [\"rdf:about\", \"\"],\n [\"xmlns:Iptc4xmpExt\", \"http://iptc.org/std/Iptc4xmpExt/2008-02-29/\"],\n [\"xmlns:xmp\", \"http://ns.adobe.com/xap/1.0/\"],\n [\"xmlns:dc\", \"http://purl.org/dc/elements/1.1/\"],\n [\"xmlns:witness\", WITNESS_NS],\n [\"witness:marker\", \"1\"],\n [\"witness:kind\", m.kind],\n [\"Iptc4xmpExt:DigitalSourceType\", iptcSourceType(m.sourceType)],\n [\"xmp:CreateDate\", m.createdAt],\n ];\n if (m.generator) {\n attributes.push([\"Iptc4xmpExt:AISystemUsed\", m.generator]);\n attributes.push([\"xmp:CreatorTool\", generatorName(m)]);\n }\n if (m.generatorVersion) attributes.push([\"Iptc4xmpExt:AISystemVersionUsed\", m.generatorVersion]);\n if (m.provider) attributes.push([\"witness:provider\", m.provider]);\n if (m.disclosureUrl) attributes.push([\"witness:disclosureUrl\", m.disclosureUrl]);\n if (m.humanReviewed) attributes.push([\"witness:humanReviewed\", \"True\"]);\n const attrs = attributes.map(([name, value]) => `\\n ${name}=\"${escapeXml(value)}\"`).join(\"\");\n const description = m.description\n ? `\\n <dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">${escapeXml(m.description)}</rdf:li></rdf:Alt></dc:description>\\n`\n : \"\";\n return description\n ? `<rdf:Description${attrs}>${description}</rdf:Description>`\n : `<rdf:Description${attrs}/>`;\n}\n\n/** Reads a simple property in attribute or element form. */\nfunction xmpProperty(xmp: string, name: string): string | undefined {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const attribute = new RegExp(`${escaped}=\"([^\"]*)\"`).exec(xmp);\n if (attribute?.[1] !== undefined) return unescapeXml(attribute[1]);\n const element = new RegExp(\n `<${escaped}(?:\\\\s+rdf:resource=\"([^\"]*)\")?\\\\s*(?:/>|>([\\\\s\\\\S]*?)</${escaped}>)`,\n ).exec(xmp);\n if (!element) return undefined;\n if (element[1] !== undefined) return unescapeXml(element[1]);\n const inner = element[2] ?? \"\";\n const li = /<rdf:li[^>]*>([\\s\\S]*?)<\\/rdf:li>/.exec(inner);\n const value = (li ? li[1] : inner)?.trim();\n return value ? unescapeXml(value) : undefined;\n}\n\n// ---------------------------------------------------------------------------- PNG\n\nfunction writePng(bytes: Uint8Array, xmp: string): Uint8Array {\n const chunks = pngChunks(bytes).filter((chunk) => !isPngXmp(bytes, chunk));\n const itxt = pngChunk(\n \"iTXt\",\n concat(latin1(\"XML:com.adobe.xmp\"), new Uint8Array([0, 0, 0, 0, 0]), utf8(xmp)),\n );\n const parts: Uint8Array[] = [bytes.subarray(0, 8)];\n for (const chunk of chunks) {\n parts.push(bytes.subarray(chunk.offset, chunk.end));\n if (chunk.type === \"IHDR\") parts.push(itxt);\n }\n return concat(...parts);\n}\n\ninterface PngChunk {\n type: string;\n offset: number;\n dataStart: number;\n dataEnd: number;\n end: number;\n}\n\nfunction pngChunks(bytes: Uint8Array): PngChunk[] {\n const chunks: PngChunk[] = [];\n let offset = 8;\n while (offset + 12 <= bytes.length) {\n const length = readU32BE(bytes, offset);\n const type = ascii(bytes, offset + 4, 4);\n const dataStart = offset + 8;\n const dataEnd = dataStart + length;\n const end = dataEnd + 4;\n if (end > bytes.length) throw new Error(\"Witness: truncated PNG chunk\");\n chunks.push({ type, offset, dataStart, dataEnd, end });\n offset = end;\n if (type === \"IEND\") break;\n }\n return chunks;\n}\n\n/** XMP lives in iTXt per the XMP spec; libvips and some other tools write zTXt instead. */\nfunction isPngXmp(bytes: Uint8Array, chunk: PngChunk): boolean {\n return (\n (chunk.type === \"iTXt\" || chunk.type === \"zTXt\") &&\n ascii(bytes, chunk.dataStart, 18) === \"XML:com.adobe.xmp\\0\"\n );\n}\n\nfunction readPngXmp(bytes: Uint8Array): string | null {\n for (const chunk of pngChunks(bytes)) {\n if (!isPngXmp(bytes, chunk)) continue;\n let p = chunk.dataStart + 18;\n let compressed: boolean;\n if (chunk.type === \"zTXt\") {\n compressed = true;\n p += 1; // compression method\n } else {\n compressed = bytes[p] === 1;\n p += 2;\n while (p < chunk.dataEnd && bytes[p] !== 0) p++; // language tag\n p++;\n while (p < chunk.dataEnd && bytes[p] !== 0) p++; // translated keyword\n p++;\n }\n const data = bytes.subarray(p, chunk.dataEnd);\n try {\n return new TextDecoder().decode(compressed ? inflateZlib(data) : data);\n } catch {\n return null;\n }\n }\n return null;\n}\n\nfunction pngChunk(type: string, data: Uint8Array): Uint8Array {\n const out = new Uint8Array(12 + data.length);\n writeU32BE(out, 0, data.length);\n out.set(latin1(type), 4);\n out.set(data, 8);\n writeU32BE(out, 8 + data.length, crc32(out.subarray(4, 8 + data.length)));\n return out;\n}\n\n// ---------------------------------------------------------------------------- JPEG\n\ninterface JpegSegment {\n marker: number;\n offset: number;\n dataStart: number;\n end: number;\n}\n\nfunction jpegSegments(bytes: Uint8Array): { segments: JpegSegment[]; scanStart: number } {\n const segments: JpegSegment[] = [];\n let offset = 2;\n while (offset + 4 <= bytes.length) {\n if (bytes[offset] !== 0xff) throw new Error(\"Witness: invalid JPEG marker\");\n let markerOffset = offset;\n while (bytes[markerOffset + 1] === 0xff) markerOffset++; // fill bytes\n const marker = bytes[markerOffset + 1] ?? 0;\n if (marker === 0xda || marker === 0xd9) return { segments, scanStart: offset };\n const length = readU16BE(bytes, markerOffset + 2);\n const end = markerOffset + 2 + length;\n if (end > bytes.length) throw new Error(\"Witness: truncated JPEG segment\");\n segments.push({ marker, offset, dataStart: markerOffset + 4, end });\n offset = end;\n }\n return { segments, scanStart: offset };\n}\n\nfunction isJpegXmp(bytes: Uint8Array, segment: JpegSegment): boolean {\n return segment.marker === 0xe1 && ascii(bytes, segment.dataStart, XMP_NS.length) === XMP_NS;\n}\n\nfunction writeJpeg(bytes: Uint8Array, xmp: string): Uint8Array {\n const { segments, scanStart } = jpegSegments(bytes);\n const payload = concat(latin1(XMP_NS), utf8(xmp));\n if (payload.length + 2 > 0xffff) throw new Error(\"Witness: XMP packet too large for JPEG\");\n const app1 = new Uint8Array(4 + payload.length);\n app1[0] = 0xff;\n app1[1] = 0xe1;\n app1[2] = ((payload.length + 2) >> 8) & 0xff;\n app1[3] = (payload.length + 2) & 0xff;\n app1.set(payload, 4);\n\n const kept = segments.filter((segment) => !isJpegXmp(bytes, segment));\n // Keep JFIF (APP0) and Exif (APP1) first, as readers expect them there.\n let insertAt = 0;\n while (insertAt < kept.length) {\n const segment = kept[insertAt];\n if (!segment) break;\n const isJfif = segment.marker === 0xe0;\n const isExif = segment.marker === 0xe1 && ascii(bytes, segment.dataStart, 4) === \"Exif\";\n if (!isJfif && !isExif) break;\n insertAt++;\n }\n const parts: Uint8Array[] = [bytes.subarray(0, 2)];\n kept.forEach((segment, index) => {\n if (index === insertAt) parts.push(app1);\n parts.push(bytes.subarray(segment.offset, segment.end));\n });\n if (insertAt >= kept.length) parts.push(app1);\n parts.push(bytes.subarray(scanStart));\n return concat(...parts);\n}\n\nfunction readJpegXmp(bytes: Uint8Array): string | null {\n for (const segment of jpegSegments(bytes).segments) {\n if (isJpegXmp(bytes, segment)) {\n return new TextDecoder().decode(\n bytes.subarray(segment.dataStart + XMP_NS.length, segment.end),\n );\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------- WebP\n\ninterface RiffChunk {\n fourcc: string;\n offset: number;\n dataStart: number;\n size: number;\n end: number;\n}\n\nfunction webpChunks(bytes: Uint8Array): RiffChunk[] {\n const chunks: RiffChunk[] = [];\n const riffEnd = Math.min(bytes.length, 8 + readU32LE(bytes, 4));\n let offset = 12;\n while (offset + 8 <= riffEnd) {\n const fourcc = ascii(bytes, offset, 4);\n const size = readU32LE(bytes, offset + 4);\n const dataStart = offset + 8;\n const end = dataStart + size + (size % 2);\n if (dataStart + size > bytes.length) throw new Error(\"Witness: truncated WebP chunk\");\n chunks.push({ fourcc, offset, dataStart, size, end: Math.min(end, bytes.length) });\n offset = end;\n }\n return chunks;\n}\n\nfunction writeWebp(bytes: Uint8Array, xmp: string): Uint8Array {\n const chunks = webpChunks(bytes).filter((chunk) => chunk.fourcc !== \"XMP \");\n const first = chunks[0];\n if (!first) throw new Error(\"Witness: empty WebP file\");\n const parts: Uint8Array[] = [];\n if (first.fourcc === \"VP8X\") {\n const vp8x = bytes.slice(first.offset, first.end);\n vp8x[8] = (vp8x[8] ?? 0) | 0x04; // XMP flag\n parts.push(vp8x);\n for (const chunk of chunks.slice(1)) parts.push(bytes.subarray(chunk.offset, chunk.end));\n } else {\n const { width, height, alpha } = webpCanvas(bytes, first);\n const data = new Uint8Array(10);\n data[0] = 0x04 | (alpha ? 0x10 : 0);\n writeU24LE(data, 4, width - 1);\n writeU24LE(data, 7, height - 1);\n parts.push(riffChunk(\"VP8X\", data));\n for (const chunk of chunks) parts.push(bytes.subarray(chunk.offset, chunk.end));\n }\n parts.push(riffChunk(\"XMP \", utf8(xmp)));\n const body = concat(...parts);\n const out = new Uint8Array(12 + body.length);\n out.set(latin1(\"RIFF\"), 0);\n writeU32LE(out, 4, 4 + body.length);\n out.set(latin1(\"WEBP\"), 8);\n out.set(body, 12);\n return out;\n}\n\nfunction webpCanvas(\n bytes: Uint8Array,\n chunk: RiffChunk,\n): { width: number; height: number; alpha: boolean } {\n const d = chunk.dataStart;\n if (chunk.fourcc === \"VP8 \") {\n if (bytes[d + 3] !== 0x9d || bytes[d + 4] !== 0x01 || bytes[d + 5] !== 0x2a) {\n throw new Error(\"Witness: invalid VP8 frame\");\n }\n return {\n width: readU16LE(bytes, d + 6) & 0x3fff,\n height: readU16LE(bytes, d + 8) & 0x3fff,\n alpha: false,\n };\n }\n if (chunk.fourcc === \"VP8L\") {\n if (bytes[d] !== 0x2f) throw new Error(\"Witness: invalid VP8L frame\");\n const bits = readU32LE(bytes, d + 1);\n return {\n width: (bits & 0x3fff) + 1,\n height: ((bits >>> 14) & 0x3fff) + 1,\n alpha: ((bits >>> 28) & 1) === 1,\n };\n }\n throw new Error(`Witness: unexpected WebP chunk ${chunk.fourcc}`);\n}\n\nfunction readWebpXmp(bytes: Uint8Array): string | null {\n const chunk = webpChunks(bytes).find((c) => c.fourcc === \"XMP \");\n return chunk\n ? new TextDecoder().decode(bytes.subarray(chunk.dataStart, chunk.dataStart + chunk.size))\n : null;\n}\n\nfunction riffChunk(fourcc: string, data: Uint8Array): Uint8Array {\n const out = new Uint8Array(8 + data.length + (data.length % 2));\n out.set(latin1(fourcc), 0);\n writeU32LE(out, 4, data.length);\n out.set(data, 8);\n return out;\n}\n\n// ---------------------------------------------------------------------------- shared\n\nfunction readXmp(bytes: Uint8Array, format: ImageFormat): string | null {\n if (format === \"png\") return readPngXmp(bytes);\n if (format === \"jpeg\") return readJpegXmp(bytes);\n return readWebpXmp(bytes);\n}\n\n/** C2PA manifests live in caBX (PNG), APP11 JUMBF (JPEG) or C2PA (WebP) chunks. */\nfunction hasC2pa(bytes: Uint8Array, format: ImageFormat): boolean {\n if (format === \"png\") return pngChunks(bytes).some((chunk) => chunk.type === \"caBX\");\n if (format === \"webp\") return webpChunks(bytes).some((chunk) => chunk.fourcc === \"C2PA\");\n return jpegSegments(bytes).segments.some(\n (segment) =>\n segment.marker === 0xeb &&\n ascii(bytes, segment.dataStart, Math.min(64, segment.end - segment.dataStart)).includes(\n \"c2pa\",\n ),\n );\n}\n\nfunction ascii(bytes: Uint8Array, offset: number, length: number): string {\n let out = \"\";\n for (let i = offset; i < offset + length && i < bytes.length; i++) {\n out += String.fromCharCode(bytes[i] ?? 0);\n }\n return out;\n}\n\nfunction latin1(text: string): Uint8Array {\n const out = new Uint8Array(text.length);\n for (let i = 0; i < text.length; i++) out[i] = text.charCodeAt(i) & 0xff;\n return out;\n}\n\nfunction utf8(text: string): Uint8Array {\n return new TextEncoder().encode(text);\n}\n\nfunction concat(...parts: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0));\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n\nfunction readU16BE(b: Uint8Array, o: number): number {\n return ((b[o] ?? 0) << 8) | (b[o + 1] ?? 0);\n}\nfunction readU16LE(b: Uint8Array, o: number): number {\n return (b[o] ?? 0) | ((b[o + 1] ?? 0) << 8);\n}\nfunction readU32BE(b: Uint8Array, o: number): number {\n return (\n (((b[o] ?? 0) << 24) | ((b[o + 1] ?? 0) << 16) | ((b[o + 2] ?? 0) << 8) | (b[o + 3] ?? 0)) >>> 0\n );\n}\nfunction readU32LE(b: Uint8Array, o: number): number {\n return (\n ((b[o] ?? 0) | ((b[o + 1] ?? 0) << 8) | ((b[o + 2] ?? 0) << 16) | ((b[o + 3] ?? 0) << 24)) >>> 0\n );\n}\nfunction writeU32BE(b: Uint8Array, o: number, v: number): void {\n b[o] = (v >>> 24) & 0xff;\n b[o + 1] = (v >>> 16) & 0xff;\n b[o + 2] = (v >>> 8) & 0xff;\n b[o + 3] = v & 0xff;\n}\nfunction writeU32LE(b: Uint8Array, o: number, v: number): void {\n b[o] = v & 0xff;\n b[o + 1] = (v >>> 8) & 0xff;\n b[o + 2] = (v >>> 16) & 0xff;\n b[o + 3] = (v >>> 24) & 0xff;\n}\nfunction writeU24LE(b: Uint8Array, o: number, v: number): void {\n b[o] = v & 0xff;\n b[o + 1] = (v >>> 8) & 0xff;\n b[o + 2] = (v >>> 16) & 0xff;\n}\n\nlet crcTable: Uint32Array | null = null;\nfunction crc32(data: Uint8Array): number {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n crcTable[n] = c >>> 0;\n }\n }\n let crc = 0xffffffff;\n for (const byte of data) crc = (crcTable[(crc ^ byte) & 0xff] ?? 0) ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nfunction unescapeXml(value: string): string {\n return value\n .replace(/&quot;/g, '\"')\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&apos;/g, \"'\")\n .replace(/&amp;/g, \"&\");\n}\n","/**\n * An invisible, machine-readable marker for AI-generated text.\n *\n * The payload is written as Unicode variation selectors (U+FE00–U+FE0F and\n * U+E0100–U+E01EF). They are default-ignorable code points: browsers do not render them and\n * screen readers skip them, and they survive copy and paste in most applications. They do\n * not survive sanitisers that strip unusual code points, retyping, or paraphrasing, so treat\n * this as one marking layer next to visible labels and metadata, not as a robust watermark.\n */\n\nconst MAGIC = [0x57, 0x31]; // \"W1\"\nconst MAX_PAYLOAD = 255;\n\nexport interface TextWatermark {\n /** Name of the AI system. */\n generator?: string;\n /** ISO 8601 timestamp. */\n createdAt?: string;\n /** Your own reference, e.g. a message or log id. */\n id?: string;\n}\n\nexport interface ReadTextWatermark extends TextWatermark {\n /** The raw payload as written. */\n raw: string;\n}\n\n/**\n * Appends an invisible watermark to `text`. An existing Witness watermark is replaced. Empty\n * text is returned unchanged.\n */\nexport function watermarkText(text: string, mark: TextWatermark = {}): string {\n if (text.length === 0) return text;\n return stripTextWatermark(text) + watermarkSuffix(mark);\n}\n\n/**\n * Only the invisible characters, for appending to a stream. They attach to whatever character\n * precedes them, so emit them after at least one visible character.\n */\nexport function watermarkSuffix(mark: TextWatermark = {}): string {\n const payload = encodePayload(mark);\n return [...MAGIC, payload.length, ...payload].map(byteToSelector).join(\"\");\n}\n\n/** Reads the first Witness watermark in `text`, or `null`. */\nexport function readTextWatermark(text: string): ReadTextWatermark | null {\n for (const run of selectorRuns(text)) {\n const found = findInRun(run.bytes);\n if (found) {\n const raw = new TextDecoder().decode(new Uint8Array(found.payload));\n return { ...decodePayload(raw), raw };\n }\n }\n return null;\n}\n\n/** True when `text` carries a Witness watermark. */\nexport function hasTextWatermark(text: string): boolean {\n return readTextWatermark(text) !== null;\n}\n\n/**\n * Removes Witness watermarks and leaves all other characters, including the variation\n * selectors that belong to emoji, untouched.\n */\nexport function stripTextWatermark(text: string): string {\n const chars = [...text];\n const remove = new Set<number>();\n for (const run of selectorRuns(text)) {\n let offset = 0;\n while (offset < run.bytes.length) {\n const found = findInRun(run.bytes.slice(offset));\n if (!found) break;\n const start = offset + found.start;\n const end = offset + found.end;\n for (let i = start; i < end; i++) remove.add(run.start + i);\n offset = end;\n }\n }\n if (remove.size === 0) return text;\n return chars.filter((_, index) => !remove.has(index)).join(\"\");\n}\n\nfunction encodePayload(mark: TextWatermark): number[] {\n const fields: string[] = [];\n if (mark.generator) fields.push(`g=${encodeURIComponent(mark.generator)}`);\n if (mark.createdAt) fields.push(`t=${encodeURIComponent(mark.createdAt)}`);\n if (mark.id) fields.push(`i=${encodeURIComponent(mark.id)}`);\n let bytes = [...new TextEncoder().encode(fields.join(\";\"))];\n if (bytes.length > MAX_PAYLOAD) {\n // Keep whole fields only, so a truncated payload still parses.\n while (fields.length > 0 && bytes.length > MAX_PAYLOAD) {\n fields.pop();\n bytes = [...new TextEncoder().encode(fields.join(\";\"))];\n }\n }\n return bytes;\n}\n\nfunction decodePayload(raw: string): TextWatermark {\n const result: TextWatermark = {};\n for (const field of raw.split(\";\")) {\n const index = field.indexOf(\"=\");\n if (index < 1) continue;\n const key = field.slice(0, index);\n let value: string;\n try {\n value = decodeURIComponent(field.slice(index + 1));\n } catch {\n continue;\n }\n if (key === \"g\") result.generator = value;\n else if (key === \"t\") result.createdAt = value;\n else if (key === \"i\") result.id = value;\n }\n return result;\n}\n\nfunction byteToSelector(byte: number): string {\n return byte < 16\n ? String.fromCodePoint(0xfe00 + byte)\n : String.fromCodePoint(0xe0100 + (byte - 16));\n}\n\nfunction selectorToByte(codePoint: number): number | null {\n if (codePoint >= 0xfe00 && codePoint <= 0xfe0f) return codePoint - 0xfe00;\n if (codePoint >= 0xe0100 && codePoint <= 0xe01ef) return codePoint - 0xe0100 + 16;\n return null;\n}\n\n/** Consecutive variation selectors, with their index in code points. */\nfunction selectorRuns(text: string): Array<{ start: number; bytes: number[] }> {\n const runs: Array<{ start: number; bytes: number[] }> = [];\n let current: { start: number; bytes: number[] } | null = null;\n let index = 0;\n for (const char of text) {\n const byte = selectorToByte(char.codePointAt(0) ?? 0);\n if (byte === null) {\n current = null;\n } else {\n if (!current) {\n current = { start: index, bytes: [] };\n runs.push(current);\n }\n current.bytes.push(byte);\n }\n index++;\n }\n return runs;\n}\n\n/** Finds MAGIC, length and payload inside a run. Positions are indexes into `bytes`. */\nfunction findInRun(bytes: number[]): { start: number; end: number; payload: number[] } | null {\n for (let i = 0; i + MAGIC.length < bytes.length; i++) {\n if (bytes[i] !== MAGIC[0] || bytes[i + 1] !== MAGIC[1]) continue;\n const length = bytes[i + 2];\n if (length === undefined) continue;\n const start = i + 3;\n const end = start + length;\n if (end > bytes.length) continue;\n return { start: i, end, payload: bytes.slice(start, end) };\n }\n return null;\n}\n"],"mappings":"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","names":["format"]}
@@ -0,0 +1,228 @@
1
+ // src/i18n.ts
2
+ var en = {
3
+ kinds: {
4
+ chatbot: {
5
+ label: "AI assistant",
6
+ title: "You are chatting with an AI",
7
+ body: "This assistant is an AI system, not a person. Its answers are generated automatically and can be wrong."
8
+ },
9
+ generated: {
10
+ label: "AI-generated",
11
+ title: "AI-generated content",
12
+ body: "This content was generated by an AI system."
13
+ },
14
+ edited: {
15
+ label: "AI-edited",
16
+ title: "Edited with AI",
17
+ body: "This content was edited or altered with an AI system."
18
+ },
19
+ deepfake: {
20
+ label: "Artificially generated",
21
+ title: "Artificially generated or manipulated",
22
+ body: "This content was generated or manipulated with AI. It may show people, places or events differently from how they really were."
23
+ },
24
+ "emotion-recognition": {
25
+ label: "Emotion recognition",
26
+ title: "Emotion recognition is active",
27
+ body: "This service uses an AI system that recognises emotions or intentions from your data."
28
+ },
29
+ "biometric-categorisation": {
30
+ label: "Biometric categorisation",
31
+ title: "Biometric categorisation is active",
32
+ body: "This service uses an AI system that assigns people to categories based on biometric data."
33
+ }
34
+ },
35
+ ui: {
36
+ acknowledge: "Got it",
37
+ details: "About this label",
38
+ generatedWith: "Generated with {generator}",
39
+ createdOn: "Created on {date}",
40
+ humanReviewed: "Reviewed by a person",
41
+ moreInfo: "How we use AI",
42
+ close: "Close"
43
+ }
44
+ };
45
+ var de = {
46
+ kinds: {
47
+ chatbot: {
48
+ label: "KI-Assistent",
49
+ title: "Sie chatten mit einer KI",
50
+ body: "Dieser Assistent ist ein KI-System und kein Mensch. Seine Antworten werden automatisch erzeugt und k\xF6nnen falsch sein."
51
+ },
52
+ generated: {
53
+ label: "KI-generiert",
54
+ title: "KI-generierter Inhalt",
55
+ body: "Dieser Inhalt wurde von einem KI-System erzeugt."
56
+ },
57
+ edited: {
58
+ label: "Mit KI bearbeitet",
59
+ title: "Mit KI bearbeitet",
60
+ body: "Dieser Inhalt wurde mit einem KI-System bearbeitet oder ver\xE4ndert."
61
+ },
62
+ deepfake: {
63
+ label: "K\xFCnstlich erzeugt",
64
+ title: "K\xFCnstlich erzeugt oder ver\xE4ndert",
65
+ body: "Dieser Inhalt wurde mit KI erzeugt oder ver\xE4ndert. Er kann Personen, Orte oder Ereignisse anders zeigen, als sie wirklich waren."
66
+ },
67
+ "emotion-recognition": {
68
+ label: "Emotionserkennung",
69
+ title: "Emotionserkennung ist aktiv",
70
+ body: "Dieser Dienst setzt ein KI-System ein, das aus Ihren Daten Emotionen oder Absichten erkennt."
71
+ },
72
+ "biometric-categorisation": {
73
+ label: "Biometrische Kategorisierung",
74
+ title: "Biometrische Kategorisierung ist aktiv",
75
+ body: "Dieser Dienst setzt ein KI-System ein, das Personen anhand biometrischer Daten Kategorien zuordnet."
76
+ }
77
+ },
78
+ ui: {
79
+ acknowledge: "Verstanden",
80
+ details: "\xDCber diese Kennzeichnung",
81
+ generatedWith: "Erzeugt mit {generator}",
82
+ createdOn: "Erstellt am {date}",
83
+ humanReviewed: "Von einem Menschen gepr\xFCft",
84
+ moreInfo: "Wie wir KI einsetzen",
85
+ close: "Schliessen"
86
+ }
87
+ };
88
+ var fr = {
89
+ kinds: {
90
+ chatbot: {
91
+ label: "Assistant IA",
92
+ title: "Vous discutez avec une IA",
93
+ body: "Cet assistant est un syst\xE8me d\u2019IA, pas une personne. Ses r\xE9ponses sont g\xE9n\xE9r\xE9es automatiquement et peuvent \xEAtre erron\xE9es."
94
+ },
95
+ generated: {
96
+ label: "G\xE9n\xE9r\xE9 par IA",
97
+ title: "Contenu g\xE9n\xE9r\xE9 par IA",
98
+ body: "Ce contenu a \xE9t\xE9 g\xE9n\xE9r\xE9 par un syst\xE8me d\u2019IA."
99
+ },
100
+ edited: {
101
+ label: "Modifi\xE9 par IA",
102
+ title: "Modifi\xE9 avec l\u2019IA",
103
+ body: "Ce contenu a \xE9t\xE9 modifi\xE9 ou alt\xE9r\xE9 \xE0 l\u2019aide d\u2019un syst\xE8me d\u2019IA."
104
+ },
105
+ deepfake: {
106
+ label: "G\xE9n\xE9r\xE9 artificiellement",
107
+ title: "G\xE9n\xE9r\xE9 ou manipul\xE9 artificiellement",
108
+ body: "Ce contenu a \xE9t\xE9 g\xE9n\xE9r\xE9 ou manipul\xE9 avec l\u2019IA. Il peut montrer des personnes, des lieux ou des \xE9v\xE9nements autrement qu\u2019ils n\u2019ont r\xE9ellement \xE9t\xE9."
109
+ },
110
+ "emotion-recognition": {
111
+ label: "Reconnaissance des \xE9motions",
112
+ title: "La reconnaissance des \xE9motions est active",
113
+ body: "Ce service utilise un syst\xE8me d\u2019IA qui reconna\xEEt des \xE9motions ou des intentions \xE0 partir de vos donn\xE9es."
114
+ },
115
+ "biometric-categorisation": {
116
+ label: "Cat\xE9gorisation biom\xE9trique",
117
+ title: "La cat\xE9gorisation biom\xE9trique est active",
118
+ body: "Ce service utilise un syst\xE8me d\u2019IA qui classe les personnes dans des cat\xE9gories \xE0 partir de donn\xE9es biom\xE9triques."
119
+ }
120
+ },
121
+ ui: {
122
+ acknowledge: "Compris",
123
+ details: "\xC0 propos de ce label",
124
+ generatedWith: "G\xE9n\xE9r\xE9 avec {generator}",
125
+ createdOn: "Cr\xE9\xE9 le {date}",
126
+ humanReviewed: "V\xE9rifi\xE9 par une personne",
127
+ moreInfo: "Comment nous utilisons l\u2019IA",
128
+ close: "Fermer"
129
+ }
130
+ };
131
+ var it = {
132
+ kinds: {
133
+ chatbot: {
134
+ label: "Assistente IA",
135
+ title: "Stai parlando con un\u2019IA",
136
+ body: "Questo assistente \xE8 un sistema di IA, non una persona. Le sue risposte sono generate automaticamente e possono essere sbagliate."
137
+ },
138
+ generated: {
139
+ label: "Generato con IA",
140
+ title: "Contenuto generato con IA",
141
+ body: "Questo contenuto \xE8 stato generato da un sistema di IA."
142
+ },
143
+ edited: {
144
+ label: "Modificato con IA",
145
+ title: "Modificato con l\u2019IA",
146
+ body: "Questo contenuto \xE8 stato modificato o alterato con un sistema di IA."
147
+ },
148
+ deepfake: {
149
+ label: "Generato artificialmente",
150
+ title: "Generato o manipolato artificialmente",
151
+ body: "Questo contenuto \xE8 stato generato o manipolato con l\u2019IA. Pu\xF2 mostrare persone, luoghi o eventi in modo diverso da come sono stati realmente."
152
+ },
153
+ "emotion-recognition": {
154
+ label: "Riconoscimento delle emozioni",
155
+ title: "Il riconoscimento delle emozioni \xE8 attivo",
156
+ body: "Questo servizio utilizza un sistema di IA che riconosce emozioni o intenzioni a partire dai tuoi dati."
157
+ },
158
+ "biometric-categorisation": {
159
+ label: "Categorizzazione biometrica",
160
+ title: "La categorizzazione biometrica \xE8 attiva",
161
+ body: "Questo servizio utilizza un sistema di IA che assegna le persone a categorie in base a dati biometrici."
162
+ }
163
+ },
164
+ ui: {
165
+ acknowledge: "Ho capito",
166
+ details: "Informazioni su questa etichetta",
167
+ generatedWith: "Generato con {generator}",
168
+ createdOn: "Creato il {date}",
169
+ humanReviewed: "Verificato da una persona",
170
+ moreInfo: "Come usiamo l\u2019IA",
171
+ close: "Chiudi"
172
+ }
173
+ };
174
+ var registry = /* @__PURE__ */ new Map([
175
+ ["en", en],
176
+ ["de", de],
177
+ ["fr", fr],
178
+ ["it", it]
179
+ ]);
180
+ var BUILT_IN_LOCALES = ["en", "de", "fr", "it"];
181
+ function registerLocale(code, messages) {
182
+ const key = code.toLowerCase();
183
+ const base = registry.get(key) ?? registry.get(key.split("-")[0] ?? "") ?? en;
184
+ registry.set(key, mergeMessages(base, messages));
185
+ }
186
+ function registeredLocales() {
187
+ return [...registry.keys()];
188
+ }
189
+ function resolveLocale(input) {
190
+ const tags = input == null ? [] : typeof input === "string" ? [input] : input;
191
+ for (const tag of tags) {
192
+ const lower = tag.toLowerCase();
193
+ if (registry.has(lower)) return lower;
194
+ const language = lower.split("-")[0] ?? "";
195
+ if (registry.has(language)) return language;
196
+ }
197
+ return "en";
198
+ }
199
+ function getMessages(locale, override) {
200
+ const messages = registry.get(resolveLocale(locale)) ?? en;
201
+ return override ? mergeMessages(messages, override) : messages;
202
+ }
203
+ function disclosureText(kind, locale, override) {
204
+ return getMessages(locale, override).kinds[kind];
205
+ }
206
+ function format(template, values) {
207
+ return template.replace(/\{(\w+)\}/g, (match, name) => values[name] ?? match);
208
+ }
209
+ function mergeMessages(base, override) {
210
+ const kinds = { ...base.kinds };
211
+ for (const [kind, text] of Object.entries(override.kinds ?? {})) {
212
+ const key = kind;
213
+ kinds[key] = { ...base.kinds[key], ...text };
214
+ }
215
+ const ui = { ...base.ui, ...override.ui ?? {} };
216
+ return { kinds, ui };
217
+ }
218
+
219
+ export {
220
+ BUILT_IN_LOCALES,
221
+ registerLocale,
222
+ registeredLocales,
223
+ resolveLocale,
224
+ getMessages,
225
+ disclosureText,
226
+ format
227
+ };
228
+ //# sourceMappingURL=chunk-L65R2SM5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/i18n.ts"],"sourcesContent":["import type {\n DisclosureKind,\n DisclosureText,\n LocaleMessages,\n LocaleOverride,\n UiText,\n} from \"./types.js\";\n\nconst en: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"AI assistant\",\n title: \"You are chatting with an AI\",\n body: \"This assistant is an AI system, not a person. Its answers are generated automatically and can be wrong.\",\n },\n generated: {\n label: \"AI-generated\",\n title: \"AI-generated content\",\n body: \"This content was generated by an AI system.\",\n },\n edited: {\n label: \"AI-edited\",\n title: \"Edited with AI\",\n body: \"This content was edited or altered with an AI system.\",\n },\n deepfake: {\n label: \"Artificially generated\",\n title: \"Artificially generated or manipulated\",\n body: \"This content was generated or manipulated with AI. It may show people, places or events differently from how they really were.\",\n },\n \"emotion-recognition\": {\n label: \"Emotion recognition\",\n title: \"Emotion recognition is active\",\n body: \"This service uses an AI system that recognises emotions or intentions from your data.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometric categorisation\",\n title: \"Biometric categorisation is active\",\n body: \"This service uses an AI system that assigns people to categories based on biometric data.\",\n },\n },\n ui: {\n acknowledge: \"Got it\",\n details: \"About this label\",\n generatedWith: \"Generated with {generator}\",\n createdOn: \"Created on {date}\",\n humanReviewed: \"Reviewed by a person\",\n moreInfo: \"How we use AI\",\n close: \"Close\",\n },\n};\n\nconst de: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"KI-Assistent\",\n title: \"Sie chatten mit einer KI\",\n body: \"Dieser Assistent ist ein KI-System und kein Mensch. Seine Antworten werden automatisch erzeugt und können falsch sein.\",\n },\n generated: {\n label: \"KI-generiert\",\n title: \"KI-generierter Inhalt\",\n body: \"Dieser Inhalt wurde von einem KI-System erzeugt.\",\n },\n edited: {\n label: \"Mit KI bearbeitet\",\n title: \"Mit KI bearbeitet\",\n body: \"Dieser Inhalt wurde mit einem KI-System bearbeitet oder verändert.\",\n },\n deepfake: {\n label: \"Künstlich erzeugt\",\n title: \"Künstlich erzeugt oder verändert\",\n body: \"Dieser Inhalt wurde mit KI erzeugt oder verändert. Er kann Personen, Orte oder Ereignisse anders zeigen, als sie wirklich waren.\",\n },\n \"emotion-recognition\": {\n label: \"Emotionserkennung\",\n title: \"Emotionserkennung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das aus Ihren Daten Emotionen oder Absichten erkennt.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometrische Kategorisierung\",\n title: \"Biometrische Kategorisierung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das Personen anhand biometrischer Daten Kategorien zuordnet.\",\n },\n },\n ui: {\n acknowledge: \"Verstanden\",\n details: \"Über diese Kennzeichnung\",\n generatedWith: \"Erzeugt mit {generator}\",\n createdOn: \"Erstellt am {date}\",\n humanReviewed: \"Von einem Menschen geprüft\",\n moreInfo: \"Wie wir KI einsetzen\",\n close: \"Schliessen\",\n },\n};\n\nconst fr: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistant IA\",\n title: \"Vous discutez avec une IA\",\n body: \"Cet assistant est un système d’IA, pas une personne. Ses réponses sont générées automatiquement et peuvent être erronées.\",\n },\n generated: {\n label: \"Généré par IA\",\n title: \"Contenu généré par IA\",\n body: \"Ce contenu a été généré par un système d’IA.\",\n },\n edited: {\n label: \"Modifié par IA\",\n title: \"Modifié avec l’IA\",\n body: \"Ce contenu a été modifié ou altéré à l’aide d’un système d’IA.\",\n },\n deepfake: {\n label: \"Généré artificiellement\",\n title: \"Généré ou manipulé artificiellement\",\n body: \"Ce contenu a été généré ou manipulé avec l’IA. Il peut montrer des personnes, des lieux ou des événements autrement qu’ils n’ont réellement été.\",\n },\n \"emotion-recognition\": {\n label: \"Reconnaissance des émotions\",\n title: \"La reconnaissance des émotions est active\",\n body: \"Ce service utilise un système d’IA qui reconnaît des émotions ou des intentions à partir de vos données.\",\n },\n \"biometric-categorisation\": {\n label: \"Catégorisation biométrique\",\n title: \"La catégorisation biométrique est active\",\n body: \"Ce service utilise un système d’IA qui classe les personnes dans des catégories à partir de données biométriques.\",\n },\n },\n ui: {\n acknowledge: \"Compris\",\n details: \"À propos de ce label\",\n generatedWith: \"Généré avec {generator}\",\n createdOn: \"Créé le {date}\",\n humanReviewed: \"Vérifié par une personne\",\n moreInfo: \"Comment nous utilisons l’IA\",\n close: \"Fermer\",\n },\n};\n\nconst it: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistente IA\",\n title: \"Stai parlando con un’IA\",\n body: \"Questo assistente è un sistema di IA, non una persona. Le sue risposte sono generate automaticamente e possono essere sbagliate.\",\n },\n generated: {\n label: \"Generato con IA\",\n title: \"Contenuto generato con IA\",\n body: \"Questo contenuto è stato generato da un sistema di IA.\",\n },\n edited: {\n label: \"Modificato con IA\",\n title: \"Modificato con l’IA\",\n body: \"Questo contenuto è stato modificato o alterato con un sistema di IA.\",\n },\n deepfake: {\n label: \"Generato artificialmente\",\n title: \"Generato o manipolato artificialmente\",\n body: \"Questo contenuto è stato generato o manipolato con l’IA. Può mostrare persone, luoghi o eventi in modo diverso da come sono stati realmente.\",\n },\n \"emotion-recognition\": {\n label: \"Riconoscimento delle emozioni\",\n title: \"Il riconoscimento delle emozioni è attivo\",\n body: \"Questo servizio utilizza un sistema di IA che riconosce emozioni o intenzioni a partire dai tuoi dati.\",\n },\n \"biometric-categorisation\": {\n label: \"Categorizzazione biometrica\",\n title: \"La categorizzazione biometrica è attiva\",\n body: \"Questo servizio utilizza un sistema di IA che assegna le persone a categorie in base a dati biometrici.\",\n },\n },\n ui: {\n acknowledge: \"Ho capito\",\n details: \"Informazioni su questa etichetta\",\n generatedWith: \"Generato con {generator}\",\n createdOn: \"Creato il {date}\",\n humanReviewed: \"Verificato da una persona\",\n moreInfo: \"Come usiamo l’IA\",\n close: \"Chiudi\",\n },\n};\n\nconst registry = new Map<string, LocaleMessages>([\n [\"en\", en],\n [\"de\", de],\n [\"fr\", fr],\n [\"it\", it],\n]);\n\n/** The locales bundled with the free package. */\nexport const BUILT_IN_LOCALES = [\"en\", \"de\", \"fr\", \"it\"] as const;\n\n/**\n * Adds or replaces a locale, e.g. one of the 24 EU languages from Witness Pro.\n * A partial override is merged over the existing locale of that code, or over English.\n */\nexport function registerLocale(code: string, messages: LocaleMessages | LocaleOverride): void {\n const key = code.toLowerCase();\n const base = registry.get(key) ?? registry.get(key.split(\"-\")[0] ?? \"\") ?? en;\n registry.set(key, mergeMessages(base, messages));\n}\n\n/** Codes of all registered locales. */\nexport function registeredLocales(): string[] {\n return [...registry.keys()];\n}\n\n/**\n * Picks the best registered locale for a tag such as \"de-CH\" or a list of tags such as\n * `navigator.languages`. Falls back to English.\n */\nexport function resolveLocale(input?: string | readonly string[] | null): string {\n const tags = input == null ? [] : typeof input === \"string\" ? [input] : input;\n for (const tag of tags) {\n const lower = tag.toLowerCase();\n if (registry.has(lower)) return lower;\n const language = lower.split(\"-\")[0] ?? \"\";\n if (registry.has(language)) return language;\n }\n return \"en\";\n}\n\n/** All messages of a locale, with an optional override merged in. */\nexport function getMessages(\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): LocaleMessages {\n const messages = registry.get(resolveLocale(locale)) ?? en;\n return override ? mergeMessages(messages, override) : messages;\n}\n\n/** Wording for one disclosure kind. */\nexport function disclosureText(\n kind: DisclosureKind,\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): DisclosureText {\n return getMessages(locale, override).kinds[kind];\n}\n\n/** Replaces `{name}` placeholders. Unknown placeholders stay as they are. */\nexport function format(template: string, values: Record<string, string | undefined>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => values[name] ?? match);\n}\n\nfunction mergeMessages(\n base: LocaleMessages,\n override: LocaleMessages | LocaleOverride,\n): LocaleMessages {\n const kinds = { ...base.kinds };\n for (const [kind, text] of Object.entries(override.kinds ?? {})) {\n const key = kind as DisclosureKind;\n kinds[key] = { ...base.kinds[key], ...(text as Partial<DisclosureText>) };\n }\n const ui: UiText = { ...base.ui, ...(override.ui ?? {}) };\n return { kinds, ui };\n}\n"],"mappings":"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","names":[]}