@sweberdev/witness 0.0.0-stage → 0.1.0

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-DHX7SNWE.js +310 -0
  18. package/dist/chunk-DHX7SNWE.js.map +1 -0
  19. package/dist/chunk-L65R2SM5.js +228 -0
  20. package/dist/chunk-L65R2SM5.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 +642 -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 +639 -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 +356 -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,310 @@
1
+ import {
2
+ DISCLOSURE_KINDS,
3
+ createDisclosure
4
+ } from "./chunk-XJOQ5IUT.js";
5
+ import {
6
+ format,
7
+ getMessages
8
+ } from "./chunk-L65R2SM5.js";
9
+
10
+ // src/elements.ts
11
+ var BaseElement = typeof HTMLElement === "undefined" ? class {
12
+ } : HTMLElement;
13
+ var SHARED_CSS = `
14
+ :host { --witness-accent: #003399; --witness-accent-text: #ffffff; --witness-bg: #ffffff;
15
+ --witness-fg: #1a1a1a; --witness-muted: #555b66; --witness-border: #d7dbe3; --witness-radius: 8px;
16
+ font: inherit; color: var(--witness-fg); }
17
+ @media (prefers-color-scheme: dark) {
18
+ :host { --witness-accent: #8fb0ff; --witness-accent-text: #0b1530; --witness-bg: #15181f;
19
+ --witness-fg: #eef1f6; --witness-muted: #a9b0bd; --witness-border: #2c323d; }
20
+ }
21
+ .icon { display: inline-flex; align-items: center; justify-content: center; min-width: 1.75em;
22
+ height: 1.5em; padding: 0 .3em; border-radius: 4px; background: var(--witness-accent);
23
+ color: var(--witness-accent-text); font-weight: 700; font-size: .75em; letter-spacing: .02em;
24
+ line-height: 1; flex: none; }
25
+ button { font: inherit; cursor: pointer; }
26
+ button:focus-visible, a:focus-visible { outline: 2px solid var(--witness-accent); outline-offset: 2px; }
27
+ a { color: inherit; }
28
+ .muted { color: var(--witness-muted); }
29
+ `;
30
+ var NOTICE_CSS = `${SHARED_CSS}
31
+ :host { display: block; }
32
+ .notice { display: flex; gap: .75em; align-items: flex-start; padding: .875em 1em;
33
+ border: 1px solid var(--witness-border); border-left: 4px solid var(--witness-accent);
34
+ border-radius: var(--witness-radius); background: var(--witness-bg); }
35
+ .notice h2 { font-size: 1em; margin: 0 0 .25em; }
36
+ .notice p { margin: 0 0 .75em; line-height: 1.45; }
37
+ .actions { display: flex; gap: .75em; align-items: center; flex-wrap: wrap; }
38
+ .ack { padding: .4em .9em; border-radius: 6px; border: 0; background: var(--witness-accent);
39
+ color: var(--witness-accent-text); font-weight: 600; }
40
+ .compact { display: inline-flex; gap: .5em; align-items: center; padding: .25em .5em;
41
+ border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);
42
+ color: var(--witness-fg); font-size: .875em; }
43
+ `;
44
+ var LABEL_CSS = `${SHARED_CSS}
45
+ :host { display: inline-block; position: relative; font-size: .875em; }
46
+ :host([variant="overlay"]) { position: absolute; inset-block-start: .5em; inset-inline-end: .5em; z-index: 1; }
47
+ .badge { display: inline-flex; gap: .4em; align-items: center; padding: .2em .55em .2em .25em;
48
+ border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);
49
+ color: var(--witness-fg); }
50
+ .panel { position: absolute; inset-block-start: calc(100% + .4em); inset-inline-end: 0; z-index: 10;
51
+ width: max-content; max-width: min(22em, 80vw); padding: .75em .875em; text-align: start;
52
+ border: 1px solid var(--witness-border); border-radius: var(--witness-radius);
53
+ background: var(--witness-bg); box-shadow: 0 6px 24px rgb(0 0 0 / .15); line-height: 1.45; }
54
+ :host([variant="inline"]) .panel, :host(:not([variant])) .panel { inset-inline-end: auto; inset-inline-start: 0; }
55
+ .panel strong { display: block; margin-bottom: .25em; }
56
+ .panel p { margin: 0 0 .4em; }
57
+ .panel ul { margin: .4em 0; padding-inline-start: 1.1em; }
58
+ .close { position: absolute; inset-block-start: .35em; inset-inline-end: .35em; border: 0;
59
+ background: none; color: var(--witness-muted); font-size: 1.1em; line-height: 1; padding: .2em .35em; }
60
+ [hidden] { display: none !important; }
61
+ `;
62
+ function locale(el) {
63
+ const own = el.getAttribute("locale") ?? el.closest("[lang]")?.getAttribute("lang");
64
+ if (own) return [own];
65
+ return typeof navigator !== "undefined" ? [...navigator.languages] : [];
66
+ }
67
+ function kindOf(el, fallback) {
68
+ const value = el.getAttribute("kind");
69
+ return value && DISCLOSURE_KINDS.includes(value) ? value : fallback;
70
+ }
71
+ function h(doc, tag, attrs = {}, ...children) {
72
+ const el = doc.createElement(tag);
73
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
74
+ for (const child of children) {
75
+ if (child !== null) el.append(child);
76
+ }
77
+ return el;
78
+ }
79
+ function icon(doc) {
80
+ return h(doc, "span", { class: "icon", "aria-hidden": "true", part: "icon" }, "AI");
81
+ }
82
+ var WitnessNoticeElement = class extends BaseElement {
83
+ static {
84
+ this.observedAttributes = ["kind", "locale", "disclosure-id", "version", "href", "storage"];
85
+ }
86
+ #disclosure = null;
87
+ #unsubscribe = null;
88
+ #expanded = false;
89
+ connectedCallback() {
90
+ if (!this.shadowRoot) this.attachShadow({ mode: "open" });
91
+ this.#setup();
92
+ }
93
+ disconnectedCallback() {
94
+ this.#unsubscribe?.();
95
+ this.#unsubscribe = null;
96
+ }
97
+ attributeChangedCallback() {
98
+ if (this.isConnected && this.shadowRoot) this.#setup();
99
+ }
100
+ /** Forgets the acknowledgement and shows the full notice again. */
101
+ reset() {
102
+ this.#disclosure?.reset();
103
+ }
104
+ get disclosure() {
105
+ return this.#disclosure;
106
+ }
107
+ #setup() {
108
+ this.#unsubscribe?.();
109
+ const storage = this.getAttribute("storage");
110
+ const kind = kindOf(this, "chatbot");
111
+ const tags = locale(this);
112
+ this.#disclosure = createDisclosure({
113
+ kind,
114
+ id: this.getAttribute("disclosure-id") ?? kind,
115
+ version: this.getAttribute("version") ?? "1",
116
+ locale: getLocaleCode(tags),
117
+ ...storage === "session" || storage === "memory" || storage === "local" ? { storage } : {},
118
+ onEvent: (event) => this.#dispatch(event)
119
+ });
120
+ this.#expanded = false;
121
+ this.#unsubscribe = this.#disclosure.subscribe(() => {
122
+ this.#expanded = false;
123
+ this.#render();
124
+ });
125
+ this.#render();
126
+ }
127
+ #dispatch(event) {
128
+ this.dispatchEvent(
129
+ new CustomEvent(`witness-${event.type}`, { detail: event, bubbles: true, composed: true })
130
+ );
131
+ }
132
+ #render() {
133
+ const root = this.shadowRoot;
134
+ const disclosure = this.#disclosure;
135
+ if (!root || !disclosure) return;
136
+ const doc = this.ownerDocument;
137
+ const messages = getMessages(locale(this));
138
+ const text = messages.kinds[disclosure.kind];
139
+ const href = this.getAttribute("href");
140
+ const full = this.#expanded || disclosure.needsAcknowledgement();
141
+ const style = h(doc, "style", {}, NOTICE_CSS);
142
+ if (full) {
143
+ const ack = h(
144
+ doc,
145
+ "button",
146
+ { type: "button", class: "ack", part: "button" },
147
+ messages.ui.acknowledge
148
+ );
149
+ ack.addEventListener("click", () => disclosure.acknowledge());
150
+ const link = href ? h(doc, "a", { href, part: "link" }, messages.ui.moreInfo) : null;
151
+ const box = h(
152
+ doc,
153
+ "section",
154
+ { class: "notice", role: "note", "aria-labelledby": "title", part: "notice" },
155
+ icon(doc),
156
+ h(
157
+ doc,
158
+ "div",
159
+ {},
160
+ h(doc, "h2", { id: "title", part: "title" }, text.title),
161
+ h(doc, "p", { part: "body" }, h(doc, "slot", {}, text.body)),
162
+ h(doc, "div", { class: "actions" }, ack, link)
163
+ )
164
+ );
165
+ root.replaceChildren(style, box);
166
+ disclosure.markShown();
167
+ } else {
168
+ const reopen = h(
169
+ doc,
170
+ "button",
171
+ {
172
+ type: "button",
173
+ class: "compact",
174
+ "aria-label": `${text.label}: ${messages.ui.details}`,
175
+ part: "compact"
176
+ },
177
+ icon(doc),
178
+ text.label
179
+ );
180
+ reopen.addEventListener("click", () => {
181
+ this.#expanded = true;
182
+ this.#render();
183
+ });
184
+ root.replaceChildren(style, reopen);
185
+ }
186
+ }
187
+ };
188
+ var WitnessLabelElement = class extends BaseElement {
189
+ static {
190
+ this.observedAttributes = [
191
+ "kind",
192
+ "locale",
193
+ "generator",
194
+ "generator-version",
195
+ "created",
196
+ "reviewed",
197
+ "href",
198
+ "variant"
199
+ ];
200
+ }
201
+ #open = false;
202
+ #onKey = (event) => {
203
+ if (event.key === "Escape" && this.#open) {
204
+ this.#toggle(false);
205
+ this.shadowRoot?.querySelector(".badge")?.focus();
206
+ }
207
+ };
208
+ #onOutside = (event) => {
209
+ if (this.#open && !event.composedPath().includes(this)) this.#toggle(false);
210
+ };
211
+ connectedCallback() {
212
+ if (!this.shadowRoot) this.attachShadow({ mode: "open" });
213
+ this.ownerDocument.addEventListener("keydown", this.#onKey);
214
+ this.ownerDocument.addEventListener("click", this.#onOutside);
215
+ this.#render();
216
+ }
217
+ disconnectedCallback() {
218
+ this.ownerDocument.removeEventListener("keydown", this.#onKey);
219
+ this.ownerDocument.removeEventListener("click", this.#onOutside);
220
+ }
221
+ attributeChangedCallback() {
222
+ if (this.isConnected && this.shadowRoot) this.#render();
223
+ }
224
+ #toggle(open) {
225
+ this.#open = open;
226
+ this.#render();
227
+ }
228
+ #render() {
229
+ const root = this.shadowRoot;
230
+ if (!root) return;
231
+ const doc = this.ownerDocument;
232
+ const tags = locale(this);
233
+ const messages = getMessages(tags);
234
+ const kind = kindOf(this, "generated");
235
+ const text = messages.kinds[kind];
236
+ const generator = [this.getAttribute("generator"), this.getAttribute("generator-version")].filter(Boolean).join(" ");
237
+ const created = this.getAttribute("created");
238
+ const href = this.getAttribute("href");
239
+ const badge = h(
240
+ doc,
241
+ "button",
242
+ {
243
+ type: "button",
244
+ class: "badge",
245
+ part: "badge",
246
+ "aria-expanded": String(this.#open),
247
+ "aria-controls": "panel",
248
+ title: messages.ui.details
249
+ },
250
+ icon(doc),
251
+ h(doc, "span", { part: "label" }, text.label)
252
+ );
253
+ badge.addEventListener("click", () => this.#toggle(!this.#open));
254
+ const facts = h(doc, "ul", {});
255
+ if (generator) facts.append(h(doc, "li", {}, format(messages.ui.generatedWith, { generator })));
256
+ if (created) {
257
+ facts.append(
258
+ h(doc, "li", {}, format(messages.ui.createdOn, { date: formatDate(created, tags) }))
259
+ );
260
+ }
261
+ if (this.hasAttribute("reviewed")) facts.append(h(doc, "li", {}, messages.ui.humanReviewed));
262
+ const close = h(
263
+ doc,
264
+ "button",
265
+ { type: "button", class: "close", "aria-label": messages.ui.close },
266
+ "\xD7"
267
+ );
268
+ close.addEventListener("click", () => this.#toggle(false));
269
+ const panel = h(
270
+ doc,
271
+ "div",
272
+ { id: "panel", class: "panel", role: "dialog", "aria-label": text.title, part: "panel" },
273
+ close,
274
+ h(doc, "strong", {}, text.title),
275
+ h(doc, "p", {}, text.body),
276
+ facts.childElementCount > 0 ? facts : null,
277
+ href ? h(doc, "a", { href, part: "link" }, messages.ui.moreInfo) : null
278
+ );
279
+ if (!this.#open) panel.hidden = true;
280
+ root.replaceChildren(h(doc, "style", {}, LABEL_CSS), badge, panel);
281
+ }
282
+ };
283
+ function formatDate(value, tags) {
284
+ const date = new Date(value);
285
+ if (Number.isNaN(date.getTime())) return value;
286
+ try {
287
+ return new Intl.DateTimeFormat(tags.length > 0 ? tags : void 0, {
288
+ dateStyle: "medium"
289
+ }).format(date);
290
+ } catch {
291
+ return value;
292
+ }
293
+ }
294
+ function getLocaleCode(tags) {
295
+ return tags[0] ?? "en";
296
+ }
297
+ function defineWitnessElements() {
298
+ if (typeof customElements === "undefined") return;
299
+ if (!customElements.get("witness-notice"))
300
+ customElements.define("witness-notice", WitnessNoticeElement);
301
+ if (!customElements.get("witness-label"))
302
+ customElements.define("witness-label", WitnessLabelElement);
303
+ }
304
+
305
+ export {
306
+ WitnessNoticeElement,
307
+ WitnessLabelElement,
308
+ defineWitnessElements
309
+ };
310
+ //# sourceMappingURL=chunk-DHX7SNWE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/elements.ts"],"sourcesContent":["/**\n * Framework-free custom elements:\n *\n * - `<witness-notice>`: the chatbot notice (Art. 50(1)). Expanded until acknowledged, then a\n * compact label that can be reopened.\n * - `<witness-label>`: a badge for AI-generated or AI-edited content with a details popover.\n *\n * Import `@sweberdev/witness/elements` to register both, or call `defineWitnessElements()`.\n */\n\nimport { createDisclosure, type Disclosure, type DisclosureEvent } from \"./disclosure.js\";\nimport { format, getMessages } from \"./i18n.js\";\nimport { DISCLOSURE_KINDS, type DisclosureKind } from \"./types.js\";\n\nconst BaseElement: typeof HTMLElement =\n typeof HTMLElement === \"undefined\" ? (class {} as unknown as typeof HTMLElement) : HTMLElement;\n\nconst SHARED_CSS = `\n:host { --witness-accent: #003399; --witness-accent-text: #ffffff; --witness-bg: #ffffff;\n --witness-fg: #1a1a1a; --witness-muted: #555b66; --witness-border: #d7dbe3; --witness-radius: 8px;\n font: inherit; color: var(--witness-fg); }\n@media (prefers-color-scheme: dark) {\n :host { --witness-accent: #8fb0ff; --witness-accent-text: #0b1530; --witness-bg: #15181f;\n --witness-fg: #eef1f6; --witness-muted: #a9b0bd; --witness-border: #2c323d; }\n}\n.icon { display: inline-flex; align-items: center; justify-content: center; min-width: 1.75em;\n height: 1.5em; padding: 0 .3em; border-radius: 4px; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 700; font-size: .75em; letter-spacing: .02em;\n line-height: 1; flex: none; }\nbutton { font: inherit; cursor: pointer; }\nbutton:focus-visible, a:focus-visible { outline: 2px solid var(--witness-accent); outline-offset: 2px; }\na { color: inherit; }\n.muted { color: var(--witness-muted); }\n`;\n\nconst NOTICE_CSS = `${SHARED_CSS}\n:host { display: block; }\n.notice { display: flex; gap: .75em; align-items: flex-start; padding: .875em 1em;\n border: 1px solid var(--witness-border); border-left: 4px solid var(--witness-accent);\n border-radius: var(--witness-radius); background: var(--witness-bg); }\n.notice h2 { font-size: 1em; margin: 0 0 .25em; }\n.notice p { margin: 0 0 .75em; line-height: 1.45; }\n.actions { display: flex; gap: .75em; align-items: center; flex-wrap: wrap; }\n.ack { padding: .4em .9em; border-radius: 6px; border: 0; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 600; }\n.compact { display: inline-flex; gap: .5em; align-items: center; padding: .25em .5em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); font-size: .875em; }\n`;\n\nconst LABEL_CSS = `${SHARED_CSS}\n:host { display: inline-block; position: relative; font-size: .875em; }\n:host([variant=\"overlay\"]) { position: absolute; inset-block-start: .5em; inset-inline-end: .5em; z-index: 1; }\n.badge { display: inline-flex; gap: .4em; align-items: center; padding: .2em .55em .2em .25em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); }\n.panel { position: absolute; inset-block-start: calc(100% + .4em); inset-inline-end: 0; z-index: 10;\n width: max-content; max-width: min(22em, 80vw); padding: .75em .875em; text-align: start;\n border: 1px solid var(--witness-border); border-radius: var(--witness-radius);\n background: var(--witness-bg); box-shadow: 0 6px 24px rgb(0 0 0 / .15); line-height: 1.45; }\n:host([variant=\"inline\"]) .panel, :host(:not([variant])) .panel { inset-inline-end: auto; inset-inline-start: 0; }\n.panel strong { display: block; margin-bottom: .25em; }\n.panel p { margin: 0 0 .4em; }\n.panel ul { margin: .4em 0; padding-inline-start: 1.1em; }\n.close { position: absolute; inset-block-start: .35em; inset-inline-end: .35em; border: 0;\n background: none; color: var(--witness-muted); font-size: 1.1em; line-height: 1; padding: .2em .35em; }\n[hidden] { display: none !important; }\n`;\n\nfunction locale(el: HTMLElement): string[] {\n const own = el.getAttribute(\"locale\") ?? el.closest(\"[lang]\")?.getAttribute(\"lang\");\n if (own) return [own];\n return typeof navigator !== \"undefined\" ? [...navigator.languages] : [];\n}\n\nfunction kindOf(el: HTMLElement, fallback: DisclosureKind): DisclosureKind {\n const value = el.getAttribute(\"kind\") as DisclosureKind | null;\n return value && DISCLOSURE_KINDS.includes(value) ? value : fallback;\n}\n\nfunction h<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n attrs: Record<string, string> = {},\n ...children: Array<Node | string | null>\n): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tag);\n for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);\n for (const child of children) {\n if (child !== null) el.append(child);\n }\n return el;\n}\n\nfunction icon(doc: Document): HTMLElement {\n return h(doc, \"span\", { class: \"icon\", \"aria-hidden\": \"true\", part: \"icon\" }, \"AI\");\n}\n\n/** `<witness-notice kind=\"chatbot\" locale=\"de\" disclosure-id=\"support\" version=\"2\" href=\"/ki\">` */\nexport class WitnessNoticeElement extends BaseElement {\n static observedAttributes = [\"kind\", \"locale\", \"disclosure-id\", \"version\", \"href\", \"storage\"];\n\n #disclosure: Disclosure | null = null;\n #unsubscribe: (() => void) | null = null;\n #expanded = false;\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.#setup();\n }\n\n disconnectedCallback(): void {\n this.#unsubscribe?.();\n this.#unsubscribe = null;\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#setup();\n }\n\n /** Forgets the acknowledgement and shows the full notice again. */\n reset(): void {\n this.#disclosure?.reset();\n }\n\n get disclosure(): Disclosure | null {\n return this.#disclosure;\n }\n\n #setup(): void {\n this.#unsubscribe?.();\n const storage = this.getAttribute(\"storage\");\n const kind = kindOf(this, \"chatbot\");\n const tags = locale(this);\n this.#disclosure = createDisclosure({\n kind,\n id: this.getAttribute(\"disclosure-id\") ?? kind,\n version: this.getAttribute(\"version\") ?? \"1\",\n locale: getLocaleCode(tags),\n ...(storage === \"session\" || storage === \"memory\" || storage === \"local\" ? { storage } : {}),\n onEvent: (event) => this.#dispatch(event),\n });\n this.#expanded = false;\n this.#unsubscribe = this.#disclosure.subscribe(() => {\n this.#expanded = false;\n this.#render();\n });\n this.#render();\n }\n\n #dispatch(event: DisclosureEvent): void {\n this.dispatchEvent(\n new CustomEvent(`witness-${event.type}`, { detail: event, bubbles: true, composed: true }),\n );\n }\n\n #render(): void {\n const root = this.shadowRoot;\n const disclosure = this.#disclosure;\n if (!root || !disclosure) return;\n const doc = this.ownerDocument;\n const messages = getMessages(locale(this));\n const text = messages.kinds[disclosure.kind];\n const href = this.getAttribute(\"href\");\n const full = this.#expanded || disclosure.needsAcknowledgement();\n\n const style = h(doc, \"style\", {}, NOTICE_CSS);\n if (full) {\n const ack = h(\n doc,\n \"button\",\n { type: \"button\", class: \"ack\", part: \"button\" },\n messages.ui.acknowledge,\n );\n ack.addEventListener(\"click\", () => disclosure.acknowledge());\n const link = href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null;\n const box = h(\n doc,\n \"section\",\n { class: \"notice\", role: \"note\", \"aria-labelledby\": \"title\", part: \"notice\" },\n icon(doc),\n h(\n doc,\n \"div\",\n {},\n h(doc, \"h2\", { id: \"title\", part: \"title\" }, text.title),\n h(doc, \"p\", { part: \"body\" }, h(doc, \"slot\", {}, text.body)),\n h(doc, \"div\", { class: \"actions\" }, ack, link),\n ),\n );\n root.replaceChildren(style, box);\n disclosure.markShown();\n } else {\n const reopen = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"compact\",\n \"aria-label\": `${text.label}: ${messages.ui.details}`,\n part: \"compact\",\n },\n icon(doc),\n text.label,\n );\n reopen.addEventListener(\"click\", () => {\n this.#expanded = true;\n this.#render();\n });\n root.replaceChildren(style, reopen);\n }\n }\n}\n\n/** `<witness-label kind=\"generated\" generator=\"Claude\" created=\"2026-10-05\" reviewed href=\"/ki\">` */\nexport class WitnessLabelElement extends BaseElement {\n static observedAttributes = [\n \"kind\",\n \"locale\",\n \"generator\",\n \"generator-version\",\n \"created\",\n \"reviewed\",\n \"href\",\n \"variant\",\n ];\n\n #open = false;\n #onKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.#open) {\n this.#toggle(false);\n this.shadowRoot?.querySelector<HTMLButtonElement>(\".badge\")?.focus();\n }\n };\n #onOutside = (event: Event) => {\n if (this.#open && !event.composedPath().includes(this)) this.#toggle(false);\n };\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.ownerDocument.addEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.addEventListener(\"click\", this.#onOutside);\n this.#render();\n }\n\n disconnectedCallback(): void {\n this.ownerDocument.removeEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.removeEventListener(\"click\", this.#onOutside);\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#render();\n }\n\n #toggle(open: boolean): void {\n this.#open = open;\n this.#render();\n }\n\n #render(): void {\n const root = this.shadowRoot;\n if (!root) return;\n const doc = this.ownerDocument;\n const tags = locale(this);\n const messages = getMessages(tags);\n const kind = kindOf(this, \"generated\");\n const text = messages.kinds[kind];\n const generator = [this.getAttribute(\"generator\"), this.getAttribute(\"generator-version\")]\n .filter(Boolean)\n .join(\" \");\n const created = this.getAttribute(\"created\");\n const href = this.getAttribute(\"href\");\n\n const badge = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"badge\",\n part: \"badge\",\n \"aria-expanded\": String(this.#open),\n \"aria-controls\": \"panel\",\n title: messages.ui.details,\n },\n icon(doc),\n h(doc, \"span\", { part: \"label\" }, text.label),\n );\n badge.addEventListener(\"click\", () => this.#toggle(!this.#open));\n\n const facts = h(doc, \"ul\", {});\n if (generator) facts.append(h(doc, \"li\", {}, format(messages.ui.generatedWith, { generator })));\n if (created) {\n facts.append(\n h(doc, \"li\", {}, format(messages.ui.createdOn, { date: formatDate(created, tags) })),\n );\n }\n if (this.hasAttribute(\"reviewed\")) facts.append(h(doc, \"li\", {}, messages.ui.humanReviewed));\n\n const close = h(\n doc,\n \"button\",\n { type: \"button\", class: \"close\", \"aria-label\": messages.ui.close },\n \"×\",\n );\n close.addEventListener(\"click\", () => this.#toggle(false));\n\n const panel = h(\n doc,\n \"div\",\n { id: \"panel\", class: \"panel\", role: \"dialog\", \"aria-label\": text.title, part: \"panel\" },\n close,\n h(doc, \"strong\", {}, text.title),\n h(doc, \"p\", {}, text.body),\n facts.childElementCount > 0 ? facts : null,\n href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null,\n );\n if (!this.#open) panel.hidden = true;\n root.replaceChildren(h(doc, \"style\", {}, LABEL_CSS), badge, panel);\n }\n}\n\nfunction formatDate(value: string, tags: string[]): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n try {\n return new Intl.DateTimeFormat(tags.length > 0 ? tags : undefined, {\n dateStyle: \"medium\",\n }).format(date);\n } catch {\n return value;\n }\n}\n\nfunction getLocaleCode(tags: string[]): string {\n return tags[0] ?? \"en\";\n}\n\n/** Registers `<witness-notice>` and `<witness-label>` once. Safe to call during SSR. */\nexport function defineWitnessElements(): void {\n if (typeof customElements === \"undefined\") return;\n if (!customElements.get(\"witness-notice\"))\n customElements.define(\"witness-notice\", WitnessNoticeElement);\n if (!customElements.get(\"witness-label\"))\n customElements.define(\"witness-label\", WitnessLabelElement);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"witness-notice\": WitnessNoticeElement;\n \"witness-label\": WitnessLabelElement;\n }\n interface HTMLElementEventMap {\n \"witness-shown\": CustomEvent<DisclosureEvent>;\n \"witness-acknowledged\": CustomEvent<DisclosureEvent>;\n }\n}\n"],"mappings":";;;;;;;;;;AAcA,IAAM,cACJ,OAAO,gBAAgB,cAAe,MAAM;AAAC,IAAsC;AAErF,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBnB,IAAM,aAAa,GAAG,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAehC,IAAM,YAAY,GAAG,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmB/B,SAAS,OAAO,IAA2B;AACzC,QAAM,MAAM,GAAG,aAAa,QAAQ,KAAK,GAAG,QAAQ,QAAQ,GAAG,aAAa,MAAM;AAClF,MAAI,IAAK,QAAO,CAAC,GAAG;AACpB,SAAO,OAAO,cAAc,cAAc,CAAC,GAAG,UAAU,SAAS,IAAI,CAAC;AACxE;AAEA,SAAS,OAAO,IAAiB,UAA0C;AACzE,QAAM,QAAQ,GAAG,aAAa,MAAM;AACpC,SAAO,SAAS,iBAAiB,SAAS,KAAK,IAAI,QAAQ;AAC7D;AAEA,SAAS,EACP,KACA,KACA,QAAgC,CAAC,MAC9B,UACuB;AAC1B,QAAM,KAAK,IAAI,cAAc,GAAG;AAChC,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,EAAG,IAAG,aAAa,MAAM,KAAK;AAC9E,aAAW,SAAS,UAAU;AAC5B,QAAI,UAAU,KAAM,IAAG,OAAO,KAAK;AAAA,EACrC;AACA,SAAO;AACT;AAEA,SAAS,KAAK,KAA4B;AACxC,SAAO,EAAE,KAAK,QAAQ,EAAE,OAAO,QAAQ,eAAe,QAAQ,MAAM,OAAO,GAAG,IAAI;AACpF;AAGO,IAAM,uBAAN,cAAmC,YAAY;AAAA,EACpD;AAAA,SAAO,qBAAqB,CAAC,QAAQ,UAAU,iBAAiB,WAAW,QAAQ,SAAS;AAAA;AAAA,EAE5F,cAAiC;AAAA,EACjC,eAAoC;AAAA,EACpC,YAAY;AAAA,EAEZ,oBAA0B;AACxB,QAAI,CAAC,KAAK,WAAY,MAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACxD,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,uBAA6B;AAC3B,SAAK,eAAe;AACpB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,2BAAiC;AAC/B,QAAI,KAAK,eAAe,KAAK,WAAY,MAAK,OAAO;AAAA,EACvD;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEA,IAAI,aAAgC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,SAAe;AACb,SAAK,eAAe;AACpB,UAAM,UAAU,KAAK,aAAa,SAAS;AAC3C,UAAM,OAAO,OAAO,MAAM,SAAS;AACnC,UAAM,OAAO,OAAO,IAAI;AACxB,SAAK,cAAc,iBAAiB;AAAA,MAClC;AAAA,MACA,IAAI,KAAK,aAAa,eAAe,KAAK;AAAA,MAC1C,SAAS,KAAK,aAAa,SAAS,KAAK;AAAA,MACzC,QAAQ,cAAc,IAAI;AAAA,MAC1B,GAAI,YAAY,aAAa,YAAY,YAAY,YAAY,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC1F,SAAS,CAAC,UAAU,KAAK,UAAU,KAAK;AAAA,IAC1C,CAAC;AACD,SAAK,YAAY;AACjB,SAAK,eAAe,KAAK,YAAY,UAAU,MAAM;AACnD,WAAK,YAAY;AACjB,WAAK,QAAQ;AAAA,IACf,CAAC;AACD,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,UAAU,OAA8B;AACtC,SAAK;AAAA,MACH,IAAI,YAAY,WAAW,MAAM,IAAI,IAAI,EAAE,QAAQ,OAAO,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,IAC3F;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,UAAM,OAAO,KAAK;AAClB,UAAM,aAAa,KAAK;AACxB,QAAI,CAAC,QAAQ,CAAC,WAAY;AAC1B,UAAM,MAAM,KAAK;AACjB,UAAM,WAAW,YAAY,OAAO,IAAI,CAAC;AACzC,UAAM,OAAO,SAAS,MAAM,WAAW,IAAI;AAC3C,UAAM,OAAO,KAAK,aAAa,MAAM;AACrC,UAAM,OAAO,KAAK,aAAa,WAAW,qBAAqB;AAE/D,UAAM,QAAQ,EAAE,KAAK,SAAS,CAAC,GAAG,UAAU;AAC5C,QAAI,MAAM;AACR,YAAM,MAAM;AAAA,QACV;AAAA,QACA;AAAA,QACA,EAAE,MAAM,UAAU,OAAO,OAAO,MAAM,SAAS;AAAA,QAC/C,SAAS,GAAG;AAAA,MACd;AACA,UAAI,iBAAiB,SAAS,MAAM,WAAW,YAAY,CAAC;AAC5D,YAAM,OAAO,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,IAAI;AAChF,YAAM,MAAM;AAAA,QACV;AAAA,QACA;AAAA,QACA,EAAE,OAAO,UAAU,MAAM,QAAQ,mBAAmB,SAAS,MAAM,SAAS;AAAA,QAC5E,KAAK,GAAG;AAAA,QACR;AAAA,UACE;AAAA,UACA;AAAA,UACA,CAAC;AAAA,UACD,EAAE,KAAK,MAAM,EAAE,IAAI,SAAS,MAAM,QAAQ,GAAG,KAAK,KAAK;AAAA,UACvD,EAAE,KAAK,KAAK,EAAE,MAAM,OAAO,GAAG,EAAE,KAAK,QAAQ,CAAC,GAAG,KAAK,IAAI,CAAC;AAAA,UAC3D,EAAE,KAAK,OAAO,EAAE,OAAO,UAAU,GAAG,KAAK,IAAI;AAAA,QAC/C;AAAA,MACF;AACA,WAAK,gBAAgB,OAAO,GAAG;AAC/B,iBAAW,UAAU;AAAA,IACvB,OAAO;AACL,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,cAAc,GAAG,KAAK,KAAK,KAAK,SAAS,GAAG,OAAO;AAAA,UACnD,MAAM;AAAA,QACR;AAAA,QACA,KAAK,GAAG;AAAA,QACR,KAAK;AAAA,MACP;AACA,aAAO,iBAAiB,SAAS,MAAM;AACrC,aAAK,YAAY;AACjB,aAAK,QAAQ;AAAA,MACf,CAAC;AACD,WAAK,gBAAgB,OAAO,MAAM;AAAA,IACpC;AAAA,EACF;AACF;AAGO,IAAM,sBAAN,cAAkC,YAAY;AAAA,EACnD;AAAA,SAAO,qBAAqB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAEA,QAAQ;AAAA,EACR,SAAS,CAAC,UAAyB;AACjC,QAAI,MAAM,QAAQ,YAAY,KAAK,OAAO;AACxC,WAAK,QAAQ,KAAK;AAClB,WAAK,YAAY,cAAiC,QAAQ,GAAG,MAAM;AAAA,IACrE;AAAA,EACF;AAAA,EACA,aAAa,CAAC,UAAiB;AAC7B,QAAI,KAAK,SAAS,CAAC,MAAM,aAAa,EAAE,SAAS,IAAI,EAAG,MAAK,QAAQ,KAAK;AAAA,EAC5E;AAAA,EAEA,oBAA0B;AACxB,QAAI,CAAC,KAAK,WAAY,MAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACxD,SAAK,cAAc,iBAAiB,WAAW,KAAK,MAAM;AAC1D,SAAK,cAAc,iBAAiB,SAAS,KAAK,UAAU;AAC5D,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,uBAA6B;AAC3B,SAAK,cAAc,oBAAoB,WAAW,KAAK,MAAM;AAC7D,SAAK,cAAc,oBAAoB,SAAS,KAAK,UAAU;AAAA,EACjE;AAAA,EAEA,2BAAiC;AAC/B,QAAI,KAAK,eAAe,KAAK,WAAY,MAAK,QAAQ;AAAA,EACxD;AAAA,EAEA,QAAQ,MAAqB;AAC3B,SAAK,QAAQ;AACb,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,UAAgB;AACd,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,KAAM;AACX,UAAM,MAAM,KAAK;AACjB,UAAM,OAAO,OAAO,IAAI;AACxB,UAAM,WAAW,YAAY,IAAI;AACjC,UAAM,OAAO,OAAO,MAAM,WAAW;AACrC,UAAM,OAAO,SAAS,MAAM,IAAI;AAChC,UAAM,YAAY,CAAC,KAAK,aAAa,WAAW,GAAG,KAAK,aAAa,mBAAmB,CAAC,EACtF,OAAO,OAAO,EACd,KAAK,GAAG;AACX,UAAM,UAAU,KAAK,aAAa,SAAS;AAC3C,UAAM,OAAO,KAAK,aAAa,MAAM;AAErC,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,iBAAiB,OAAO,KAAK,KAAK;AAAA,QAClC,iBAAiB;AAAA,QACjB,OAAO,SAAS,GAAG;AAAA,MACrB;AAAA,MACA,KAAK,GAAG;AAAA,MACR,EAAE,KAAK,QAAQ,EAAE,MAAM,QAAQ,GAAG,KAAK,KAAK;AAAA,IAC9C;AACA,UAAM,iBAAiB,SAAS,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;AAE/D,UAAM,QAAQ,EAAE,KAAK,MAAM,CAAC,CAAC;AAC7B,QAAI,UAAW,OAAM,OAAO,EAAE,KAAK,MAAM,CAAC,GAAG,OAAO,SAAS,GAAG,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC;AAC9F,QAAI,SAAS;AACX,YAAM;AAAA,QACJ,EAAE,KAAK,MAAM,CAAC,GAAG,OAAO,SAAS,GAAG,WAAW,EAAE,MAAM,WAAW,SAAS,IAAI,EAAE,CAAC,CAAC;AAAA,MACrF;AAAA,IACF;AACA,QAAI,KAAK,aAAa,UAAU,EAAG,OAAM,OAAO,EAAE,KAAK,MAAM,CAAC,GAAG,SAAS,GAAG,aAAa,CAAC;AAE3F,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA,EAAE,MAAM,UAAU,OAAO,SAAS,cAAc,SAAS,GAAG,MAAM;AAAA,MAClE;AAAA,IACF;AACA,UAAM,iBAAiB,SAAS,MAAM,KAAK,QAAQ,KAAK,CAAC;AAEzD,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA,EAAE,IAAI,SAAS,OAAO,SAAS,MAAM,UAAU,cAAc,KAAK,OAAO,MAAM,QAAQ;AAAA,MACvF;AAAA,MACA,EAAE,KAAK,UAAU,CAAC,GAAG,KAAK,KAAK;AAAA,MAC/B,EAAE,KAAK,KAAK,CAAC,GAAG,KAAK,IAAI;AAAA,MACzB,MAAM,oBAAoB,IAAI,QAAQ;AAAA,MACtC,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,IAAI;AAAA,IACrE;AACA,QAAI,CAAC,KAAK,MAAO,OAAM,SAAS;AAChC,SAAK,gBAAgB,EAAE,KAAK,SAAS,CAAC,GAAG,SAAS,GAAG,OAAO,KAAK;AAAA,EACnE;AACF;AAEA,SAAS,WAAW,OAAe,MAAwB;AACzD,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,MAAI;AACF,WAAO,IAAI,KAAK,eAAe,KAAK,SAAS,IAAI,OAAO,QAAW;AAAA,MACjE,WAAW;AAAA,IACb,CAAC,EAAE,OAAO,IAAI;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,MAAwB;AAC7C,SAAO,KAAK,CAAC,KAAK;AACpB;AAGO,SAAS,wBAA8B;AAC5C,MAAI,OAAO,mBAAmB,YAAa;AAC3C,MAAI,CAAC,eAAe,IAAI,gBAAgB;AACtC,mBAAe,OAAO,kBAAkB,oBAAoB;AAC9D,MAAI,CAAC,eAAe,IAAI,eAAe;AACrC,mBAAe,OAAO,iBAAiB,mBAAmB;AAC9D;","names":[]}