@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.
- package/LICENSE +21 -0
- package/README.md +21 -2
- package/dist/ai-sdk.cjs +921 -0
- package/dist/ai-sdk.cjs.map +1 -0
- package/dist/ai-sdk.d.cts +95 -0
- package/dist/ai-sdk.d.ts +95 -0
- package/dist/ai-sdk.js +150 -0
- package/dist/ai-sdk.js.map +1 -0
- package/dist/bin.cjs +944 -0
- package/dist/bin.cjs.map +1 -0
- package/dist/bin.d.cts +1 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +12 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-APXU3MTX.js +958 -0
- package/dist/chunk-APXU3MTX.js.map +1 -0
- package/dist/chunk-L65R2SM5.js +228 -0
- package/dist/chunk-L65R2SM5.js.map +1 -0
- package/dist/chunk-O6TADCND.js +317 -0
- package/dist/chunk-O6TADCND.js.map +1 -0
- package/dist/chunk-UBRK4CTM.js +156 -0
- package/dist/chunk-UBRK4CTM.js.map +1 -0
- package/dist/chunk-XJOQ5IUT.js +110 -0
- package/dist/chunk-XJOQ5IUT.js.map +1 -0
- package/dist/cli.cjs +964 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +7 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -0
- package/dist/disclosure-5a3UIVQZ.d.cts +70 -0
- package/dist/disclosure-C7Y_uY73.d.ts +70 -0
- package/dist/elements-auto.cjs +649 -0
- package/dist/elements-auto.cjs.map +1 -0
- package/dist/elements-auto.d.cts +3 -0
- package/dist/elements-auto.d.ts +3 -0
- package/dist/elements-auto.js +16 -0
- package/dist/elements-auto.js.map +1 -0
- package/dist/elements.cjs +646 -0
- package/dist/elements.cjs.map +1 -0
- package/dist/elements.d.cts +47 -0
- package/dist/elements.d.ts +47 -0
- package/dist/elements.js +13 -0
- package/dist/elements.js.map +1 -0
- package/dist/image-B7YvdITx.d.ts +49 -0
- package/dist/image-BNrEO-hj.d.cts +49 -0
- package/dist/index.cjs +1344 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +124 -0
- package/dist/index.d.ts +124 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/types-WWHzrNlc.d.cts +90 -0
- package/dist/types-WWHzrNlc.d.ts +90 -0
- package/package.json +123 -3
- package/src/ai-sdk.ts +252 -0
- package/src/bin.ts +6 -0
- package/src/cli.ts +160 -0
- package/src/disclosure.ts +172 -0
- package/src/elements-auto.ts +5 -0
- package/src/elements.ts +363 -0
- package/src/i18n.ts +259 -0
- package/src/image.ts +552 -0
- package/src/index.ts +66 -0
- package/src/inflate.ts +189 -0
- package/src/marking.ts +237 -0
- package/src/types.ts +115 -0
- package/src/watermark.ts +165 -0
- package/styles.css +103 -0
package/src/i18n.ts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DisclosureKind,
|
|
3
|
+
DisclosureText,
|
|
4
|
+
LocaleMessages,
|
|
5
|
+
LocaleOverride,
|
|
6
|
+
UiText,
|
|
7
|
+
} from "./types.js";
|
|
8
|
+
|
|
9
|
+
const en: LocaleMessages = {
|
|
10
|
+
kinds: {
|
|
11
|
+
chatbot: {
|
|
12
|
+
label: "AI assistant",
|
|
13
|
+
title: "You are chatting with an AI",
|
|
14
|
+
body: "This assistant is an AI system, not a person. Its answers are generated automatically and can be wrong.",
|
|
15
|
+
},
|
|
16
|
+
generated: {
|
|
17
|
+
label: "AI-generated",
|
|
18
|
+
title: "AI-generated content",
|
|
19
|
+
body: "This content was generated by an AI system.",
|
|
20
|
+
},
|
|
21
|
+
edited: {
|
|
22
|
+
label: "AI-edited",
|
|
23
|
+
title: "Edited with AI",
|
|
24
|
+
body: "This content was edited or altered with an AI system.",
|
|
25
|
+
},
|
|
26
|
+
deepfake: {
|
|
27
|
+
label: "Artificially generated",
|
|
28
|
+
title: "Artificially generated or manipulated",
|
|
29
|
+
body: "This content was generated or manipulated with AI. It may show people, places or events differently from how they really were.",
|
|
30
|
+
},
|
|
31
|
+
"emotion-recognition": {
|
|
32
|
+
label: "Emotion recognition",
|
|
33
|
+
title: "Emotion recognition is active",
|
|
34
|
+
body: "This service uses an AI system that recognises emotions or intentions from your data.",
|
|
35
|
+
},
|
|
36
|
+
"biometric-categorisation": {
|
|
37
|
+
label: "Biometric categorisation",
|
|
38
|
+
title: "Biometric categorisation is active",
|
|
39
|
+
body: "This service uses an AI system that assigns people to categories based on biometric data.",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
ui: {
|
|
43
|
+
acknowledge: "Got it",
|
|
44
|
+
details: "About this label",
|
|
45
|
+
generatedWith: "Generated with {generator}",
|
|
46
|
+
createdOn: "Created on {date}",
|
|
47
|
+
humanReviewed: "Reviewed by a person",
|
|
48
|
+
moreInfo: "How we use AI",
|
|
49
|
+
close: "Close",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const de: LocaleMessages = {
|
|
54
|
+
kinds: {
|
|
55
|
+
chatbot: {
|
|
56
|
+
label: "KI-Assistent",
|
|
57
|
+
title: "Sie chatten mit einer KI",
|
|
58
|
+
body: "Dieser Assistent ist ein KI-System und kein Mensch. Seine Antworten werden automatisch erzeugt und können falsch sein.",
|
|
59
|
+
},
|
|
60
|
+
generated: {
|
|
61
|
+
label: "KI-generiert",
|
|
62
|
+
title: "KI-generierter Inhalt",
|
|
63
|
+
body: "Dieser Inhalt wurde von einem KI-System erzeugt.",
|
|
64
|
+
},
|
|
65
|
+
edited: {
|
|
66
|
+
label: "Mit KI bearbeitet",
|
|
67
|
+
title: "Mit KI bearbeitet",
|
|
68
|
+
body: "Dieser Inhalt wurde mit einem KI-System bearbeitet oder verändert.",
|
|
69
|
+
},
|
|
70
|
+
deepfake: {
|
|
71
|
+
label: "Künstlich erzeugt",
|
|
72
|
+
title: "Künstlich erzeugt oder verändert",
|
|
73
|
+
body: "Dieser Inhalt wurde mit KI erzeugt oder verändert. Er kann Personen, Orte oder Ereignisse anders zeigen, als sie wirklich waren.",
|
|
74
|
+
},
|
|
75
|
+
"emotion-recognition": {
|
|
76
|
+
label: "Emotionserkennung",
|
|
77
|
+
title: "Emotionserkennung ist aktiv",
|
|
78
|
+
body: "Dieser Dienst setzt ein KI-System ein, das aus Ihren Daten Emotionen oder Absichten erkennt.",
|
|
79
|
+
},
|
|
80
|
+
"biometric-categorisation": {
|
|
81
|
+
label: "Biometrische Kategorisierung",
|
|
82
|
+
title: "Biometrische Kategorisierung ist aktiv",
|
|
83
|
+
body: "Dieser Dienst setzt ein KI-System ein, das Personen anhand biometrischer Daten Kategorien zuordnet.",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
ui: {
|
|
87
|
+
acknowledge: "Verstanden",
|
|
88
|
+
details: "Über diese Kennzeichnung",
|
|
89
|
+
generatedWith: "Erzeugt mit {generator}",
|
|
90
|
+
createdOn: "Erstellt am {date}",
|
|
91
|
+
humanReviewed: "Von einem Menschen geprüft",
|
|
92
|
+
moreInfo: "Wie wir KI einsetzen",
|
|
93
|
+
close: "Schliessen",
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const fr: LocaleMessages = {
|
|
98
|
+
kinds: {
|
|
99
|
+
chatbot: {
|
|
100
|
+
label: "Assistant IA",
|
|
101
|
+
title: "Vous discutez avec une IA",
|
|
102
|
+
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.",
|
|
103
|
+
},
|
|
104
|
+
generated: {
|
|
105
|
+
label: "Généré par IA",
|
|
106
|
+
title: "Contenu généré par IA",
|
|
107
|
+
body: "Ce contenu a été généré par un système d’IA.",
|
|
108
|
+
},
|
|
109
|
+
edited: {
|
|
110
|
+
label: "Modifié par IA",
|
|
111
|
+
title: "Modifié avec l’IA",
|
|
112
|
+
body: "Ce contenu a été modifié ou altéré à l’aide d’un système d’IA.",
|
|
113
|
+
},
|
|
114
|
+
deepfake: {
|
|
115
|
+
label: "Généré artificiellement",
|
|
116
|
+
title: "Généré ou manipulé artificiellement",
|
|
117
|
+
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é.",
|
|
118
|
+
},
|
|
119
|
+
"emotion-recognition": {
|
|
120
|
+
label: "Reconnaissance des émotions",
|
|
121
|
+
title: "La reconnaissance des émotions est active",
|
|
122
|
+
body: "Ce service utilise un système d’IA qui reconnaît des émotions ou des intentions à partir de vos données.",
|
|
123
|
+
},
|
|
124
|
+
"biometric-categorisation": {
|
|
125
|
+
label: "Catégorisation biométrique",
|
|
126
|
+
title: "La catégorisation biométrique est active",
|
|
127
|
+
body: "Ce service utilise un système d’IA qui classe les personnes dans des catégories à partir de données biométriques.",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
ui: {
|
|
131
|
+
acknowledge: "Compris",
|
|
132
|
+
details: "À propos de ce label",
|
|
133
|
+
generatedWith: "Généré avec {generator}",
|
|
134
|
+
createdOn: "Créé le {date}",
|
|
135
|
+
humanReviewed: "Vérifié par une personne",
|
|
136
|
+
moreInfo: "Comment nous utilisons l’IA",
|
|
137
|
+
close: "Fermer",
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const it: LocaleMessages = {
|
|
142
|
+
kinds: {
|
|
143
|
+
chatbot: {
|
|
144
|
+
label: "Assistente IA",
|
|
145
|
+
title: "Stai parlando con un’IA",
|
|
146
|
+
body: "Questo assistente è un sistema di IA, non una persona. Le sue risposte sono generate automaticamente e possono essere sbagliate.",
|
|
147
|
+
},
|
|
148
|
+
generated: {
|
|
149
|
+
label: "Generato con IA",
|
|
150
|
+
title: "Contenuto generato con IA",
|
|
151
|
+
body: "Questo contenuto è stato generato da un sistema di IA.",
|
|
152
|
+
},
|
|
153
|
+
edited: {
|
|
154
|
+
label: "Modificato con IA",
|
|
155
|
+
title: "Modificato con l’IA",
|
|
156
|
+
body: "Questo contenuto è stato modificato o alterato con un sistema di IA.",
|
|
157
|
+
},
|
|
158
|
+
deepfake: {
|
|
159
|
+
label: "Generato artificialmente",
|
|
160
|
+
title: "Generato o manipolato artificialmente",
|
|
161
|
+
body: "Questo contenuto è stato generato o manipolato con l’IA. Può mostrare persone, luoghi o eventi in modo diverso da come sono stati realmente.",
|
|
162
|
+
},
|
|
163
|
+
"emotion-recognition": {
|
|
164
|
+
label: "Riconoscimento delle emozioni",
|
|
165
|
+
title: "Il riconoscimento delle emozioni è attivo",
|
|
166
|
+
body: "Questo servizio utilizza un sistema di IA che riconosce emozioni o intenzioni a partire dai tuoi dati.",
|
|
167
|
+
},
|
|
168
|
+
"biometric-categorisation": {
|
|
169
|
+
label: "Categorizzazione biometrica",
|
|
170
|
+
title: "La categorizzazione biometrica è attiva",
|
|
171
|
+
body: "Questo servizio utilizza un sistema di IA che assegna le persone a categorie in base a dati biometrici.",
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
ui: {
|
|
175
|
+
acknowledge: "Ho capito",
|
|
176
|
+
details: "Informazioni su questa etichetta",
|
|
177
|
+
generatedWith: "Generato con {generator}",
|
|
178
|
+
createdOn: "Creato il {date}",
|
|
179
|
+
humanReviewed: "Verificato da una persona",
|
|
180
|
+
moreInfo: "Come usiamo l’IA",
|
|
181
|
+
close: "Chiudi",
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const registry = new Map<string, LocaleMessages>([
|
|
186
|
+
["en", en],
|
|
187
|
+
["de", de],
|
|
188
|
+
["fr", fr],
|
|
189
|
+
["it", it],
|
|
190
|
+
]);
|
|
191
|
+
|
|
192
|
+
/** The locales bundled with the free package. */
|
|
193
|
+
export const BUILT_IN_LOCALES = ["en", "de", "fr", "it"] as const;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Adds or replaces a locale, e.g. one of the 24 EU languages from Witness Pro.
|
|
197
|
+
* A partial override is merged over the existing locale of that code, or over English.
|
|
198
|
+
*/
|
|
199
|
+
export function registerLocale(code: string, messages: LocaleMessages | LocaleOverride): void {
|
|
200
|
+
const key = code.toLowerCase();
|
|
201
|
+
const base = registry.get(key) ?? registry.get(key.split("-")[0] ?? "") ?? en;
|
|
202
|
+
registry.set(key, mergeMessages(base, messages));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Codes of all registered locales. */
|
|
206
|
+
export function registeredLocales(): string[] {
|
|
207
|
+
return [...registry.keys()];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Picks the best registered locale for a tag such as "de-CH" or a list of tags such as
|
|
212
|
+
* `navigator.languages`. Falls back to English.
|
|
213
|
+
*/
|
|
214
|
+
export function resolveLocale(input?: string | readonly string[] | null): string {
|
|
215
|
+
const tags = input == null ? [] : typeof input === "string" ? [input] : input;
|
|
216
|
+
for (const tag of tags) {
|
|
217
|
+
const lower = tag.toLowerCase();
|
|
218
|
+
if (registry.has(lower)) return lower;
|
|
219
|
+
const language = lower.split("-")[0] ?? "";
|
|
220
|
+
if (registry.has(language)) return language;
|
|
221
|
+
}
|
|
222
|
+
return "en";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** All messages of a locale, with an optional override merged in. */
|
|
226
|
+
export function getMessages(
|
|
227
|
+
locale?: string | readonly string[] | null,
|
|
228
|
+
override?: LocaleOverride,
|
|
229
|
+
): LocaleMessages {
|
|
230
|
+
const messages = registry.get(resolveLocale(locale)) ?? en;
|
|
231
|
+
return override ? mergeMessages(messages, override) : messages;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Wording for one disclosure kind. */
|
|
235
|
+
export function disclosureText(
|
|
236
|
+
kind: DisclosureKind,
|
|
237
|
+
locale?: string | readonly string[] | null,
|
|
238
|
+
override?: LocaleOverride,
|
|
239
|
+
): DisclosureText {
|
|
240
|
+
return getMessages(locale, override).kinds[kind];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Replaces `{name}` placeholders. Unknown placeholders stay as they are. */
|
|
244
|
+
export function format(template: string, values: Record<string, string | undefined>): string {
|
|
245
|
+
return template.replace(/\{(\w+)\}/g, (match, name: string) => values[name] ?? match);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function mergeMessages(
|
|
249
|
+
base: LocaleMessages,
|
|
250
|
+
override: LocaleMessages | LocaleOverride,
|
|
251
|
+
): LocaleMessages {
|
|
252
|
+
const kinds = { ...base.kinds };
|
|
253
|
+
for (const [kind, text] of Object.entries(override.kinds ?? {})) {
|
|
254
|
+
const key = kind as DisclosureKind;
|
|
255
|
+
kinds[key] = { ...base.kinds[key], ...(text as Partial<DisclosureText>) };
|
|
256
|
+
}
|
|
257
|
+
const ui: UiText = { ...base.ui, ...(override.ui ?? {}) };
|
|
258
|
+
return { kinds, ui };
|
|
259
|
+
}
|