@krizaka/org 0.7.2 → 1.0.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.
- package/README.md +24 -12
- package/bin/krizaka-code-names.mjs +25 -26
- package/dist/apps/{orazaka.json → folioviv.json} +2 -2
- package/dist/apps/{akinaza.json → sovkora.json} +2 -2
- package/dist/apps/{yomizaka.json → verikora.json} +2 -2
- package/dist/index.d.ts +29 -22
- package/dist/index.js +89 -143
- package/dist/index.js.map +1 -1
- package/dist/org.json +29 -29
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @krizaka/org
|
|
2
2
|
|
|
3
3
|
**The public facts about Krizaka, in one validated JSON.** The legal name, the NEQ, « Fait à Montréal » in French and English,
|
|
4
|
-
the brand marks, the default avatars, the live products (
|
|
4
|
+
the brand marks, the default avatars, the live products (Sovkora, Verikora, Folioviv), the sites, the public contact, the footer
|
|
5
5
|
line and the legal links — read by every footer, site and app, so changing one takes one pull request here.
|
|
6
6
|
|
|
7
7
|
```ts
|
|
@@ -20,7 +20,7 @@ Without a build step, read it from the CDN: [krizaka-assets.b-cdn.net/org/v1/org
|
|
|
20
20
|
`listDefaults(kind)` lists them, `defaultFor(kind, seed)` picks one deterministically (FNV-1a of the seed, modulo the list), `defaultUrl(item, size)` gives the URL,
|
|
21
21
|
`fetchDefaults(ORG_URL)` reads the section from the published JSON. A folder is never given a person.
|
|
22
22
|
- **One name per entry of the family.** `org.family` (and `familyName(id)`) is the only place a name is written: the company
|
|
23
|
-
is « Krizaka », a product goes by its own name (
|
|
23
|
+
is « Krizaka », a product goes by its own name (Sovkora, Verikora, Folioviv — never « Krizaka Verikora »), a library or a tool
|
|
24
24
|
is « Krizaka <X> » (Krizaka UI, Krizaka Java, Krizaka TypeScript, Krizaka Lab; the short name only under a
|
|
25
25
|
heading « Open source »). The bar, the switcher and every footer read it; a test holds the rule.
|
|
26
26
|
- **Public facts only.** Never an address, a phone number, figures, a secret, an IP address or an internal host: the test
|
|
@@ -45,19 +45,31 @@ The shared validation (no code name as a display name, FR/EN labels, valid URLs)
|
|
|
45
45
|
A rename is therefore: the administrator edits the value in the app's settings, saves, and the build-time pages redeploy.
|
|
46
46
|
The seed below is only the default of that setting.
|
|
47
47
|
|
|
48
|
-
##
|
|
48
|
+
## Brands (`brands`, a seed)
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
Since 1.0.0 (founder, 2026-11-06, krizaka-internal#2659) a brand's id **is** its commercial name in lower case — `verikora`,
|
|
51
|
+
`folioviv`, `sovkora`, `kridoc` — in repositories, packages, hosts and code alike. A customer reads it endorsed by the company:
|
|
52
|
+
**« Verikora by Krizaka »** / **« Verikora par Krizaka »**.
|
|
52
53
|
|
|
53
54
|
```ts
|
|
54
55
|
import { brandOf, displayName, lockup } from "@krizaka/org";
|
|
55
|
-
brandOf("
|
|
56
|
-
displayName("
|
|
57
|
-
lockup("
|
|
56
|
+
brandOf("folioviv").domains.shop; // "https://folioviv.shop"
|
|
57
|
+
displayName("verikora", settingValue); // the admin's choice (`brand.displayName`), else « Verikora »
|
|
58
|
+
lockup("sovkora", "fr"); // « Sovkora par Krizaka »
|
|
58
59
|
```
|
|
59
60
|
|
|
60
|
-
**The
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
**The historic table.** `CODE_NAMES` maps each retired code name to its brand id; it is the one place they are written. There
|
|
62
|
+
is no alias: `brandOf(<retired code name>)` throws and names the new id.
|
|
63
|
+
|
|
64
|
+
**The guard.** `npx krizaka-code-names [--report] [--allow <path-part>]... <file-or-dir>...` reads every text file under the
|
|
65
|
+
roots (code, configs, workflows, docs, messages, built HTML) and fails on a retired code name in any case, as a word or inside
|
|
66
|
+
one (environment variables, CSS classes, hosts, URLs, package coordinates, code spans): there is no allowed span. History is skipped
|
|
67
|
+
(`CHANGELOG.md` files); `--allow` skips the paths that hold a copy of the rename table. Kridoc's former wording is refused too.
|
|
68
|
+
|
|
69
|
+
### Upgrading from 0.x
|
|
70
|
+
|
|
71
|
+
- `OrgBrand.codeName` is now `OrgBrand.id`; `formerly` is gone. Call `brandOf`, `displayName` and `lockup` with the new ids.
|
|
72
|
+
- `CODE_NAMES` is a frozen `Record<retired, id>` (it was the list of ids); `codeNameMap()` maps retired → commercial name.
|
|
73
|
+
- `findCodeNames` allows nothing any more (URLs, hosts, `@krizaka/*`, `com.krizaka.*`, backticks were allowed before), and
|
|
74
|
+
`visibleText` no longer drops a `data-code-name` line.
|
|
75
|
+
- `org.products` / `org.family` ids, `apps/<id>.json` and `CastProduct` use the new ids.
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// krizaka-code-names —
|
|
2
|
+
// krizaka-code-names — no retired code name anywhere (founder, 2026-11-06, krizaka-internal#2659; first #2036).
|
|
3
3
|
// krizaka-code-names [--report] [--allow <path-part>]... <file-or-dir>...
|
|
4
|
-
// Reads
|
|
5
|
-
// and
|
|
6
|
-
//
|
|
4
|
+
// Reads every text file under the roots — code, configs, workflows, docs, messages, built HTML (raw: links, classes and
|
|
5
|
+
// scripts included) — and refuses the four retired code names in any case, as a word or inside one. There is no allowed
|
|
6
|
+
// span: the historic table is `CODE_NAMES` of @krizaka/org, and history (CHANGELOG.md files) is skipped. `--allow` skips the
|
|
7
|
+
// files whose path contains the part (a repository's own copy of the rename table). Binary files, node_modules and .git are
|
|
8
|
+
// skipped. Exit 1 on a hit; `--report` prints and exits 0.
|
|
7
9
|
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
8
|
-
import {
|
|
10
|
+
import { basename, join } from "node:path";
|
|
9
11
|
|
|
10
|
-
import {
|
|
12
|
+
import { findCodeNames } from "../dist/index.js";
|
|
11
13
|
|
|
12
14
|
const args = process.argv.slice(2);
|
|
13
15
|
const report = args.includes("--report");
|
|
@@ -22,36 +24,33 @@ if (roots.length === 0) {
|
|
|
22
24
|
console.error("usage: krizaka-code-names [--report] [--allow <path-part>]... <file-or-dir>...");
|
|
23
25
|
process.exit(2);
|
|
24
26
|
}
|
|
25
|
-
const
|
|
27
|
+
const SKIPPED_DIRS = new Set(["node_modules", ".git", ".hg", ".svn"]);
|
|
28
|
+
const HISTORY = new Set(["CHANGELOG.md"]);
|
|
26
29
|
const files = [];
|
|
27
30
|
const walk = (p) => {
|
|
28
31
|
if (allow.some((a) => p.includes(a))) return;
|
|
29
32
|
if (statSync(p).isDirectory()) {
|
|
30
|
-
for (const e of readdirSync(p)) if (
|
|
31
|
-
} else if (
|
|
33
|
+
for (const e of readdirSync(p)) if (!SKIPPED_DIRS.has(e)) walk(join(p, e));
|
|
34
|
+
} else if (!HISTORY.has(basename(p))) files.push(p);
|
|
32
35
|
};
|
|
33
36
|
roots.forEach(walk);
|
|
34
37
|
|
|
38
|
+
/** A file is text when its first 8 KiB hold no NUL byte. */
|
|
39
|
+
const isText = (buf) => !buf.subarray(0, 8192).includes(0);
|
|
40
|
+
|
|
35
41
|
let count = 0;
|
|
42
|
+
let read = 0;
|
|
36
43
|
for (const file of files) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
pieces = catalogueValues(JSON.parse(raw));
|
|
44
|
-
} catch {
|
|
45
|
-
pieces = [["", raw]];
|
|
46
|
-
}
|
|
47
|
-
} else pieces = [["", raw]];
|
|
48
|
-
for (const [key, text] of pieces) {
|
|
49
|
-
for (const hit of findCodeNames(text)) {
|
|
44
|
+
const buf = readFileSync(file);
|
|
45
|
+
if (!isText(buf)) continue;
|
|
46
|
+
read++;
|
|
47
|
+
const lines = buf.toString("utf8").split("\n");
|
|
48
|
+
lines.forEach((line, i) => {
|
|
49
|
+
for (const hit of findCodeNames(line)) {
|
|
50
50
|
count++;
|
|
51
|
-
|
|
52
|
-
console.log(`${where}: « ${hit.word} » → « ${hit.use} » …${hit.context}…`);
|
|
51
|
+
console.log(`${file}:${i + 1}: « ${hit.word} » → « ${hit.use} » …${hit.context}…`);
|
|
53
52
|
}
|
|
54
|
-
}
|
|
53
|
+
});
|
|
55
54
|
}
|
|
56
|
-
console.log(`${count} code name(s)
|
|
55
|
+
console.log(`${count} retired code name(s) in ${read} file(s)${report ? " (report only)" : ""}.`);
|
|
57
56
|
process.exit(count > 0 && !report ? 1 : 0);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://krizaka-assets.b-cdn.net/org/v1/app.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"app": "
|
|
4
|
+
"app": "folioviv",
|
|
5
5
|
"apiBaseUrl": {
|
|
6
|
-
"dev": "https://dev.
|
|
6
|
+
"dev": "https://dev.folioviv.com",
|
|
7
7
|
"production": null
|
|
8
8
|
},
|
|
9
9
|
"features": {},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://krizaka-assets.b-cdn.net/org/v1/app.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"app": "
|
|
4
|
+
"app": "sovkora",
|
|
5
5
|
"apiBaseUrl": {
|
|
6
|
-
"dev": "https://dev.
|
|
6
|
+
"dev": "https://dev.sovkora.com",
|
|
7
7
|
"production": null
|
|
8
8
|
},
|
|
9
9
|
"features": {},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://krizaka-assets.b-cdn.net/org/v1/app.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"app": "
|
|
4
|
+
"app": "verikora",
|
|
5
5
|
"apiBaseUrl": {
|
|
6
|
-
"dev": "https://dev.
|
|
6
|
+
"dev": "https://dev.verikora.com",
|
|
7
7
|
"production": null
|
|
8
8
|
},
|
|
9
9
|
"features": {},
|
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ type FamilyGroup = "krizaka" | "products" | "open-source" | "github";
|
|
|
24
24
|
type FamilyStatus = "released" | "development";
|
|
25
25
|
/**
|
|
26
26
|
* One name of the family, the only place it is written. The naming rule (founder, 2026-10-30): the company is
|
|
27
|
-
* « Krizaka »; a product goes by its own name («
|
|
27
|
+
* « Krizaka »; a product goes by its own name (« Verikora », never « Krizaka Verikora »); a library or a tool is always
|
|
28
28
|
* « Krizaka <X> » (« Krizaka UI », never « UI » alone outside a group headed « Open source »).
|
|
29
29
|
*/
|
|
30
30
|
interface FamilyEntry {
|
|
@@ -174,8 +174,9 @@ declare const APP_SCHEMA_URL = "https://krizaka-assets.b-cdn.net/org/v1/app.sche
|
|
|
174
174
|
declare const apps: Record<string, AppConfig>;
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
|
-
* The
|
|
178
|
-
* commercial name, « Verikora by Krizaka ». Every app, site and template reads
|
|
177
|
+
* The brands of Krizaka (krizaka-internal#2033, #2035; renamed 2026-11-06, krizaka-internal#2659): one id per brand, and the
|
|
178
|
+
* id is the commercial name (`verikora`), the customer reads « Verikora by Krizaka ». Every app, site and template reads
|
|
179
|
+
* them from here — never a literal.
|
|
179
180
|
*
|
|
180
181
|
* These are NOT in `org.json`: the org JSON is service discovery only (the addresses and versions clients resolve). Names,
|
|
181
182
|
* status, stores and the footer are admin configuration of each app (`@krizaka/settings`, audit trail); this module is the
|
|
@@ -184,8 +185,8 @@ declare const apps: Record<string, AppConfig>;
|
|
|
184
185
|
/** `product`: sold on its own. `service`: a part the products carry (Kridoc, the managed storage). */
|
|
185
186
|
type BrandKind = "product" | "service";
|
|
186
187
|
interface OrgBrand {
|
|
187
|
-
/** The
|
|
188
|
-
|
|
188
|
+
/** The id of the brand: its commercial name in lower case (`verikora`) — repositories, packages, hosts, CLI. */
|
|
189
|
+
id: string;
|
|
189
190
|
/** The name the customer reads (`Verikora`). One capital; capitals only in the wordmark. */
|
|
190
191
|
commercialName: string;
|
|
191
192
|
kind: BrandKind;
|
|
@@ -198,50 +199,56 @@ interface OrgBrand {
|
|
|
198
199
|
shop: string | null;
|
|
199
200
|
dev: string | null;
|
|
200
201
|
};
|
|
201
|
-
/** The one dated « formerly » line of the transition; `null` when the code name was never public. */
|
|
202
|
-
formerly: Localized | null;
|
|
203
202
|
}
|
|
204
|
-
/** The
|
|
203
|
+
/** The brands, one per product or service. */
|
|
205
204
|
declare const brands: readonly OrgBrand[];
|
|
206
|
-
/**
|
|
207
|
-
|
|
205
|
+
/**
|
|
206
|
+
* The historic table, and the only place the retired code names are written (founder, 2026-11-06, krizaka-internal#2659):
|
|
207
|
+
* old code name → brand id. History (commits, closed issues, CHANGELOG, released coordinates) keeps the old names; nothing
|
|
208
|
+
* else does — there is no alias, `brandOf("yomizaka")` throws and names the new id.
|
|
209
|
+
*/
|
|
210
|
+
declare const CODE_NAMES: Readonly<Record<string, string>>;
|
|
211
|
+
/** The brand of an id (`brandOf("verikora").commercialName` → « Verikora »). A retired code name is refused, never mapped. */
|
|
212
|
+
declare const brandOf: (id: string) => OrgBrand;
|
|
208
213
|
/** The longest name an administrator may set (a bar, a store listing and an email subject must hold it). */
|
|
209
214
|
declare const DISPLAY_NAME_MAX = 30;
|
|
210
215
|
/**
|
|
211
216
|
* The name an app shows: the administrator's choice (`brand.displayName` in its settings) when one is set, else the
|
|
212
|
-
* commercial name. Never
|
|
217
|
+
* commercial name. Never a retired code name: a setting that holds one falls back to the commercial name.
|
|
213
218
|
*/
|
|
214
|
-
declare const displayName: (
|
|
219
|
+
declare const displayName: (id: string, chosen?: string | null) => string;
|
|
215
220
|
/** The lockup in words: « Verikora by Krizaka » / « Verikora par Krizaka ». `fr` reads French, anything else English. */
|
|
216
|
-
declare const lockup: (
|
|
217
|
-
/**
|
|
218
|
-
declare const CODE_NAMES: readonly string[];
|
|
219
|
-
/** The code name → commercial name map the guard prints in its hints. */
|
|
221
|
+
declare const lockup: (id: string, locale: string, chosen?: string | null) => string;
|
|
222
|
+
/** Retired code name → commercial name (`yomizaka` → « Verikora »): what the guard prints in its hints. */
|
|
220
223
|
declare const codeNameMap: () => Record<string, string>;
|
|
221
224
|
interface CodeNameHit {
|
|
222
225
|
/** The word found, as written. */
|
|
223
226
|
word: string;
|
|
224
|
-
/** What to write instead. */
|
|
227
|
+
/** What to write instead, in the same case (`ORAZAKA` → `SOVKORA`, `Yomizaka` → `Verikora`, `akinaza` → `folioviv`). */
|
|
225
228
|
use: string;
|
|
226
229
|
/** Up to 40 characters around it. */
|
|
227
230
|
context: string;
|
|
228
231
|
}
|
|
229
|
-
/**
|
|
232
|
+
/**
|
|
233
|
+
* The retired code names a text holds (founder, 2026-11-06: none, anywhere): every occurrence in any case, in prose, code,
|
|
234
|
+
* hosts, URLs, package coordinates and code spans alike — there is no allowed span. Only the historic table above and the
|
|
235
|
+
* history (CHANGELOG files, skipped by the `krizaka-code-names` bin) keep them.
|
|
236
|
+
*/
|
|
230
237
|
declare const findCodeNames: (text: string) => CodeNameHit[];
|
|
231
238
|
/**
|
|
232
239
|
* The text a visitor reads in a built HTML page: the body text, the title, the description and social metadata, and the
|
|
233
240
|
* `alt`, `title` and `aria-label` attributes. Scripts, styles, `<pre>` and `<code>` (developer pages' commands) and
|
|
234
|
-
* comments are left out, and so are class names and links (a `brand-
|
|
241
|
+
* comments are left out, and so are class names and links (a `brand-verikora` class or a GitHub href is not shown).
|
|
235
242
|
*/
|
|
236
243
|
declare const visibleText: (html: string) => string;
|
|
237
244
|
/**
|
|
238
|
-
* The values of a message catalogue (EN/FR JSON), keyed by their path.
|
|
239
|
-
* (`site.
|
|
245
|
+
* The values of a message catalogue (EN/FR JSON), keyed by their path. Keys are structure
|
|
246
|
+
* (`site.verikora.title`); only the values are read by a customer.
|
|
240
247
|
*/
|
|
241
248
|
declare const catalogueValues: (catalogue: unknown, path?: string) => [string, string][];
|
|
242
249
|
|
|
243
250
|
/** The products that have a demo cast. */
|
|
244
|
-
type CastProduct = "
|
|
251
|
+
type CastProduct = "sovkora" | "verikora" | "folioviv";
|
|
245
252
|
/** What a persona does in the app: a member, a shop owner or a customer of one, an administrator. */
|
|
246
253
|
type CastRole = "member" | "admin" | "owner" | "client";
|
|
247
254
|
/** One fictitious person of the demo cast. No e-mail domain and no password: those come from the environment, through the secrets map. */
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@krizaka/org",
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "1.0.0",
|
|
5
5
|
description: "The public facts about Krizaka, in one validated JSON that every footer, site and app reads: legal name, NEQ, \xAB Fait \xE0 Montr\xE9al \xBB in French and English, brand marks, default avatars and banners, the live products and sites, the public contact, the footer line and the mobile apps' public runtime config. Typed data, JSON Schema, and the files published on the CDN.",
|
|
6
6
|
keywords: [
|
|
7
7
|
"krizaka",
|
|
@@ -365,11 +365,11 @@ var gh = (repo) => `${GITHUB}/${repo}`;
|
|
|
365
365
|
var FAMILY_ROWS = [
|
|
366
366
|
["krizaka", "Krizaka", "Krizaka", "krizaka", "released", "https://www.krizaka.com", gh("krizaka-com")],
|
|
367
367
|
["blog", "Blog", "Blog", "krizaka", "released", "https://blog.krizaka.com", gh("krizaka-blog")],
|
|
368
|
-
["
|
|
369
|
-
["
|
|
370
|
-
["
|
|
368
|
+
["sovkora", "Sovkora", "Sovkora", "products", "development", "https://www.sovkora.com", gh("sovkora")],
|
|
369
|
+
["verikora", "Verikora", "Verikora", "products", "development", "https://www.verikora.com", gh("verikora")],
|
|
370
|
+
["folioviv", "Folioviv", "Folioviv", "products", "development", "https://www.folioviv.com", gh("folioviv")],
|
|
371
371
|
["ui", "Krizaka UI", "UI", "open-source", "development", "https://ui.krizaka.com", gh("krizaka-ui")],
|
|
372
|
-
["java", "Krizaka Java", "Java", "open-source", "development", "https://java.krizaka.com", gh("krizaka-
|
|
372
|
+
["java", "Krizaka Java", "Java", "open-source", "development", "https://java.krizaka.com", gh("krizaka-java")],
|
|
373
373
|
["ts", "Krizaka TypeScript", "TypeScript", "open-source", "development", "https://ts.krizaka.com", gh("krizaka-ts")],
|
|
374
374
|
["lab", "Krizaka Lab", "Lab", "open-source", "development", "https://lab.krizaka.com", gh("krizaka-lab")],
|
|
375
375
|
["github", "GitHub", "GitHub", "github", "released", GITHUB, null]
|
|
@@ -415,25 +415,25 @@ var org = {
|
|
|
415
415
|
defaults,
|
|
416
416
|
products: [
|
|
417
417
|
{
|
|
418
|
-
id: "
|
|
419
|
-
name: "
|
|
418
|
+
id: "sovkora",
|
|
419
|
+
name: "Sovkora",
|
|
420
420
|
status: "development",
|
|
421
|
-
url: "https://www.
|
|
422
|
-
repo: "https://github.com/krizaka/
|
|
421
|
+
url: "https://www.sovkora.com",
|
|
422
|
+
repo: "https://github.com/krizaka/sovkora"
|
|
423
423
|
},
|
|
424
424
|
{
|
|
425
|
-
id: "
|
|
426
|
-
name: "
|
|
425
|
+
id: "verikora",
|
|
426
|
+
name: "Verikora",
|
|
427
427
|
status: "development",
|
|
428
|
-
url: "https://www.
|
|
429
|
-
repo: "https://github.com/krizaka/
|
|
428
|
+
url: "https://www.verikora.com",
|
|
429
|
+
repo: "https://github.com/krizaka/verikora"
|
|
430
430
|
},
|
|
431
431
|
{
|
|
432
|
-
id: "
|
|
433
|
-
name: "
|
|
432
|
+
id: "folioviv",
|
|
433
|
+
name: "Folioviv",
|
|
434
434
|
status: "development",
|
|
435
|
-
url: "https://www.
|
|
436
|
-
repo: "https://github.com/krizaka/
|
|
435
|
+
url: "https://www.folioviv.com",
|
|
436
|
+
repo: "https://github.com/krizaka/folioviv"
|
|
437
437
|
}
|
|
438
438
|
],
|
|
439
439
|
sites: [
|
|
@@ -483,124 +483,83 @@ var app = (id, devUrl) => ({
|
|
|
483
483
|
updatedAt: UPDATED
|
|
484
484
|
});
|
|
485
485
|
var apps = {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
486
|
+
sovkora: app("sovkora", "https://dev.sovkora.com"),
|
|
487
|
+
verikora: app("verikora", "https://dev.verikora.com"),
|
|
488
|
+
folioviv: app("folioviv", "https://dev.folioviv.com")
|
|
489
489
|
};
|
|
490
490
|
|
|
491
491
|
// src/brands.ts
|
|
492
492
|
var ENDORSEMENT = { en: "by Krizaka", fr: "par Krizaka" };
|
|
493
|
-
var brand = (
|
|
494
|
-
|
|
493
|
+
var brand = (id, commercialName, kind, domains) => ({
|
|
494
|
+
id,
|
|
495
495
|
commercialName,
|
|
496
496
|
kind,
|
|
497
497
|
endorsement: ENDORSEMENT,
|
|
498
|
-
domains
|
|
499
|
-
formerly: formerly ? { en: `${formerly} is now ${commercialName}`, fr: `${formerly} s\u2019appelle d\xE9sormais ${commercialName}` } : null
|
|
498
|
+
domains
|
|
500
499
|
});
|
|
501
500
|
var brands = [
|
|
502
|
-
brand(
|
|
503
|
-
"
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
"
|
|
511
|
-
"
|
|
512
|
-
"
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
)
|
|
521
|
-
brand(
|
|
522
|
-
"orazaka",
|
|
523
|
-
"Sovkora",
|
|
524
|
-
"product",
|
|
525
|
-
{ site: "https://www.sovkora.com", app: null, shop: null, dev: "https://dev.sovkora.com" },
|
|
526
|
-
"Orazaka"
|
|
527
|
-
),
|
|
528
|
-
// Kachizaka is the code name of the managed storage (Krizaka ECM, krizaka-internal#1916); it was never public.
|
|
529
|
-
brand("kachizaka", "Kridoc", "service", { site: "https://www.kridoc.com", app: null, shop: null, dev: null }, null)
|
|
501
|
+
brand("verikora", "Verikora", "product", {
|
|
502
|
+
site: "https://www.verikora.com",
|
|
503
|
+
app: null,
|
|
504
|
+
shop: null,
|
|
505
|
+
dev: "https://dev.verikora.com"
|
|
506
|
+
}),
|
|
507
|
+
brand("folioviv", "Folioviv", "product", {
|
|
508
|
+
site: "https://www.folioviv.com",
|
|
509
|
+
app: "https://folioviv.app",
|
|
510
|
+
shop: "https://folioviv.shop",
|
|
511
|
+
dev: "https://dev.folioviv.com"
|
|
512
|
+
}),
|
|
513
|
+
brand("sovkora", "Sovkora", "product", {
|
|
514
|
+
site: "https://www.sovkora.com",
|
|
515
|
+
app: null,
|
|
516
|
+
shop: null,
|
|
517
|
+
dev: "https://dev.sovkora.com"
|
|
518
|
+
}),
|
|
519
|
+
// Kridoc is the managed storage (Krizaka ECM, krizaka-internal#1916).
|
|
520
|
+
brand("kridoc", "Kridoc", "service", { site: "https://www.kridoc.com", app: null, shop: null, dev: null })
|
|
530
521
|
];
|
|
531
|
-
var
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
522
|
+
var CODE_NAMES = Object.freeze({
|
|
523
|
+
yomizaka: "verikora",
|
|
524
|
+
akinaza: "folioviv",
|
|
525
|
+
orazaka: "sovkora",
|
|
526
|
+
kachizaka: "kridoc"
|
|
527
|
+
});
|
|
528
|
+
var brandOf = (id) => {
|
|
529
|
+
const found = brands.find((b) => b.id === id);
|
|
530
|
+
if (found) return found;
|
|
531
|
+
const renamed = CODE_NAMES[id.toLowerCase()];
|
|
532
|
+
if (renamed) throw new Error(`"${id}" is a retired code name (krizaka-internal#2659): use brandOf("${renamed}").`);
|
|
533
|
+
throw new Error(`Unknown Krizaka brand "${id}".`);
|
|
535
534
|
};
|
|
536
535
|
var DISPLAY_NAME_MAX = 30;
|
|
537
|
-
var displayName = (
|
|
536
|
+
var displayName = (id, chosen) => {
|
|
538
537
|
const own = chosen?.trim() ?? "";
|
|
539
|
-
if (own.length === 0 || own.length > DISPLAY_NAME_MAX ||
|
|
540
|
-
return brandOf(
|
|
538
|
+
if (own.length === 0 || own.length > DISPLAY_NAME_MAX || findCodeNames(own).length > 0)
|
|
539
|
+
return brandOf(id).commercialName;
|
|
541
540
|
return own;
|
|
542
541
|
};
|
|
543
|
-
var lockup = (
|
|
544
|
-
const { endorsement } = brandOf(
|
|
545
|
-
return `${displayName(
|
|
542
|
+
var lockup = (id, locale, chosen) => {
|
|
543
|
+
const { endorsement } = brandOf(id);
|
|
544
|
+
return `${displayName(id, chosen)} ${locale === "fr" ? endorsement.fr : endorsement.en}`;
|
|
546
545
|
};
|
|
547
|
-
var
|
|
546
|
+
var codeNameMap = () => Object.fromEntries(Object.entries(CODE_NAMES).map(([old, id]) => [old, brandOf(id).commercialName]));
|
|
548
547
|
var FORMER_WORDINGS = [[/\bkrizaka\s+ecm\b/gi, "Kridoc"]];
|
|
549
|
-
var
|
|
550
|
-
var
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
let start = 0;
|
|
556
|
-
let end = raw.length;
|
|
557
|
-
while (start < end && LEADING.has(raw[start] ?? "")) start++;
|
|
558
|
-
while (end > start && TRAILING.has(raw[end - 1] ?? "")) end--;
|
|
559
|
-
return raw.slice(start, end);
|
|
560
|
-
};
|
|
561
|
-
var allowedToken = (raw) => {
|
|
562
|
-
const token = trimPunctuation(raw);
|
|
563
|
-
const lower = token.toLowerCase();
|
|
564
|
-
return token.includes("://") && URL.canParse(token) || lower.startsWith("@krizaka/") || lower.startsWith("com.krizaka") || lower.startsWith("krizaka/") || HOST_ENDINGS.some((end) => lower.endsWith(end) && lower.includes("."));
|
|
565
|
-
};
|
|
566
|
-
var CODE_SPAN = /`[^`\n]*`/g;
|
|
567
|
-
var blankLinkTargets = (text) => {
|
|
568
|
-
let out = "";
|
|
569
|
-
let at = 0;
|
|
570
|
-
for (; ; ) {
|
|
571
|
-
const open = text.indexOf("](", at);
|
|
572
|
-
if (open < 0) return out + text.slice(at);
|
|
573
|
-
const start = open + 2;
|
|
574
|
-
let end = start;
|
|
575
|
-
while (end < text.length && text[end] !== ")" && text[end] !== "\n") end++;
|
|
576
|
-
if (text[end] !== ")") {
|
|
577
|
-
out += text.slice(at, start);
|
|
578
|
-
at = start;
|
|
579
|
-
continue;
|
|
580
|
-
}
|
|
581
|
-
out += text.slice(at, start) + " ".repeat(end - start);
|
|
582
|
-
at = end;
|
|
583
|
-
}
|
|
584
|
-
};
|
|
585
|
-
var blankAllowed = (text) => {
|
|
586
|
-
let out = text;
|
|
587
|
-
for (const brand2 of brands) {
|
|
588
|
-
for (const line of brand2.formerly ? [brand2.formerly.en, brand2.formerly.fr] : [])
|
|
589
|
-
out = out.split(line).join(" ".repeat(line.length));
|
|
590
|
-
}
|
|
591
|
-
out = blankLinkTargets(out).replace(CODE_SPAN, (m) => " ".repeat(m.length));
|
|
592
|
-
return out.replace(/\S+/g, (m) => allowedToken(m) ? " ".repeat(m.length) : m);
|
|
548
|
+
var codeNamePattern = () => new RegExp(`(${Object.keys(CODE_NAMES).join("|")})`, "gi");
|
|
549
|
+
var replacementOf = (word) => {
|
|
550
|
+
const id = CODE_NAMES[word.toLowerCase()] ?? "";
|
|
551
|
+
if (word === word.toUpperCase()) return id.toUpperCase();
|
|
552
|
+
if (word.startsWith(word.charAt(0).toUpperCase())) return brandOf(id).commercialName;
|
|
553
|
+
return id;
|
|
593
554
|
};
|
|
594
555
|
var findCodeNames = (text) => {
|
|
595
|
-
const scanned = blankAllowed(text);
|
|
596
|
-
const map = codeNameMap();
|
|
597
556
|
const hits = [];
|
|
598
557
|
const around = (i, n) => text.slice(Math.max(0, i - 20), i + n + 20).replace(/\s+/g, " ").trim();
|
|
599
|
-
for (const m of
|
|
600
|
-
hits.push({ word: m[0], use:
|
|
558
|
+
for (const m of text.matchAll(codeNamePattern())) {
|
|
559
|
+
hits.push({ word: m[0], use: replacementOf(m[0]), context: around(m.index, m[0].length) });
|
|
601
560
|
}
|
|
602
561
|
for (const [re, use] of FORMER_WORDINGS) {
|
|
603
|
-
for (const m of
|
|
562
|
+
for (const m of text.matchAll(re)) hits.push({ word: m[0], use, context: around(m.index, m[0].length) });
|
|
604
563
|
}
|
|
605
564
|
return hits;
|
|
606
565
|
};
|
|
@@ -642,19 +601,6 @@ var stripTags = (html) => {
|
|
|
642
601
|
}
|
|
643
602
|
return out + html.slice(at);
|
|
644
603
|
};
|
|
645
|
-
var stripCodeNameLines = (html) => {
|
|
646
|
-
let out = "";
|
|
647
|
-
let at = 0;
|
|
648
|
-
for (let mark3 = html.indexOf("data-code-name"); mark3 >= 0; mark3 = html.indexOf("data-code-name", at)) {
|
|
649
|
-
const open = html.lastIndexOf("<", mark3);
|
|
650
|
-
const closing = html.indexOf("</", mark3);
|
|
651
|
-
const end = closing < 0 ? -1 : html.indexOf(">", closing);
|
|
652
|
-
if (open < at || end < 0) break;
|
|
653
|
-
out += `${html.slice(at, open)} `;
|
|
654
|
-
at = end + 1;
|
|
655
|
-
}
|
|
656
|
-
return out + html.slice(at);
|
|
657
|
-
};
|
|
658
604
|
var stripElements = (html) => {
|
|
659
605
|
const lower = html.toLowerCase();
|
|
660
606
|
let out = "";
|
|
@@ -680,7 +626,7 @@ var visibleText = (html) => {
|
|
|
680
626
|
}
|
|
681
627
|
}
|
|
682
628
|
for (const m of html.matchAll(/\b(?:alt|title|aria-label)\s*=\s*"([^"]*)"/gi)) attrs.push(m[1] ?? "");
|
|
683
|
-
const body = stripTags(stripElements(
|
|
629
|
+
const body = stripTags(stripElements(stripBlocks(html, "<!--", "-->"))).replaceAll(" ", " ").replaceAll("&", "&");
|
|
684
630
|
return [body, ...attrs].join("\n");
|
|
685
631
|
};
|
|
686
632
|
var catalogueValues = (catalogue, path = "") => {
|
|
@@ -698,7 +644,7 @@ var CAST = [
|
|
|
698
644
|
// The same three people as the deployed QA accounts (Eric, Mira, Camille) in each product, so a laptop and the dev deployment hold the same names.
|
|
699
645
|
{
|
|
700
646
|
id: "eric",
|
|
701
|
-
product: "
|
|
647
|
+
product: "verikora",
|
|
702
648
|
firstName: "\xC9ric",
|
|
703
649
|
displayName: "\xC9ric Tremblay",
|
|
704
650
|
role: "member",
|
|
@@ -708,7 +654,7 @@ var CAST = [
|
|
|
708
654
|
},
|
|
709
655
|
{
|
|
710
656
|
id: "mira",
|
|
711
|
-
product: "
|
|
657
|
+
product: "verikora",
|
|
712
658
|
firstName: "Mira",
|
|
713
659
|
displayName: "Mira Haddad",
|
|
714
660
|
role: "admin",
|
|
@@ -718,7 +664,7 @@ var CAST = [
|
|
|
718
664
|
},
|
|
719
665
|
{
|
|
720
666
|
id: "camille",
|
|
721
|
-
product: "
|
|
667
|
+
product: "verikora",
|
|
722
668
|
firstName: "Camille",
|
|
723
669
|
displayName: "Camille Tremblay",
|
|
724
670
|
role: "member",
|
|
@@ -726,11 +672,11 @@ var CAST = [
|
|
|
726
672
|
avatar: "visual-artist",
|
|
727
673
|
workspace: "rosemont-villeray"
|
|
728
674
|
},
|
|
729
|
-
//
|
|
730
|
-
// (
|
|
675
|
+
// Sovkora: the accounts already deployed on dev. Éric is the user (SOVKORA_USER_*, APP_QA_SOVKORA_PERSONA_*), Mira the administrator
|
|
676
|
+
// (SOVKORA_ADMIN_*, APP_QA_SOVKORA_MIRA_*), Krizaka the company as an SME customer (APP_QA_SOVKORA_KRIZAKA_*). The greeting reads the name: never « qa_user ».
|
|
731
677
|
{
|
|
732
678
|
id: "eric",
|
|
733
|
-
product: "
|
|
679
|
+
product: "sovkora",
|
|
734
680
|
firstName: "\xC9ric",
|
|
735
681
|
displayName: "\xC9ric Tremblay",
|
|
736
682
|
role: "member",
|
|
@@ -740,7 +686,7 @@ var CAST = [
|
|
|
740
686
|
},
|
|
741
687
|
{
|
|
742
688
|
id: "mira",
|
|
743
|
-
product: "
|
|
689
|
+
product: "sovkora",
|
|
744
690
|
firstName: "Mira",
|
|
745
691
|
displayName: "Mira Haddad",
|
|
746
692
|
role: "admin",
|
|
@@ -750,7 +696,7 @@ var CAST = [
|
|
|
750
696
|
},
|
|
751
697
|
{
|
|
752
698
|
id: "krizaka",
|
|
753
|
-
product: "
|
|
699
|
+
product: "sovkora",
|
|
754
700
|
firstName: "Krizaka",
|
|
755
701
|
displayName: "Krizaka",
|
|
756
702
|
role: "member",
|
|
@@ -758,10 +704,10 @@ var CAST = [
|
|
|
758
704
|
avatar: "tech-architect",
|
|
759
705
|
workspace: "demo"
|
|
760
706
|
},
|
|
761
|
-
//
|
|
707
|
+
// Folioviv: Éric owns the Krizaka studio, Léa is the Saint-Henri walker, Camille is her first client, Mira administers.
|
|
762
708
|
{
|
|
763
709
|
id: "eric",
|
|
764
|
-
product: "
|
|
710
|
+
product: "folioviv",
|
|
765
711
|
firstName: "\xC9ric",
|
|
766
712
|
displayName: "\xC9ric Tremblay",
|
|
767
713
|
role: "owner",
|
|
@@ -772,7 +718,7 @@ var CAST = [
|
|
|
772
718
|
},
|
|
773
719
|
{
|
|
774
720
|
id: "mira",
|
|
775
|
-
product: "
|
|
721
|
+
product: "folioviv",
|
|
776
722
|
firstName: "Mira",
|
|
777
723
|
displayName: "Mira Haddad",
|
|
778
724
|
role: "admin",
|
|
@@ -782,7 +728,7 @@ var CAST = [
|
|
|
782
728
|
},
|
|
783
729
|
{
|
|
784
730
|
id: "lea",
|
|
785
|
-
product: "
|
|
731
|
+
product: "folioviv",
|
|
786
732
|
firstName: "L\xE9a",
|
|
787
733
|
displayName: "L\xE9a Beaulieu",
|
|
788
734
|
role: "owner",
|
|
@@ -793,7 +739,7 @@ var CAST = [
|
|
|
793
739
|
},
|
|
794
740
|
{
|
|
795
741
|
id: "camille",
|
|
796
|
-
product: "
|
|
742
|
+
product: "folioviv",
|
|
797
743
|
firstName: "Camille",
|
|
798
744
|
displayName: "Camille Tremblay",
|
|
799
745
|
role: "client",
|
|
@@ -803,7 +749,7 @@ var CAST = [
|
|
|
803
749
|
},
|
|
804
750
|
{
|
|
805
751
|
id: "jordan",
|
|
806
|
-
product: "
|
|
752
|
+
product: "folioviv",
|
|
807
753
|
firstName: "Jordan",
|
|
808
754
|
displayName: "Jordan Lee",
|
|
809
755
|
role: "client",
|
|
@@ -813,7 +759,7 @@ var CAST = [
|
|
|
813
759
|
},
|
|
814
760
|
{
|
|
815
761
|
id: "nadia",
|
|
816
|
-
product: "
|
|
762
|
+
product: "folioviv",
|
|
817
763
|
firstName: "Nadia",
|
|
818
764
|
displayName: "Nadia Benali",
|
|
819
765
|
role: "client",
|
|
@@ -823,7 +769,7 @@ var CAST = [
|
|
|
823
769
|
},
|
|
824
770
|
{
|
|
825
771
|
id: "etienne",
|
|
826
|
-
product: "
|
|
772
|
+
product: "folioviv",
|
|
827
773
|
firstName: "\xC9tienne",
|
|
828
774
|
displayName: "\xC9tienne Gagnon",
|
|
829
775
|
role: "client",
|
|
@@ -833,7 +779,7 @@ var CAST = [
|
|
|
833
779
|
},
|
|
834
780
|
{
|
|
835
781
|
id: "sofia",
|
|
836
|
-
product: "
|
|
782
|
+
product: "folioviv",
|
|
837
783
|
firstName: "Sofia",
|
|
838
784
|
displayName: "Sofia Rossi",
|
|
839
785
|
role: "client",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/defaults.ts","../src/org.ts","../src/apps.ts","../src/brands.ts","../src/cast.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@krizaka/org\",\n \"version\": \"0.7.2\",\n \"description\": \"The public facts about Krizaka, in one validated JSON that every footer, site and app reads: legal name, NEQ, « Fait à Montréal » in French and English, brand marks, default avatars and banners, the live products and sites, the public contact, the footer line and the mobile apps' public runtime config. Typed data, JSON Schema, and the files published on the CDN.\",\n \"keywords\": [\n \"krizaka\",\n \"organization\",\n \"footer\",\n \"brand\",\n \"json-schema\"\n ],\n \"homepage\": \"https://ts.krizaka.com/org\",\n \"bugs\": \"https://github.com/krizaka/krizaka-ts/issues\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/krizaka/krizaka-ts.git\",\n \"directory\": \"packages/org\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Krizaka (https://www.krizaka.com)\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./org.json\": \"./dist/org.json\",\n \"./org.schema.json\": \"./dist/org.schema.json\",\n \"./apps/*.json\": \"./dist/apps/*.json\",\n \"./package.json\": \"./package.json\"\n },\n \"bin\": {\n \"krizaka-code-names\": \"./bin/krizaka-code-names.mjs\"\n },\n \"files\": [\n \"dist\",\n \"bin\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"sideEffects\": false,\n \"scripts\": {\n \"build\": \"node -e \\\"require('node:fs').rmSync('dist',{recursive:true,force:true})\\\" && tsup && node scripts/emit.mjs\",\n \"lint\": \"eslint . --max-warnings 0 && tsc --noEmit\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --coverage --coverage.provider=v8 --coverage.reporter=lcov --coverage.reporter=text-summary \\\"--coverage.include=src/**/*.ts\\\"\",\n \"check\": \"pnpm run lint && pnpm run test && pnpm run build\",\n \"publish:cdn\": \"node scripts/publish.mjs\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"devDependencies\": {\n \"@krizaka/config\": \"workspace:^\",\n \"@types/node\": \"^22.10.0\",\n \"ajv\": \"^8.17.0\",\n \"eslint\": \"^9.39.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.1.11\"\n }\n}\n","import type { Localized, OrgDefaultItem, OrgDefaultKind, OrgDefaults } from \"./org.types\";\n\n/** The pull zone that serves the sets. Declared here, not imported from `org.ts`, so `org.ts` can build its section from this file. */\nconst BASE = \"https://krizaka-assets.b-cdn.net/defaults/v1\";\n\n/** The kinds of entity that have a default set, in the order the JSON lists them. */\nexport const DEFAULT_KINDS = [\n \"person\",\n \"folder\",\n \"organisation\",\n \"shop\",\n \"banner\",\n] as const satisfies readonly OrgDefaultKind[];\n\n/** The sizes (px) each kind is served in: squares for the pictures, widths for the banners (3:1). */\nconst SIZES: Record<OrgDefaultKind, readonly number[]> = {\n person: [256, 512, 1024],\n folder: [256, 512, 1024],\n organisation: [256, 512, 1024],\n shop: [256, 512, 1024],\n banner: [960, 1920],\n};\n\n/** Withdrawn pictures, `<kind>/<id>`: kept in the JSON and on the CDN, never picked. The neon flamingo carries the wordmark of a paused product. */\nexport const DISABLED_DEFAULTS: ReadonlySet<string> = new Set([\"banner/the-neon-flamingo\"]);\n\nconst item = (kind: OrgDefaultKind, id: string, alt: Localized, drawn: boolean): OrgDefaultItem => ({\n id,\n alt,\n ...(DISABLED_DEFAULTS.has(`${kind}/${id}`) ? { disabled: true as const } : {}),\n urls: {\n ...(drawn ? { svg: `${BASE}/${kind}/${id}.svg` } : {}),\n webp: Object.fromEntries(SIZES[kind].map((size) => [String(size), `${BASE}/${kind}/${id}-${size}.webp`])),\n },\n});\n\nconst tones = (kind: OrgDefaultKind, id: string, alt: (n: number) => Localized): OrgDefaultItem[] =>\n Array.from({ length: 6 }, (_, i) => item(kind, `${id}-${i + 1}`, alt(i + 1), true));\n\n/** The founder's illustrated people (`defaults/v1/person/<id>-<size>.webp`). Alt texts say what the picture shows, never who. */\nconst PEOPLE: [string, Localized][] = [\n [\n \"boom-bap\",\n {\n en: \"Illustration: a rapper in a denim jacket and beanie, microphone in hand, in a rainy Montréal alley at night\",\n fr: \"Illustration : un rappeur en veste de jean et tuque, micro à la main, dans une ruelle de Montréal sous la pluie, la nuit\",\n },\n ],\n [\n \"rasta-creative\",\n {\n en: \"A smiling man with long dreadlocks in a paint-stained denim jacket, in an artist's workshop\",\n fr: \"Un homme souriant aux longues dreadlocks, en veste de jean tachée de peinture, dans un atelier d'artiste\",\n },\n ],\n [\n \"mile-end-hipster\",\n {\n en: \"A smiling person with round glasses and an orange beanie at a leatherworking bench, in a brick workshop\",\n fr: \"Une personne souriante à lunettes rondes et tuque orange, à son établi de cuir, dans un atelier de briques\",\n },\n ],\n [\n \"tech-architect\",\n {\n en: \"A person in a dark hoodie typing at a keyboard, between screens of code and a server rack\",\n fr: \"Une personne en chandail à capuchon sombre qui tape au clavier, entre des écrans de code et une baie de serveurs\",\n },\n ],\n [\n \"electronic-dj\",\n {\n en: \"A DJ with headphones behind synthesizers and a mixing desk, in a club with violet lights\",\n fr: \"Un DJ casque aux oreilles derrière des synthétiseurs et une table de mixage, dans un club aux lumières violettes\",\n },\n ],\n [\n \"visual-artist\",\n {\n en: \"A smiling painter with violet hair and big glasses, palette in hand, in a studio full of canvases\",\n fr: \"Une peintre souriante aux cheveux violets et aux grosses lunettes, palette à la main, dans un atelier plein de toiles\",\n },\n ],\n [\n \"salon-tattoo-maker\",\n {\n en: \"A tattoo artist with tattooed arms working on a client in a warm shop with wooden shelves\",\n fr: \"Une tatoueuse aux bras tatoués au travail sur un client, dans un salon chaleureux aux étagères de bois\",\n },\n ],\n [\n \"wise-auditor\",\n {\n en: \"A grey-haired person with glasses at a desk of old books and a lamp, a pen over open notes\",\n fr: \"Une personne aux cheveux gris et à lunettes à un bureau de vieux livres et de lampe, un stylo sur des notes ouvertes\",\n },\n ],\n [\n \"digital-creator\",\n {\n en: \"A laughing streamer with a microphone in a purple-lit studio under a neon « Creator Zone » sign\",\n fr: \"Une diffuseuse qui rit devant un micro, dans un studio violet sous une enseigne néon « Creator Zone »\",\n },\n ],\n [\n \"studio-maker\",\n {\n en: \"A potter in a linen apron holding a clay bowl, in a bright ceramics studio with plants\",\n fr: \"Une potière en tablier de lin tenant un bol d'argile, dans un atelier de céramique lumineux et plein de plantes\",\n },\n ],\n [\n \"community-lead\",\n {\n en: \"A smiling person with curly hair and a grey coat at a wooden table, a community space behind them\",\n fr: \"Une personne souriante aux cheveux bouclés et au manteau gris, à une table de bois, devant un espace communautaire\",\n },\n ],\n [\n \"ai-builder\",\n {\n en: \"A thoughtful person with blue-tinted glasses at a desk, screens of a neural network and code behind\",\n fr: \"Une personne pensive aux lunettes teintées de bleu à son bureau, devant des écrans de réseau neuronal et de code\",\n },\n ],\n];\n\n/** The founder's banners, 3:1 (`defaults/v1/banner/<id>-<width>.webp`). */\nconst BANNERS: [string, Localized][] = [\n [\n \"montreal-winter-night\",\n {\n en: \"Illustration: a snowy night in downtown Montréal, lit shop fronts and walkers\",\n fr: \"Illustration : une nuit de neige au centre-ville de Montréal, devantures éclairées et passants\",\n },\n ],\n [\n \"industrial-heritage\",\n {\n en: \"Dark blue skyline of old brick buildings with lit orange windows under a full moon\",\n fr: \"Silhouette bleu nuit de vieux immeubles de briques aux fenêtres orangées, sous la pleine lune\",\n },\n ],\n [\n \"creator-loft-studio\",\n {\n en: \"A dark loft desk with a plant, a code window and a mixing board\",\n fr: \"Un bureau de loft sombre avec une plante, une fenêtre de code et une table de mixage\",\n },\n ],\n [\n \"abstract-digital-flow\",\n {\n en: \"Flowing teal, violet and orange lines linking glowing points on a dark background\",\n fr: \"Des lignes ondulantes turquoise, violettes et orange reliant des points lumineux sur fond sombre\",\n },\n ],\n [\n \"paperwork-and-ink\",\n {\n en: \"Two dark document cards with colored stamps on a night-blue grid\",\n fr: \"Deux cartes de documents sombres tamponnées de couleur sur une grille bleu nuit\",\n },\n ],\n [\n \"nightlife-music-visual\",\n {\n en: \"A large glowing vinyl record with a pink label beside a small level meter, in violet light\",\n fr: \"Un grand disque vinyle lumineux à l'étiquette rose près d'un petit indicateur de niveau, en lumière violette\",\n },\n ],\n [\n \"the-mascot-flock\",\n {\n en: \"The Krizaka mascots — an owl, a beaver and a flamingo — standing on a shelf in the dark\",\n fr: \"Les mascottes de Krizaka — un hibou, un castor et un flamant — debout sur une étagère dans le noir\",\n },\n ],\n [\n \"abstract-stripes\",\n {\n en: \"Diagonal teal, indigo, violet and orange stripes with a white star and « Montréal // 514 »\",\n fr: \"Des bandes diagonales turquoise, indigo, violettes et orange avec une étoile blanche et « Montréal // 514 »\",\n },\n ],\n [\n \"open-source-horizon\",\n {\n en: \"A dark terminal window on a grid, a faint horizon behind\",\n fr: \"Une fenêtre de terminal sombre sur une grille, un horizon pâle derrière\",\n },\n ],\n [\n \"cafe-maker-studio\",\n {\n en: \"A warm dark brown scene with a card reading « Fabriqué à Montréal »\",\n fr: \"Une scène brun foncé chaleureuse avec une carte « Fabriqué à Montréal »\",\n },\n ],\n [\n \"the-neon-flamingo\",\n {\n en: \"A pink neon flamingo outline on black, with a violet halo\",\n fr: \"Le contour d'un flamant rose en néon sur fond noir, avec un halo violet\",\n },\n ],\n [\n \"cooperative-network\",\n {\n en: \"Small linked glowing points over a dark hill at dusk\",\n fr: \"De petits points lumineux reliés au-dessus d'une colline sombre au crépuscule\",\n },\n ],\n];\n\nconst GLYPH_ALT = {\n person: (n: number): Localized => ({\n en: `Default profile picture: a silhouette, tone ${n}`,\n fr: `Photo de profil par défaut : une silhouette, teinte ${n}`,\n }),\n folder: (n: number): Localized => ({\n en: `Default folder picture: a folder, tone ${n}`,\n fr: `Image de dossier par défaut : un dossier, teinte ${n}`,\n }),\n organisation: (n: number): Localized => ({\n en: `Default organisation picture: a building, tone ${n}`,\n fr: `Image d'organisation par défaut : un immeuble, teinte ${n}`,\n }),\n shop: (n: number): Localized => ({\n en: `Default shop picture: a storefront, tone ${n}`,\n fr: `Image de boutique par défaut : une devanture, teinte ${n}`,\n }),\n};\n\n/** The `defaults` section of the org JSON: the central sets on Bunny (`defaults/v1/<kind>/<id>-<size>.<ext>`), written by krizaka-ui `tools/export-defaults.mjs`. */\nexport const defaults: OrgDefaults = {\n version: \"v1\",\n base: BASE,\n rule: {\n pick: \"fnv1a32-modulo\",\n description:\n \"defaultFor(kind, seed) = items[fnv1a32(String(seed)) mod items.length] of the kind's list, in the order of the JSON; the same seed always gives the same item, in every app.\",\n },\n kinds: {\n person: [\n ...tones(\"person\", \"silhouette\", GLYPH_ALT.person),\n ...PEOPLE.map(([id, alt]) => item(\"person\", id, alt, false)),\n ],\n folder: tones(\"folder\", \"folder\", GLYPH_ALT.folder),\n organisation: tones(\"organisation\", \"organisation\", GLYPH_ALT.organisation),\n shop: tones(\"shop\", \"shop\", GLYPH_ALT.shop),\n banner: BANNERS.map(([id, alt]) => item(\"banner\", id, alt, false)),\n },\n};\n\n// ---- reading -------------------------------------------------------------------------------------------------------\n\n/** 32-bit FNV-1a of a seed: stable across runs, devices and products (the same one `@krizaka/ui`'s default avatars use). */\nexport function seedHash(seed: string | number): number {\n let h = 0x811c9dc5;\n for (const ch of String(seed)) {\n h ^= ch.codePointAt(0) ?? 0;\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h;\n}\n\n/** The items of a kind that can be picked, in the order of the JSON (a withdrawn one is skipped). A source other than the bundled one is the JSON an app fetched. */\nexport function listDefaults(kind: OrgDefaultKind, source: OrgDefaults = defaults): readonly OrgDefaultItem[] {\n return (source.kinds[kind] ?? []).filter((entry) => entry.disabled !== true);\n}\n\n/** The item of a kind for a seed (an entity's id): deterministic, so a folder keeps its picture everywhere. `undefined` only when the kind's list is empty. */\nexport function defaultFor(\n kind: OrgDefaultKind,\n seed: string | number,\n source: OrgDefaults = defaults,\n): OrgDefaultItem | undefined {\n const items = listDefaults(kind, source);\n return items.length === 0 ? undefined : items[seedHash(seed) % items.length];\n}\n\n/** The URL of an item at the smallest size that is at least `size` px (or the largest there is); `svg` when the item has a vector and `format` says so. */\nexport function defaultUrl(entry: OrgDefaultItem, size: number, format: \"webp\" | \"svg\" = \"webp\"): string {\n if (format === \"svg\" && entry.urls.svg) return entry.urls.svg;\n const sizes = Object.keys(entry.urls.webp)\n .map(Number)\n .sort((a, b) => a - b);\n const chosen = sizes.find((s) => s >= size) ?? sizes[sizes.length - 1];\n return entry.urls.webp[String(chosen)] ?? \"\";\n}\n\n/** Reads the section from the published JSON (`ORG_URL`), for an app that does not bundle this package. */\nexport async function fetchDefaults(url: string, fetchImpl: typeof fetch = fetch): Promise<OrgDefaults> {\n const res = await fetchImpl(url, { headers: { Accept: \"application/json\" } });\n if (!res.ok) throw new Error(`${url} answered ${res.status}`);\n const json = (await res.json()) as { defaults?: OrgDefaults };\n if (!json.defaults) throw new Error(`${url} has no \\`defaults\\` section`);\n return json.defaults;\n}\n","import pkg from \"../package.json\" with { type: \"json\" };\nimport { defaults as centralDefaults } from \"./defaults\";\nimport type { Localized, Org, OrgAvatar, OrgMark } from \"./org.types\";\n\n/** The pull zone that serves the brand files and this JSON. */\nexport const CDN = \"https://krizaka-assets.b-cdn.net\";\nexport const ORG_URL = `${CDN}/org/v1/org.json`;\nexport const ORG_SCHEMA_URL = `${CDN}/org/v1/org.schema.json`;\n\nconst cdn = (path: string) => `${CDN}/${path}`;\n\nconst mark = (kind: \"logo\" | \"mark\", theme: \"dark\" | \"light\"): OrgMark => ({\n svg: cdn(`brand/krizaka/${kind}-${theme}.svg`),\n png64: cdn(`brand/krizaka/${kind}-${theme}-64.png`),\n png256: cdn(`brand/krizaka/${kind}-${theme}-256.png`),\n png512: cdn(`brand/krizaka/${kind}-${theme}-512.png`),\n png1024: cdn(`brand/krizaka/${kind}-${theme}-1024.png`),\n});\n\nconst TONES = [1, 2, 3, 4, 5, 6] as const;\n\nconst avatarAlt = (kind: \"person\" | \"plain\", n: number): Localized =>\n kind === \"person\"\n ? {\n fr: `Photo de profil par défaut : silhouette, teinte ${n}`,\n en: `Default profile picture: silhouette, tone ${n}`,\n }\n : {\n fr: `Photo de profil par défaut : disque uni, teinte ${n}`,\n en: `Default profile picture: plain disc, tone ${n}`,\n };\n\n/** The default profile pictures a product shows when a person has no photo (`people/defaults/v1`, krizaka-ui `tools/export-brand.mjs`). */\nconst defaults: OrgAvatar[] = ([\"person\", \"plain\"] as const).flatMap((kind) =>\n TONES.map((n) => ({\n id: `${kind}-${n}`,\n kind,\n svg: cdn(`people/defaults/v1/krizaka/${kind}-${n}.svg`),\n webp256: cdn(`people/defaults/v1/krizaka/${kind}-${n}-256.webp`),\n webp512: cdn(`people/defaults/v1/krizaka/${kind}-${n}-512.webp`),\n alt: avatarAlt(kind, n),\n })),\n);\n\n/** The public facts about Krizaka. Reviewed by pull request; changing a fact is one PR here and a release. */\ntype FamilyEntry = NonNullable<Org[\"family\"]>[number];\ntype FamilyRow = [\n FamilyEntry[\"id\"],\n string,\n string,\n FamilyEntry[\"group\"],\n FamilyEntry[\"status\"],\n string,\n string | null,\n];\n\nconst GITHUB = \"https://github.com/krizaka\";\nconst gh = (repo: string) => `${GITHUB}/${repo}`;\n\n/** The family list as data: one row per entry (id, name, short, group, status, url, repo). */\nconst FAMILY_ROWS: FamilyRow[] = [\n [\"krizaka\", \"Krizaka\", \"Krizaka\", \"krizaka\", \"released\", \"https://www.krizaka.com\", gh(\"krizaka-com\")],\n [\"blog\", \"Blog\", \"Blog\", \"krizaka\", \"released\", \"https://blog.krizaka.com\", gh(\"krizaka-blog\")],\n [\"orazaka\", \"Orazaka\", \"Orazaka\", \"products\", \"development\", \"https://www.orazaka.com\", gh(\"orazaka\")],\n [\"yomizaka\", \"Yomizaka\", \"Yomizaka\", \"products\", \"development\", \"https://www.yomizaka.com\", gh(\"yomizaka\")],\n [\"akinaza\", \"Akinaza\", \"Akinaza\", \"products\", \"development\", \"https://www.akinaza.com\", gh(\"akinaza\")],\n [\"ui\", \"Krizaka UI\", \"UI\", \"open-source\", \"development\", \"https://ui.krizaka.com\", gh(\"krizaka-ui\")],\n [\"java\", \"Krizaka Java\", \"Java\", \"open-source\", \"development\", \"https://java.krizaka.com\", gh(\"krizaka-build\")],\n [\"ts\", \"Krizaka TypeScript\", \"TypeScript\", \"open-source\", \"development\", \"https://ts.krizaka.com\", gh(\"krizaka-ts\")],\n [\"lab\", \"Krizaka Lab\", \"Lab\", \"open-source\", \"development\", \"https://lab.krizaka.com\", gh(\"krizaka-lab\")],\n [\"github\", \"GitHub\", \"GitHub\", \"github\", \"released\", GITHUB, null],\n];\n\nconst family: FamilyEntry[] = FAMILY_ROWS.map(([id, name, short, group, status, url, repo]) => ({\n id,\n name,\n short,\n group,\n status,\n url,\n repo,\n}));\n\nexport const org: Org = {\n $schema: ORG_SCHEMA_URL,\n schemaVersion: 2,\n version: pkg.version,\n updatedAt: \"2026-10-30\",\n company: {\n legalName: \"Technologies Krizaka Inc.\",\n tradeName: \"Krizaka\",\n neq: \"1182652231\",\n city: \"Montréal\",\n region: \"Québec\",\n country: \"CA\",\n license: \"Apache-2.0\",\n madeIn: { fr: \"Fait à Montréal\", en: \"Made in Montréal\" },\n },\n brand: {\n name: \"Krizaka\",\n logo: { dark: mark(\"logo\", \"dark\"), light: mark(\"logo\", \"light\") },\n mark: { dark: mark(\"mark\", \"dark\"), light: mark(\"mark\", \"light\") },\n favicon: cdn(\"brand/krizaka/favicon.svg\"),\n appleTouchIcon: cdn(\"brand/krizaka/apple-touch-icon.png\"),\n socialPreview: cdn(\"brand/krizaka/social-preview-1280x640.png\"),\n manifest: cdn(\"brand/manifest.json\"),\n },\n people: {\n defaults,\n // No banner is published on the CDN yet; the set joins here with its alts when it is.\n banners: [],\n },\n defaults: centralDefaults,\n products: [\n {\n id: \"orazaka\",\n name: \"Orazaka\",\n status: \"development\",\n url: \"https://www.orazaka.com\",\n repo: \"https://github.com/krizaka/orazaka\",\n },\n {\n id: \"yomizaka\",\n name: \"Yomizaka\",\n status: \"development\",\n url: \"https://www.yomizaka.com\",\n repo: \"https://github.com/krizaka/yomizaka\",\n },\n {\n id: \"akinaza\",\n name: \"Akinaza\",\n status: \"development\",\n url: \"https://www.akinaza.com\",\n repo: \"https://github.com/krizaka/akinaza\",\n },\n ],\n sites: [\n { id: \"www\", name: \"krizaka.com\", url: \"https://www.krizaka.com\" },\n { id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\" },\n { id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\" },\n { id: \"ts\", name: \"Krizaka TypeScript\", url: \"https://ts.krizaka.com\" },\n { id: \"motion\", name: \"Krizaka Lab\", url: \"https://lab.krizaka.com\" },\n { id: \"blog\", name: \"Blog\", url: \"https://blog.krizaka.com\" },\n ],\n family,\n contact: {\n page: { fr: \"https://www.krizaka.com/fr/contact\", en: \"https://www.krizaka.com/en/contact\" },\n email: null,\n },\n footer: {\n line: {\n fr: \"Une entreprise de Technologies Krizaka · Fait à Montréal\",\n en: \"A Technologies Krizaka company · Made in Montréal\",\n },\n legal: [\n {\n id: \"privacy\",\n label: { fr: \"Confidentialité\", en: \"Privacy\" },\n url: { fr: \"https://www.krizaka.com/fr/privacy\", en: \"https://www.krizaka.com/en/privacy\" },\n },\n {\n id: \"terms\",\n label: { fr: \"Conditions\", en: \"Terms\" },\n url: { fr: \"https://www.krizaka.com/fr/terms\", en: \"https://www.krizaka.com/en/terms\" },\n },\n ],\n },\n};\n","import { CDN } from \"./org\";\nimport type { AppConfig } from \"./org.types\";\n\nexport const APP_SCHEMA_URL = `${CDN}/org/v1/app.schema.json`;\nconst UPDATED = \"2026-10-26\";\n\nconst app = (id: string, devUrl: string): AppConfig => ({\n $schema: APP_SCHEMA_URL,\n schemaVersion: 1,\n app: id,\n // Public by nature: an address a client calls. No key, no token, no internal host.\n apiBaseUrl: { dev: devUrl, production: null },\n features: {},\n minAppVersion: \"0.0.0\",\n updatedAt: UPDATED,\n});\n\n/** The runtime config a mobile app may know, per live product. The app reads it at start, with a copy built into the binary as fallback. */\nexport const apps: Record<string, AppConfig> = {\n orazaka: app(\"orazaka\", \"https://dev.orazaka.com\"),\n yomizaka: app(\"yomizaka\", \"https://dev.yomizaka.com\"),\n akinaza: app(\"akinaza\", \"https://dev.akinaza.com\"),\n};\n","import type { Localized } from \"./org.types\";\n\n/**\n * The commercial names (krizaka-internal#2033, #2035, #2036): the code name stays internal, the customer reads the\n * commercial name, « Verikora by Krizaka ». Every app, site and template reads them from here — never a literal.\n *\n * These are NOT in `org.json`: the org JSON is service discovery only (the addresses and versions clients resolve). Names,\n * status, stores and the footer are admin configuration of each app (`@krizaka/settings`, audit trail); this module is the\n * seed and the validation vocabulary, not a published file.\n */\n\n/** `product`: sold on its own. `service`: a part the products carry (Kridoc, the managed storage). */\nexport type BrandKind = \"product\" | \"service\";\n\nexport interface OrgBrand {\n /** The internal name: the repository, the packages, the CLI (`yomizaka`). Never on a public page. */\n codeName: string;\n /** The name the customer reads (`Verikora`). One capital; capitals only in the wordmark. */\n commercialName: string;\n kind: BrandKind;\n /** The endorsement after the name: « by Krizaka » / « par Krizaka ». */\n endorsement: Localized;\n /** The hosts of the brand (https URLs); `null` where it has none. */\n domains: { site: string; app: string | null; shop: string | null; dev: string | null };\n /** The one dated « formerly » line of the transition; `null` when the code name was never public. */\n formerly: Localized | null;\n}\n\nconst ENDORSEMENT = { en: \"by Krizaka\", fr: \"par Krizaka\" };\n\nconst brand = (\n codeName: string,\n commercialName: string,\n kind: BrandKind,\n domains: OrgBrand[\"domains\"],\n formerly: string | null,\n): OrgBrand => ({\n codeName,\n commercialName,\n kind,\n endorsement: ENDORSEMENT,\n domains,\n formerly: formerly\n ? { en: `${formerly} is now ${commercialName}`, fr: `${formerly} s’appelle désormais ${commercialName}` }\n : null,\n});\n\n/** The seed: one commercial name per code name. Nothing flips to it until the readiness checklist (krizaka-internal#2092). */\nexport const brands: readonly OrgBrand[] = [\n brand(\n \"yomizaka\",\n \"Verikora\",\n \"product\",\n { site: \"https://www.verikora.com\", app: null, shop: null, dev: \"https://dev.verikora.com\" },\n \"Yomizaka\",\n ),\n brand(\n \"akinaza\",\n \"Folioviv\",\n \"product\",\n {\n site: \"https://www.folioviv.com\",\n app: \"https://folioviv.app\",\n shop: \"https://folioviv.shop\",\n dev: \"https://dev.folioviv.com\",\n },\n \"Akinaza\",\n ),\n brand(\n \"orazaka\",\n \"Sovkora\",\n \"product\",\n { site: \"https://www.sovkora.com\", app: null, shop: null, dev: \"https://dev.sovkora.com\" },\n \"Orazaka\",\n ),\n // Kachizaka is the code name of the managed storage (Krizaka ECM, krizaka-internal#1916); it was never public.\n brand(\"kachizaka\", \"Kridoc\", \"service\", { site: \"https://www.kridoc.com\", app: null, shop: null, dev: null }, null),\n];\n\n/** The brand of a code name (`brandOf(\"yomizaka\").commercialName` → « Verikora »). */\nexport const brandOf = (codeName: string): OrgBrand => {\n const found = brands.find((b) => b.codeName === codeName);\n if (!found) throw new Error(`Unknown Krizaka code name \"${codeName}\".`);\n return found;\n};\n\n/** The longest name an administrator may set (a bar, a store listing and an email subject must hold it). */\n// @fixed: the App Store's display name limit is 30 characters; the bar and the lockup are drawn for it\nexport const DISPLAY_NAME_MAX = 30;\n\n/**\n * The name an app shows: the administrator's choice (`brand.displayName` in its settings) when one is set, else the\n * commercial name. Never the code name: a setting equal to a code name falls back to the commercial name.\n */\nexport const displayName = (codeName: string, chosen?: string | null): string => {\n const own = chosen?.trim() ?? \"\";\n if (own.length === 0 || own.length > DISPLAY_NAME_MAX || codeNamePattern().test(own))\n return brandOf(codeName).commercialName;\n return own;\n};\n\n/** The lockup in words: « Verikora by Krizaka » / « Verikora par Krizaka ». `fr` reads French, anything else English. */\nexport const lockup = (codeName: string, locale: string, chosen?: string | null): string => {\n const { endorsement } = brandOf(codeName);\n return `${displayName(codeName, chosen)} ${locale === \"fr\" ? endorsement.fr : endorsement.en}`;\n};\n\n/** The words a public surface never shows: every code name, and « Krizaka ECM » (it is Kridoc). */\nexport const CODE_NAMES: readonly string[] = brands.map((b) => b.codeName);\nconst FORMER_WORDINGS: readonly [RegExp, string][] = [[/\\bkrizaka\\s+ecm\\b/gi, \"Kridoc\"]];\n\n/** The code name → commercial name map the guard prints in its hints. */\nexport const codeNameMap = (): Record<string, string> =>\n Object.fromEntries(brands.map((b) => [b.codeName, b.commercialName]));\n\nconst codeNamePattern = (flags = \"i\") => new RegExp(String.raw`\\b(${CODE_NAMES.join(\"|\")})\\b`, flags);\n\n/**\n * What is allowed to keep a code name, declared once (#2036): repository and GitHub URLs, npm and Maven coordinates,\n * the old hosts (`dev.yomizaka.com`, they redirect), code (backticks), and the one « formerly » line of each brand.\n */\nconst HOST_ENDINGS = [\".com\", \".app\", \".shop\", \".dev\"];\nconst LEADING = new Set([\"(\", \"<\", \"«\", '\"', \"'\"]);\nconst TRAILING = new Set([\".\", \",\", \";\", \":\", \"!\", \"?\", \")\", \"]\", \">\", \"»\", '\"', \"'\"]);\n/** The token without the punctuation around it (`(dev.yomizaka.com).` → `dev.yomizaka.com`), in one linear pass. */\nconst trimPunctuation = (raw: string): string => {\n let start = 0;\n let end = raw.length;\n while (start < end && LEADING.has(raw[start] ?? \"\")) start++;\n while (end > start && TRAILING.has(raw[end - 1] ?? \"\")) end--;\n return raw.slice(start, end);\n};\nconst allowedToken = (raw: string): boolean => {\n const token = trimPunctuation(raw);\n const lower = token.toLowerCase();\n return (\n (token.includes(\"://\") && URL.canParse(token)) ||\n lower.startsWith(\"@krizaka/\") ||\n lower.startsWith(\"com.krizaka\") ||\n lower.startsWith(\"krizaka/\") ||\n HOST_ENDINGS.some((end) => lower.endsWith(end) && lower.includes(\".\"))\n );\n};\nconst CODE_SPAN = /`[^`\\n]*`/g;\n/** The text with the target of every markdown link `[label](target)` blanked (lengths kept): the target is a URL, the label stays checked. Linear. */\nconst blankLinkTargets = (text: string): string => {\n let out = \"\";\n let at = 0;\n for (;;) {\n const open = text.indexOf(\"](\", at);\n if (open < 0) return out + text.slice(at);\n const start = open + 2;\n let end = start;\n while (end < text.length && text[end] !== \")\" && text[end] !== \"\\n\") end++;\n if (text[end] !== \")\") {\n out += text.slice(at, start);\n at = start;\n continue;\n }\n out += text.slice(at, start) + \" \".repeat(end - start);\n at = end;\n }\n};\n\nexport interface CodeNameHit {\n /** The word found, as written. */\n word: string;\n /** What to write instead. */\n use: string;\n /** Up to 40 characters around it. */\n context: string;\n}\n\n/** The text with every allowed span blanked (lengths kept, so contexts stay readable). */\nconst blankAllowed = (text: string): string => {\n let out = text;\n for (const brand of brands) {\n for (const line of brand.formerly ? [brand.formerly.en, brand.formerly.fr] : [])\n out = out.split(line).join(\" \".repeat(line.length));\n }\n out = blankLinkTargets(out).replace(CODE_SPAN, (m) => \" \".repeat(m.length));\n return out.replace(/\\S+/g, (m) => (allowedToken(m) ? \" \".repeat(m.length) : m));\n};\n\n/** The code names a piece of customer-facing text shows (case-insensitive, whole words), minus the allowed spans. */\nexport const findCodeNames = (text: string): CodeNameHit[] => {\n const scanned = blankAllowed(text);\n const map = codeNameMap();\n const hits: CodeNameHit[] = [];\n const around = (i: number, n: number) =>\n text\n .slice(Math.max(0, i - 20), i + n + 20)\n .replace(/\\s+/g, \" \")\n .trim();\n for (const m of scanned.matchAll(codeNamePattern(\"gi\"))) {\n hits.push({ word: m[0], use: map[m[0].toLowerCase()] ?? \"\", context: around(m.index ?? 0, m[0].length) });\n }\n for (const [re, use] of FORMER_WORDINGS) {\n for (const m of scanned.matchAll(re)) hits.push({ word: m[0], use, context: around(m.index ?? 0, m[0].length) });\n }\n return hits;\n};\n\n/** The text without the spans from `open` to `close` (an unclosed one runs to the end). Linear: no backtracking regex on page input. */\nconst stripBlocks = (text: string, open: string, close: string): string => {\n let out = \"\";\n let at = 0;\n for (;;) {\n const start = text.indexOf(open, at);\n if (start < 0) return out + text.slice(at);\n out += `${text.slice(at, start)} `;\n const end = text.indexOf(close, start + open.length);\n if (end < 0) return out;\n at = end + close.length;\n }\n};\n\nconst SKIPPED_ELEMENTS = [\"script\", \"style\", \"pre\", \"code\", \"svg\"];\n/** Where the element `name` next opens from `at` (`<code>` or `<code class…>`, never `<codex>`), or -1. */\nconst openingOf = (lower: string, name: string, at: number): number => {\n for (let i = lower.indexOf(`<${name}`, at); i >= 0; i = lower.indexOf(`<${name}`, i + 1)) {\n if (!/[a-z0-9-]/.test(lower[i + name.length + 1] ?? \" \")) return i;\n }\n return -1;\n};\n/** The first skipped element that opens from `at`: its index (-1 when none) and its name. */\nconst nextSkipped = (lower: string, at: number): [number, string] => {\n let found: [number, string] = [-1, \"\"];\n for (const name of SKIPPED_ELEMENTS) {\n const i = openingOf(lower, name, at);\n if (i >= 0 && (found[0] < 0 || i < found[0])) found = [i, name];\n }\n return found;\n};\n/** The text with every tag (`<…>`) replaced by a space, in one linear pass (no backtracking regex on page input). */\nconst stripTags = (html: string): string => {\n let out = \"\";\n let at = 0;\n for (let open = html.indexOf(\"<\"); open >= 0; open = html.indexOf(\"<\", at)) {\n const close = html.indexOf(\">\", open + 1);\n if (close < 0) break;\n out += `${html.slice(at, open)} `;\n at = close + 1;\n }\n return out + html.slice(at);\n};\n/**\n * The text without the development line of a lockup: an element marked `data-code-name` (« code name: yomizaka »), the one place\n * a dev deployment says its code name on purpose, under the commercial name (krizaka-internal#2368). It is a leaf (text only), so it\n * ends at the next closing tag. Linear: no backtracking regex on page input.\n */\nconst stripCodeNameLines = (html: string): string => {\n let out = \"\";\n let at = 0;\n for (let mark = html.indexOf(\"data-code-name\"); mark >= 0; mark = html.indexOf(\"data-code-name\", at)) {\n const open = html.lastIndexOf(\"<\", mark);\n const closing = html.indexOf(\"</\", mark);\n const end = closing < 0 ? -1 : html.indexOf(\">\", closing);\n if (open < at || end < 0) break;\n out += `${html.slice(at, open)} `;\n at = end + 1;\n }\n return out + html.slice(at);\n};\n/** The text without the elements a visitor does not read as prose (scripts, styles, code, svg), matched case-insensitively. */\nconst stripElements = (html: string): string => {\n const lower = html.toLowerCase();\n let out = \"\";\n let at = 0;\n while (at < html.length) {\n const [next, tag] = nextSkipped(lower, at);\n if (next < 0) return out + html.slice(at);\n out += `${html.slice(at, next)} `;\n const end = lower.indexOf(`</${tag}>`, next);\n if (end < 0) return out;\n at = end + tag.length + 3;\n }\n return out;\n};\n\n/**\n * The text a visitor reads in a built HTML page: the body text, the title, the description and social metadata, and the\n * `alt`, `title` and `aria-label` attributes. Scripts, styles, `<pre>` and `<code>` (developer pages' commands) and\n * comments are left out, and so are class names and links (a `brand-yomizaka` class or a GitHub href is not shown).\n */\nexport const visibleText = (html: string): string => {\n const attrs: string[] = [];\n for (const m of html.matchAll(/<meta\\b[^>]*>/gi)) {\n if (\n /\\b(?:name|property)\\s*=\\s*[\"'](?:description|og:[\\w:]+|twitter:[\\w:]+|application-name|apple-mobile-web-app-title)[\"']/i.test(\n m[0],\n )\n ) {\n const content = /\\bcontent\\s*=\\s*\"([^\"]*)\"|\\bcontent\\s*=\\s*'([^']*)'/i.exec(m[0]);\n if (content) attrs.push(content[1] ?? content[2] ?? \"\");\n }\n }\n for (const m of html.matchAll(/\\b(?:alt|title|aria-label)\\s*=\\s*\"([^\"]*)\"/gi)) attrs.push(m[1] ?? \"\");\n const body = stripTags(stripElements(stripCodeNameLines(stripBlocks(html, \"<!--\", \"-->\"))))\n .replaceAll(\" \", \" \")\n .replaceAll(\"&\", \"&\");\n return [body, ...attrs].join(\"\\n\");\n};\n\n/**\n * The values of a message catalogue (EN/FR JSON), keyed by their path. A key path may name a code name\n * (`site.yomizaka.title`): keys are structure; only the values are read by a customer.\n */\nexport const catalogueValues = (catalogue: unknown, path = \"\"): [string, string][] => {\n if (typeof catalogue === \"string\") return [[path, catalogue]];\n if (Array.isArray(catalogue)) return catalogue.flatMap((v, i) => catalogueValues(v, `${path}[${i}]`));\n if (catalogue && typeof catalogue === \"object\") {\n return Object.entries(catalogue).flatMap(([k, v]) => catalogueValues(v, path ? `${path}.${k}` : k));\n }\n return [];\n};\n","import { defaultUrl, listDefaults } from \"./defaults\";\nimport type { OrgDefaultItem } from \"./org.types\";\n\n/** The products that have a demo cast. */\nexport type CastProduct = \"orazaka\" | \"yomizaka\" | \"akinaza\";\n\n/** What a persona does in the app: a member, a shop owner or a customer of one, an administrator. */\nexport type CastRole = \"member\" | \"admin\" | \"owner\" | \"client\";\n\n/** One fictitious person of the demo cast. No e-mail domain and no password: those come from the environment, through the secrets map. */\nexport interface CastPersona {\n /** Stable key, unique in its product: `eric`, `camille`. Seeds, recordings and tests name the persona by it. */\n readonly id: string;\n readonly product: CastProduct;\n readonly firstName: string;\n /** The name every screen, demo and recording shows: never « qa » nor « admin ». */\n readonly displayName: string;\n readonly role: CastRole;\n readonly locale: \"fr\" | \"en\";\n /** Id of a `person` default of the org defaults JSON (`defaults/v1/person/<id>`). */\n readonly avatar: string;\n /** Id of a `banner` default, for the personas whose page has one. */\n readonly banner?: string;\n /** The demo workspace the persona belongs to (a key the app's seed knows: a set of folders, a shop). */\n readonly workspace: string;\n}\n\n/** The versioned cast. Change it here, then re-run each app's `seed --cast`: every environment gets the same people. */\n// @fixed: a schema version of the cast, bumped by hand when its shape changes\nexport const CAST_VERSION = 1;\n\nexport const CAST: readonly CastPersona[] = [\n // The same three people as the deployed QA accounts (Eric, Mira, Camille) in each product, so a laptop and the dev deployment hold the same names.\n {\n id: \"eric\",\n product: \"yomizaka\",\n firstName: \"Éric\",\n displayName: \"Éric Tremblay\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"community-lead\",\n workspace: \"rosemont-villeray\",\n },\n {\n id: \"mira\",\n product: \"yomizaka\",\n firstName: \"Mira\",\n displayName: \"Mira Haddad\",\n role: \"admin\",\n locale: \"fr\",\n avatar: \"ai-builder\",\n workspace: \"administration\",\n },\n {\n id: \"camille\",\n product: \"yomizaka\",\n firstName: \"Camille\",\n displayName: \"Camille Tremblay\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"visual-artist\",\n workspace: \"rosemont-villeray\",\n },\n // Orazaka: the accounts already deployed on dev. Éric is the user (ORAZAKA_USER_*, APP_QA_ORAZAKA_PERSONA_*), Mira the administrator\n // (ORAZAKA_ADMIN_*, APP_QA_ORAZAKA_MIRA_*), Krizaka the company as an SME customer (APP_QA_ORAZAKA_KRIZAKA_*). The greeting reads the name: never « qa_user ».\n {\n id: \"eric\",\n product: \"orazaka\",\n firstName: \"Éric\",\n displayName: \"Éric Tremblay\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"community-lead\",\n workspace: \"demo\",\n },\n {\n id: \"mira\",\n product: \"orazaka\",\n firstName: \"Mira\",\n displayName: \"Mira Haddad\",\n role: \"admin\",\n locale: \"fr\",\n avatar: \"ai-builder\",\n workspace: \"administration\",\n },\n {\n id: \"krizaka\",\n product: \"orazaka\",\n firstName: \"Krizaka\",\n displayName: \"Krizaka\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"tech-architect\",\n workspace: \"demo\",\n },\n // Akinaza: Éric owns the Krizaka studio, Léa is the Saint-Henri walker, Camille is her first client, Mira administers.\n {\n id: \"eric\",\n product: \"akinaza\",\n firstName: \"Éric\",\n displayName: \"Éric Tremblay\",\n role: \"owner\",\n locale: \"fr\",\n avatar: \"community-lead\",\n banner: \"creator-loft-studio\",\n workspace: \"krizaka-studio\",\n },\n {\n id: \"mira\",\n product: \"akinaza\",\n firstName: \"Mira\",\n displayName: \"Mira Haddad\",\n role: \"admin\",\n locale: \"fr\",\n avatar: \"ai-builder\",\n workspace: \"administration\",\n },\n {\n id: \"lea\",\n product: \"akinaza\",\n firstName: \"Léa\",\n displayName: \"Léa Beaulieu\",\n role: \"owner\",\n locale: \"fr\",\n avatar: \"studio-maker\",\n banner: \"cafe-maker-studio\",\n workspace: \"saint-henri\",\n },\n {\n id: \"camille\",\n product: \"akinaza\",\n firstName: \"Camille\",\n displayName: \"Camille Tremblay\",\n role: \"client\",\n locale: \"fr\",\n avatar: \"visual-artist\",\n workspace: \"saint-henri\",\n },\n {\n id: \"jordan\",\n product: \"akinaza\",\n firstName: \"Jordan\",\n displayName: \"Jordan Lee\",\n role: \"client\",\n locale: \"en\",\n avatar: \"tech-architect\",\n workspace: \"saint-henri\",\n },\n {\n id: \"nadia\",\n product: \"akinaza\",\n firstName: \"Nadia\",\n displayName: \"Nadia Benali\",\n role: \"client\",\n locale: \"fr\",\n avatar: \"digital-creator\",\n workspace: \"saint-henri\",\n },\n {\n id: \"etienne\",\n product: \"akinaza\",\n firstName: \"Étienne\",\n displayName: \"Étienne Gagnon\",\n role: \"client\",\n locale: \"fr\",\n avatar: \"boom-bap\",\n workspace: \"saint-henri\",\n },\n {\n id: \"sofia\",\n product: \"akinaza\",\n firstName: \"Sofia\",\n displayName: \"Sofia Rossi\",\n role: \"client\",\n locale: \"en\",\n avatar: \"salon-tattoo-maker\",\n workspace: \"saint-henri\",\n },\n];\n\n/** The personas of a product, in cast order. */\nexport const castOf = (product: CastProduct): readonly CastPersona[] => CAST.filter((p) => p.product === product);\n\n/** One persona by product and id; throws on an unknown one (a seed or a recording naming a person the cast lacks is a bug). */\nexport function persona(product: CastProduct, id: string): CastPersona {\n const found = CAST.find((p) => p.product === product && p.id === id);\n if (!found)\n throw new Error(\n `cast: no persona \"${id}\" in ${product} (known: ${castOf(product)\n .map((p) => p.id)\n .join(\", \")})`,\n );\n return found;\n}\n\n/** The first persona of a role in a product (the member to sign in as, the administrator). */\nexport function personaByRole(product: CastProduct, role: CastRole): CastPersona {\n const found = castOf(product).find((p) => p.role === role);\n if (!found) throw new Error(`cast: no ${role} in ${product}`);\n return found;\n}\n\nconst urlOf = (kind: \"person\" | \"banner\", id: string, size: number): string => {\n const entry: OrgDefaultItem | undefined = listDefaults(kind).find((d) => d.id === id);\n if (!entry) throw new Error(`cast: no ${kind} default \"${id}\" in the org defaults`);\n return defaultUrl(entry, size);\n};\n\n/** The avatar and banner URLs of a persona, from the org defaults (Bunny, versioned): never typed in an app. */\nexport function castMedia(p: CastPersona, size = 512): { avatar: string; banner?: string } {\n return { avatar: urlOf(\"person\", p.avatar, size), ...(p.banner ? { banner: urlOf(\"banner\", p.banner, 960) } : {}) };\n}\n\n/**\n * The fingerprint of what a seed must leave in a database: counts per table, in a stable order. The seed prints it and\n * a check after the deploy compares the local one with the dev one (same cast and same code give the same string).\n */\nexport function seedFingerprint(counts: Readonly<Record<string, number>>): string {\n return Object.keys(counts)\n .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)) // by code point, never by locale: the same string on every machine\n .map((table) => `${table}=${counts[table]}`)\n .join(\";\");\n}\n","import { CDN, ORG_SCHEMA_URL } from \"./org\";\n\nconst localized = {\n type: \"object\",\n additionalProperties: false,\n required: [\"fr\", \"en\"],\n properties: { fr: { type: \"string\", minLength: 1 }, en: { type: \"string\", minLength: 1 } },\n} as const;\nconst httpsUrl = { type: \"string\", format: \"uri\", pattern: \"^https://\" } as const;\nconst mark = {\n type: \"object\",\n additionalProperties: false,\n required: [\"svg\", \"png64\", \"png256\", \"png512\", \"png1024\"],\n properties: { svg: httpsUrl, png64: httpsUrl, png256: httpsUrl, png512: httpsUrl, png1024: httpsUrl },\n} as const;\nconst slug = { type: \"string\", pattern: \"^[a-z0-9]+(-[a-z0-9]+)*$\" } as const;\nconst themed = {\n type: \"object\",\n additionalProperties: false,\n required: [\"dark\", \"light\"],\n properties: { dark: mark, light: mark },\n} as const;\nconst date = { type: \"string\", pattern: \"^\\\\d{4}-\\\\d{2}-\\\\d{2}$\" } as const;\nconst semver = { type: \"string\", pattern: \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\" } as const;\n\nconst defaultItems = {\n type: \"array\",\n minItems: 1,\n uniqueItems: true,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"alt\", \"urls\"],\n properties: {\n id: slug,\n alt: localized,\n disabled: { const: true },\n urls: {\n type: \"object\",\n additionalProperties: false,\n required: [\"webp\"],\n properties: {\n svg: httpsUrl,\n webp: {\n type: \"object\",\n minProperties: 1,\n propertyNames: { pattern: \"^\\\\d+$\" },\n additionalProperties: httpsUrl,\n },\n },\n },\n },\n },\n} as const;\n\n/** The JSON Schema of `org/v1/org.json`. Nothing outside it is allowed (`additionalProperties: false` everywhere): a new fact is a new line here first. */\nexport const orgSchema = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n $id: ORG_SCHEMA_URL,\n title: \"Krizaka organisation — public facts\",\n type: \"object\",\n additionalProperties: false,\n required: [\n \"$schema\",\n \"schemaVersion\",\n \"version\",\n \"updatedAt\",\n \"company\",\n \"brand\",\n \"people\",\n \"defaults\",\n \"products\",\n \"sites\",\n \"family\",\n \"contact\",\n \"footer\",\n ],\n properties: {\n $schema: { type: \"string\" },\n schemaVersion: { enum: [1, 2] },\n version: semver,\n updatedAt: date,\n company: {\n type: \"object\",\n additionalProperties: false,\n required: [\"legalName\", \"tradeName\", \"neq\", \"city\", \"region\", \"country\", \"license\", \"madeIn\"],\n properties: {\n legalName: { type: \"string\", minLength: 1 },\n tradeName: { type: \"string\", minLength: 1 },\n neq: { type: \"string\", pattern: \"^\\\\d{10}$\" },\n city: { type: \"string\", minLength: 1 },\n region: { type: \"string\", minLength: 1 },\n country: { type: \"string\", pattern: \"^[A-Z]{2}$\" },\n license: { type: \"string\", minLength: 1 },\n madeIn: localized,\n },\n },\n brand: {\n type: \"object\",\n additionalProperties: false,\n required: [\"name\", \"logo\", \"mark\", \"favicon\", \"appleTouchIcon\", \"socialPreview\", \"manifest\"],\n properties: {\n name: { type: \"string\", minLength: 1 },\n logo: themed,\n mark: themed,\n favicon: httpsUrl,\n appleTouchIcon: httpsUrl,\n socialPreview: httpsUrl,\n manifest: httpsUrl,\n },\n },\n people: {\n type: \"object\",\n additionalProperties: false,\n required: [\"defaults\", \"banners\"],\n properties: {\n defaults: {\n type: \"array\",\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"kind\", \"svg\", \"webp256\", \"webp512\", \"alt\"],\n properties: {\n id: slug,\n kind: { enum: [\"person\", \"plain\"] },\n svg: httpsUrl,\n webp256: httpsUrl,\n webp512: httpsUrl,\n alt: localized,\n },\n },\n },\n banners: {\n type: \"array\",\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"url\", \"alt\"],\n properties: { id: slug, url: httpsUrl, alt: localized },\n },\n },\n },\n },\n defaults: {\n type: \"object\",\n additionalProperties: false,\n required: [\"version\", \"base\", \"rule\", \"kinds\"],\n properties: {\n version: { type: \"string\", pattern: \"^v\\\\d+$\" },\n base: httpsUrl,\n rule: {\n type: \"object\",\n additionalProperties: false,\n required: [\"pick\", \"description\"],\n properties: { pick: { const: \"fnv1a32-modulo\" }, description: { type: \"string\", minLength: 1 } },\n },\n kinds: {\n type: \"object\",\n additionalProperties: false,\n required: [\"person\", \"folder\", \"organisation\", \"shop\", \"banner\"],\n properties: Object.fromEntries(\n [\"person\", \"folder\", \"organisation\", \"shop\", \"banner\"].map((kind) => [kind, defaultItems]),\n ),\n },\n },\n },\n products: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"name\", \"status\", \"url\", \"repo\"],\n properties: {\n id: slug,\n name: { type: \"string\", minLength: 1 },\n status: { enum: [\"development\", \"devPreview\"] },\n url: httpsUrl,\n repo: httpsUrl,\n },\n },\n },\n sites: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"name\", \"url\"],\n properties: { id: slug, name: { type: \"string\", minLength: 1 }, url: httpsUrl },\n },\n },\n family: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"name\", \"short\", \"group\", \"status\", \"url\", \"repo\"],\n properties: {\n id: slug,\n name: { type: \"string\", minLength: 1 },\n short: { type: \"string\", minLength: 1 },\n group: { enum: [\"krizaka\", \"products\", \"open-source\", \"github\"] },\n status: { enum: [\"released\", \"development\"] },\n releasedAt: { type: \"string\", pattern: \"^\\\\d{4}-\\\\d{2}-\\\\d{2}$\" },\n url: httpsUrl,\n repo: { anyOf: [httpsUrl, { type: \"null\" }] },\n },\n },\n },\n contact: {\n type: \"object\",\n additionalProperties: false,\n required: [\"page\", \"email\"],\n properties: {\n page: {\n type: \"object\",\n additionalProperties: false,\n required: [\"fr\", \"en\"],\n properties: { fr: httpsUrl, en: httpsUrl },\n },\n email: { type: [\"string\", \"null\"], format: \"email\" },\n },\n },\n footer: {\n type: \"object\",\n additionalProperties: false,\n required: [\"line\", \"legal\"],\n properties: {\n line: localized,\n legal: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"label\", \"url\"],\n properties: {\n id: { enum: [\"privacy\", \"terms\"] },\n label: localized,\n url: {\n type: \"object\",\n additionalProperties: false,\n required: [\"fr\", \"en\"],\n properties: { fr: httpsUrl, en: httpsUrl },\n },\n },\n },\n },\n },\n },\n },\n} as const;\n\n/** The JSON Schema of `apps/<product>.json`. */\nexport const appSchema = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n $id: `${CDN}/org/v1/app.schema.json`,\n title: \"Krizaka mobile app — public runtime config\",\n type: \"object\",\n additionalProperties: false,\n required: [\"$schema\", \"schemaVersion\", \"app\", \"apiBaseUrl\", \"features\", \"minAppVersion\", \"updatedAt\"],\n properties: {\n $schema: { type: \"string\" },\n schemaVersion: { const: 1 },\n app: slug,\n apiBaseUrl: {\n type: \"object\",\n additionalProperties: false,\n required: [\"dev\", \"production\"],\n properties: { dev: { anyOf: [httpsUrl, { type: \"null\" }] }, production: { anyOf: [httpsUrl, { type: \"null\" }] } },\n },\n features: { type: \"object\", additionalProperties: { type: \"boolean\" } },\n minAppVersion: semver,\n updatedAt: date,\n },\n} as const;\n","export { APP_SCHEMA_URL, apps } from \"./apps\";\nexport type { BrandKind, CodeNameHit, OrgBrand } from \"./brands\";\nexport {\n brandOf,\n brands,\n catalogueValues,\n CODE_NAMES,\n codeNameMap,\n DISPLAY_NAME_MAX,\n displayName,\n findCodeNames,\n lockup,\n visibleText,\n} from \"./brands\";\nexport type { CastPersona, CastProduct, CastRole } from \"./cast\";\nexport { CAST, CAST_VERSION, castMedia, castOf, persona, personaByRole, seedFingerprint } from \"./cast\";\nexport { DEFAULT_KINDS, defaultFor, defaults, defaultUrl, fetchDefaults, listDefaults, seedHash } from \"./defaults\";\nexport { CDN, org, ORG_SCHEMA_URL, ORG_URL } from \"./org\";\nexport type {\n AppConfig,\n AppEnvironment,\n FamilyEntry,\n FamilyGroup,\n FamilyStatus,\n Localized,\n Org,\n OrgAvatar,\n OrgBanner,\n OrgDefaultItem,\n OrgDefaultKind,\n OrgDefaults,\n OrgMark,\n OrgProduct,\n OrgSite,\n ProductStatus,\n} from \"./org.types\";\nexport { appSchema, orgSchema } from \"./schema\";\n\nimport { org } from \"./org\";\nimport type { Localized } from \"./org.types\";\n\n/** The text of a localized pair for a language (`fr` or `en`; anything else reads English). */\nexport const localized = (text: Localized, locale: string): string => (locale === \"fr\" ? text.fr : text.en);\n\n/** The footer line of the family, « Une entreprise de Technologies Krizaka · Fait à Montréal ». */\nexport const footerLine = (locale: string): string => localized(org.footer.line, locale);\n\n/** A name of the family by id (`familyName(\"ts\")` → « Krizaka TypeScript »): the only way a site writes one. */\nexport const familyEntry = (id: string) => {\n const entry = org.family.find((e) => e.id === id);\n if (!entry) throw new Error(`Unknown Krizaka family entry \"${id}\".`);\n return entry;\n};\nexport const familyName = (id: string): string => familyEntry(id).name;\n"],"mappings":"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","names":["defaults","brand","mark","mark","localized"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/defaults.ts","../src/org.ts","../src/apps.ts","../src/brands.ts","../src/cast.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@krizaka/org\",\n \"version\": \"1.0.0\",\n \"description\": \"The public facts about Krizaka, in one validated JSON that every footer, site and app reads: legal name, NEQ, « Fait à Montréal » in French and English, brand marks, default avatars and banners, the live products and sites, the public contact, the footer line and the mobile apps' public runtime config. Typed data, JSON Schema, and the files published on the CDN.\",\n \"keywords\": [\n \"krizaka\",\n \"organization\",\n \"footer\",\n \"brand\",\n \"json-schema\"\n ],\n \"homepage\": \"https://ts.krizaka.com/org\",\n \"bugs\": \"https://github.com/krizaka/krizaka-ts/issues\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/krizaka/krizaka-ts.git\",\n \"directory\": \"packages/org\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Krizaka (https://www.krizaka.com)\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./org.json\": \"./dist/org.json\",\n \"./org.schema.json\": \"./dist/org.schema.json\",\n \"./apps/*.json\": \"./dist/apps/*.json\",\n \"./package.json\": \"./package.json\"\n },\n \"bin\": {\n \"krizaka-code-names\": \"./bin/krizaka-code-names.mjs\"\n },\n \"files\": [\n \"dist\",\n \"bin\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"sideEffects\": false,\n \"scripts\": {\n \"build\": \"node -e \\\"require('node:fs').rmSync('dist',{recursive:true,force:true})\\\" && tsup && node scripts/emit.mjs\",\n \"lint\": \"eslint . --max-warnings 0 && tsc --noEmit\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --coverage --coverage.provider=v8 --coverage.reporter=lcov --coverage.reporter=text-summary \\\"--coverage.include=src/**/*.ts\\\"\",\n \"check\": \"pnpm run lint && pnpm run test && pnpm run build\",\n \"publish:cdn\": \"node scripts/publish.mjs\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"devDependencies\": {\n \"@krizaka/config\": \"workspace:^\",\n \"@types/node\": \"^22.10.0\",\n \"ajv\": \"^8.17.0\",\n \"eslint\": \"^9.39.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.1.11\"\n }\n}\n","import type { Localized, OrgDefaultItem, OrgDefaultKind, OrgDefaults } from \"./org.types\";\n\n/** The pull zone that serves the sets. Declared here, not imported from `org.ts`, so `org.ts` can build its section from this file. */\nconst BASE = \"https://krizaka-assets.b-cdn.net/defaults/v1\";\n\n/** The kinds of entity that have a default set, in the order the JSON lists them. */\nexport const DEFAULT_KINDS = [\n \"person\",\n \"folder\",\n \"organisation\",\n \"shop\",\n \"banner\",\n] as const satisfies readonly OrgDefaultKind[];\n\n/** The sizes (px) each kind is served in: squares for the pictures, widths for the banners (3:1). */\nconst SIZES: Record<OrgDefaultKind, readonly number[]> = {\n person: [256, 512, 1024],\n folder: [256, 512, 1024],\n organisation: [256, 512, 1024],\n shop: [256, 512, 1024],\n banner: [960, 1920],\n};\n\n/** Withdrawn pictures, `<kind>/<id>`: kept in the JSON and on the CDN, never picked. The neon flamingo carries the wordmark of a paused product. */\nexport const DISABLED_DEFAULTS: ReadonlySet<string> = new Set([\"banner/the-neon-flamingo\"]);\n\nconst item = (kind: OrgDefaultKind, id: string, alt: Localized, drawn: boolean): OrgDefaultItem => ({\n id,\n alt,\n ...(DISABLED_DEFAULTS.has(`${kind}/${id}`) ? { disabled: true as const } : {}),\n urls: {\n ...(drawn ? { svg: `${BASE}/${kind}/${id}.svg` } : {}),\n webp: Object.fromEntries(SIZES[kind].map((size) => [String(size), `${BASE}/${kind}/${id}-${size}.webp`])),\n },\n});\n\nconst tones = (kind: OrgDefaultKind, id: string, alt: (n: number) => Localized): OrgDefaultItem[] =>\n Array.from({ length: 6 }, (_, i) => item(kind, `${id}-${i + 1}`, alt(i + 1), true));\n\n/** The founder's illustrated people (`defaults/v1/person/<id>-<size>.webp`). Alt texts say what the picture shows, never who. */\nconst PEOPLE: [string, Localized][] = [\n [\n \"boom-bap\",\n {\n en: \"Illustration: a rapper in a denim jacket and beanie, microphone in hand, in a rainy Montréal alley at night\",\n fr: \"Illustration : un rappeur en veste de jean et tuque, micro à la main, dans une ruelle de Montréal sous la pluie, la nuit\",\n },\n ],\n [\n \"rasta-creative\",\n {\n en: \"A smiling man with long dreadlocks in a paint-stained denim jacket, in an artist's workshop\",\n fr: \"Un homme souriant aux longues dreadlocks, en veste de jean tachée de peinture, dans un atelier d'artiste\",\n },\n ],\n [\n \"mile-end-hipster\",\n {\n en: \"A smiling person with round glasses and an orange beanie at a leatherworking bench, in a brick workshop\",\n fr: \"Une personne souriante à lunettes rondes et tuque orange, à son établi de cuir, dans un atelier de briques\",\n },\n ],\n [\n \"tech-architect\",\n {\n en: \"A person in a dark hoodie typing at a keyboard, between screens of code and a server rack\",\n fr: \"Une personne en chandail à capuchon sombre qui tape au clavier, entre des écrans de code et une baie de serveurs\",\n },\n ],\n [\n \"electronic-dj\",\n {\n en: \"A DJ with headphones behind synthesizers and a mixing desk, in a club with violet lights\",\n fr: \"Un DJ casque aux oreilles derrière des synthétiseurs et une table de mixage, dans un club aux lumières violettes\",\n },\n ],\n [\n \"visual-artist\",\n {\n en: \"A smiling painter with violet hair and big glasses, palette in hand, in a studio full of canvases\",\n fr: \"Une peintre souriante aux cheveux violets et aux grosses lunettes, palette à la main, dans un atelier plein de toiles\",\n },\n ],\n [\n \"salon-tattoo-maker\",\n {\n en: \"A tattoo artist with tattooed arms working on a client in a warm shop with wooden shelves\",\n fr: \"Une tatoueuse aux bras tatoués au travail sur un client, dans un salon chaleureux aux étagères de bois\",\n },\n ],\n [\n \"wise-auditor\",\n {\n en: \"A grey-haired person with glasses at a desk of old books and a lamp, a pen over open notes\",\n fr: \"Une personne aux cheveux gris et à lunettes à un bureau de vieux livres et de lampe, un stylo sur des notes ouvertes\",\n },\n ],\n [\n \"digital-creator\",\n {\n en: \"A laughing streamer with a microphone in a purple-lit studio under a neon « Creator Zone » sign\",\n fr: \"Une diffuseuse qui rit devant un micro, dans un studio violet sous une enseigne néon « Creator Zone »\",\n },\n ],\n [\n \"studio-maker\",\n {\n en: \"A potter in a linen apron holding a clay bowl, in a bright ceramics studio with plants\",\n fr: \"Une potière en tablier de lin tenant un bol d'argile, dans un atelier de céramique lumineux et plein de plantes\",\n },\n ],\n [\n \"community-lead\",\n {\n en: \"A smiling person with curly hair and a grey coat at a wooden table, a community space behind them\",\n fr: \"Une personne souriante aux cheveux bouclés et au manteau gris, à une table de bois, devant un espace communautaire\",\n },\n ],\n [\n \"ai-builder\",\n {\n en: \"A thoughtful person with blue-tinted glasses at a desk, screens of a neural network and code behind\",\n fr: \"Une personne pensive aux lunettes teintées de bleu à son bureau, devant des écrans de réseau neuronal et de code\",\n },\n ],\n];\n\n/** The founder's banners, 3:1 (`defaults/v1/banner/<id>-<width>.webp`). */\nconst BANNERS: [string, Localized][] = [\n [\n \"montreal-winter-night\",\n {\n en: \"Illustration: a snowy night in downtown Montréal, lit shop fronts and walkers\",\n fr: \"Illustration : une nuit de neige au centre-ville de Montréal, devantures éclairées et passants\",\n },\n ],\n [\n \"industrial-heritage\",\n {\n en: \"Dark blue skyline of old brick buildings with lit orange windows under a full moon\",\n fr: \"Silhouette bleu nuit de vieux immeubles de briques aux fenêtres orangées, sous la pleine lune\",\n },\n ],\n [\n \"creator-loft-studio\",\n {\n en: \"A dark loft desk with a plant, a code window and a mixing board\",\n fr: \"Un bureau de loft sombre avec une plante, une fenêtre de code et une table de mixage\",\n },\n ],\n [\n \"abstract-digital-flow\",\n {\n en: \"Flowing teal, violet and orange lines linking glowing points on a dark background\",\n fr: \"Des lignes ondulantes turquoise, violettes et orange reliant des points lumineux sur fond sombre\",\n },\n ],\n [\n \"paperwork-and-ink\",\n {\n en: \"Two dark document cards with colored stamps on a night-blue grid\",\n fr: \"Deux cartes de documents sombres tamponnées de couleur sur une grille bleu nuit\",\n },\n ],\n [\n \"nightlife-music-visual\",\n {\n en: \"A large glowing vinyl record with a pink label beside a small level meter, in violet light\",\n fr: \"Un grand disque vinyle lumineux à l'étiquette rose près d'un petit indicateur de niveau, en lumière violette\",\n },\n ],\n [\n \"the-mascot-flock\",\n {\n en: \"The Krizaka mascots — an owl, a beaver and a flamingo — standing on a shelf in the dark\",\n fr: \"Les mascottes de Krizaka — un hibou, un castor et un flamant — debout sur une étagère dans le noir\",\n },\n ],\n [\n \"abstract-stripes\",\n {\n en: \"Diagonal teal, indigo, violet and orange stripes with a white star and « Montréal // 514 »\",\n fr: \"Des bandes diagonales turquoise, indigo, violettes et orange avec une étoile blanche et « Montréal // 514 »\",\n },\n ],\n [\n \"open-source-horizon\",\n {\n en: \"A dark terminal window on a grid, a faint horizon behind\",\n fr: \"Une fenêtre de terminal sombre sur une grille, un horizon pâle derrière\",\n },\n ],\n [\n \"cafe-maker-studio\",\n {\n en: \"A warm dark brown scene with a card reading « Fabriqué à Montréal »\",\n fr: \"Une scène brun foncé chaleureuse avec une carte « Fabriqué à Montréal »\",\n },\n ],\n [\n \"the-neon-flamingo\",\n {\n en: \"A pink neon flamingo outline on black, with a violet halo\",\n fr: \"Le contour d'un flamant rose en néon sur fond noir, avec un halo violet\",\n },\n ],\n [\n \"cooperative-network\",\n {\n en: \"Small linked glowing points over a dark hill at dusk\",\n fr: \"De petits points lumineux reliés au-dessus d'une colline sombre au crépuscule\",\n },\n ],\n];\n\nconst GLYPH_ALT = {\n person: (n: number): Localized => ({\n en: `Default profile picture: a silhouette, tone ${n}`,\n fr: `Photo de profil par défaut : une silhouette, teinte ${n}`,\n }),\n folder: (n: number): Localized => ({\n en: `Default folder picture: a folder, tone ${n}`,\n fr: `Image de dossier par défaut : un dossier, teinte ${n}`,\n }),\n organisation: (n: number): Localized => ({\n en: `Default organisation picture: a building, tone ${n}`,\n fr: `Image d'organisation par défaut : un immeuble, teinte ${n}`,\n }),\n shop: (n: number): Localized => ({\n en: `Default shop picture: a storefront, tone ${n}`,\n fr: `Image de boutique par défaut : une devanture, teinte ${n}`,\n }),\n};\n\n/** The `defaults` section of the org JSON: the central sets on Bunny (`defaults/v1/<kind>/<id>-<size>.<ext>`), written by krizaka-ui `tools/export-defaults.mjs`. */\nexport const defaults: OrgDefaults = {\n version: \"v1\",\n base: BASE,\n rule: {\n pick: \"fnv1a32-modulo\",\n description:\n \"defaultFor(kind, seed) = items[fnv1a32(String(seed)) mod items.length] of the kind's list, in the order of the JSON; the same seed always gives the same item, in every app.\",\n },\n kinds: {\n person: [\n ...tones(\"person\", \"silhouette\", GLYPH_ALT.person),\n ...PEOPLE.map(([id, alt]) => item(\"person\", id, alt, false)),\n ],\n folder: tones(\"folder\", \"folder\", GLYPH_ALT.folder),\n organisation: tones(\"organisation\", \"organisation\", GLYPH_ALT.organisation),\n shop: tones(\"shop\", \"shop\", GLYPH_ALT.shop),\n banner: BANNERS.map(([id, alt]) => item(\"banner\", id, alt, false)),\n },\n};\n\n// ---- reading -------------------------------------------------------------------------------------------------------\n\n/** 32-bit FNV-1a of a seed: stable across runs, devices and products (the same one `@krizaka/ui`'s default avatars use). */\nexport function seedHash(seed: string | number): number {\n let h = 0x811c9dc5;\n for (const ch of String(seed)) {\n h ^= ch.codePointAt(0) ?? 0;\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h;\n}\n\n/** The items of a kind that can be picked, in the order of the JSON (a withdrawn one is skipped). A source other than the bundled one is the JSON an app fetched. */\nexport function listDefaults(kind: OrgDefaultKind, source: OrgDefaults = defaults): readonly OrgDefaultItem[] {\n return (source.kinds[kind] ?? []).filter((entry) => entry.disabled !== true);\n}\n\n/** The item of a kind for a seed (an entity's id): deterministic, so a folder keeps its picture everywhere. `undefined` only when the kind's list is empty. */\nexport function defaultFor(\n kind: OrgDefaultKind,\n seed: string | number,\n source: OrgDefaults = defaults,\n): OrgDefaultItem | undefined {\n const items = listDefaults(kind, source);\n return items.length === 0 ? undefined : items[seedHash(seed) % items.length];\n}\n\n/** The URL of an item at the smallest size that is at least `size` px (or the largest there is); `svg` when the item has a vector and `format` says so. */\nexport function defaultUrl(entry: OrgDefaultItem, size: number, format: \"webp\" | \"svg\" = \"webp\"): string {\n if (format === \"svg\" && entry.urls.svg) return entry.urls.svg;\n const sizes = Object.keys(entry.urls.webp)\n .map(Number)\n .sort((a, b) => a - b);\n const chosen = sizes.find((s) => s >= size) ?? sizes[sizes.length - 1];\n return entry.urls.webp[String(chosen)] ?? \"\";\n}\n\n/** Reads the section from the published JSON (`ORG_URL`), for an app that does not bundle this package. */\nexport async function fetchDefaults(url: string, fetchImpl: typeof fetch = fetch): Promise<OrgDefaults> {\n const res = await fetchImpl(url, { headers: { Accept: \"application/json\" } });\n if (!res.ok) throw new Error(`${url} answered ${res.status}`);\n const json = (await res.json()) as { defaults?: OrgDefaults };\n if (!json.defaults) throw new Error(`${url} has no \\`defaults\\` section`);\n return json.defaults;\n}\n","import pkg from \"../package.json\" with { type: \"json\" };\nimport { defaults as centralDefaults } from \"./defaults\";\nimport type { Localized, Org, OrgAvatar, OrgMark } from \"./org.types\";\n\n/** The pull zone that serves the brand files and this JSON. */\nexport const CDN = \"https://krizaka-assets.b-cdn.net\";\nexport const ORG_URL = `${CDN}/org/v1/org.json`;\nexport const ORG_SCHEMA_URL = `${CDN}/org/v1/org.schema.json`;\n\nconst cdn = (path: string) => `${CDN}/${path}`;\n\nconst mark = (kind: \"logo\" | \"mark\", theme: \"dark\" | \"light\"): OrgMark => ({\n svg: cdn(`brand/krizaka/${kind}-${theme}.svg`),\n png64: cdn(`brand/krizaka/${kind}-${theme}-64.png`),\n png256: cdn(`brand/krizaka/${kind}-${theme}-256.png`),\n png512: cdn(`brand/krizaka/${kind}-${theme}-512.png`),\n png1024: cdn(`brand/krizaka/${kind}-${theme}-1024.png`),\n});\n\nconst TONES = [1, 2, 3, 4, 5, 6] as const;\n\nconst avatarAlt = (kind: \"person\" | \"plain\", n: number): Localized =>\n kind === \"person\"\n ? {\n fr: `Photo de profil par défaut : silhouette, teinte ${n}`,\n en: `Default profile picture: silhouette, tone ${n}`,\n }\n : {\n fr: `Photo de profil par défaut : disque uni, teinte ${n}`,\n en: `Default profile picture: plain disc, tone ${n}`,\n };\n\n/** The default profile pictures a product shows when a person has no photo (`people/defaults/v1`, krizaka-ui `tools/export-brand.mjs`). */\nconst defaults: OrgAvatar[] = ([\"person\", \"plain\"] as const).flatMap((kind) =>\n TONES.map((n) => ({\n id: `${kind}-${n}`,\n kind,\n svg: cdn(`people/defaults/v1/krizaka/${kind}-${n}.svg`),\n webp256: cdn(`people/defaults/v1/krizaka/${kind}-${n}-256.webp`),\n webp512: cdn(`people/defaults/v1/krizaka/${kind}-${n}-512.webp`),\n alt: avatarAlt(kind, n),\n })),\n);\n\n/** The public facts about Krizaka. Reviewed by pull request; changing a fact is one PR here and a release. */\ntype FamilyEntry = NonNullable<Org[\"family\"]>[number];\ntype FamilyRow = [\n FamilyEntry[\"id\"],\n string,\n string,\n FamilyEntry[\"group\"],\n FamilyEntry[\"status\"],\n string,\n string | null,\n];\n\nconst GITHUB = \"https://github.com/krizaka\";\nconst gh = (repo: string) => `${GITHUB}/${repo}`;\n\n/** The family list as data: one row per entry (id, name, short, group, status, url, repo). */\nconst FAMILY_ROWS: FamilyRow[] = [\n [\"krizaka\", \"Krizaka\", \"Krizaka\", \"krizaka\", \"released\", \"https://www.krizaka.com\", gh(\"krizaka-com\")],\n [\"blog\", \"Blog\", \"Blog\", \"krizaka\", \"released\", \"https://blog.krizaka.com\", gh(\"krizaka-blog\")],\n [\"sovkora\", \"Sovkora\", \"Sovkora\", \"products\", \"development\", \"https://www.sovkora.com\", gh(\"sovkora\")],\n [\"verikora\", \"Verikora\", \"Verikora\", \"products\", \"development\", \"https://www.verikora.com\", gh(\"verikora\")],\n [\"folioviv\", \"Folioviv\", \"Folioviv\", \"products\", \"development\", \"https://www.folioviv.com\", gh(\"folioviv\")],\n [\"ui\", \"Krizaka UI\", \"UI\", \"open-source\", \"development\", \"https://ui.krizaka.com\", gh(\"krizaka-ui\")],\n [\"java\", \"Krizaka Java\", \"Java\", \"open-source\", \"development\", \"https://java.krizaka.com\", gh(\"krizaka-java\")],\n [\"ts\", \"Krizaka TypeScript\", \"TypeScript\", \"open-source\", \"development\", \"https://ts.krizaka.com\", gh(\"krizaka-ts\")],\n [\"lab\", \"Krizaka Lab\", \"Lab\", \"open-source\", \"development\", \"https://lab.krizaka.com\", gh(\"krizaka-lab\")],\n [\"github\", \"GitHub\", \"GitHub\", \"github\", \"released\", GITHUB, null],\n];\n\nconst family: FamilyEntry[] = FAMILY_ROWS.map(([id, name, short, group, status, url, repo]) => ({\n id,\n name,\n short,\n group,\n status,\n url,\n repo,\n}));\n\nexport const org: Org = {\n $schema: ORG_SCHEMA_URL,\n schemaVersion: 2,\n version: pkg.version,\n updatedAt: \"2026-10-30\",\n company: {\n legalName: \"Technologies Krizaka Inc.\",\n tradeName: \"Krizaka\",\n neq: \"1182652231\",\n city: \"Montréal\",\n region: \"Québec\",\n country: \"CA\",\n license: \"Apache-2.0\",\n madeIn: { fr: \"Fait à Montréal\", en: \"Made in Montréal\" },\n },\n brand: {\n name: \"Krizaka\",\n logo: { dark: mark(\"logo\", \"dark\"), light: mark(\"logo\", \"light\") },\n mark: { dark: mark(\"mark\", \"dark\"), light: mark(\"mark\", \"light\") },\n favicon: cdn(\"brand/krizaka/favicon.svg\"),\n appleTouchIcon: cdn(\"brand/krizaka/apple-touch-icon.png\"),\n socialPreview: cdn(\"brand/krizaka/social-preview-1280x640.png\"),\n manifest: cdn(\"brand/manifest.json\"),\n },\n people: {\n defaults,\n // No banner is published on the CDN yet; the set joins here with its alts when it is.\n banners: [],\n },\n defaults: centralDefaults,\n products: [\n {\n id: \"sovkora\",\n name: \"Sovkora\",\n status: \"development\",\n url: \"https://www.sovkora.com\",\n repo: \"https://github.com/krizaka/sovkora\",\n },\n {\n id: \"verikora\",\n name: \"Verikora\",\n status: \"development\",\n url: \"https://www.verikora.com\",\n repo: \"https://github.com/krizaka/verikora\",\n },\n {\n id: \"folioviv\",\n name: \"Folioviv\",\n status: \"development\",\n url: \"https://www.folioviv.com\",\n repo: \"https://github.com/krizaka/folioviv\",\n },\n ],\n sites: [\n { id: \"www\", name: \"krizaka.com\", url: \"https://www.krizaka.com\" },\n { id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\" },\n { id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\" },\n { id: \"ts\", name: \"Krizaka TypeScript\", url: \"https://ts.krizaka.com\" },\n { id: \"motion\", name: \"Krizaka Lab\", url: \"https://lab.krizaka.com\" },\n { id: \"blog\", name: \"Blog\", url: \"https://blog.krizaka.com\" },\n ],\n family,\n contact: {\n page: { fr: \"https://www.krizaka.com/fr/contact\", en: \"https://www.krizaka.com/en/contact\" },\n email: null,\n },\n footer: {\n line: {\n fr: \"Une entreprise de Technologies Krizaka · Fait à Montréal\",\n en: \"A Technologies Krizaka company · Made in Montréal\",\n },\n legal: [\n {\n id: \"privacy\",\n label: { fr: \"Confidentialité\", en: \"Privacy\" },\n url: { fr: \"https://www.krizaka.com/fr/privacy\", en: \"https://www.krizaka.com/en/privacy\" },\n },\n {\n id: \"terms\",\n label: { fr: \"Conditions\", en: \"Terms\" },\n url: { fr: \"https://www.krizaka.com/fr/terms\", en: \"https://www.krizaka.com/en/terms\" },\n },\n ],\n },\n};\n","import { CDN } from \"./org\";\nimport type { AppConfig } from \"./org.types\";\n\nexport const APP_SCHEMA_URL = `${CDN}/org/v1/app.schema.json`;\nconst UPDATED = \"2026-10-26\";\n\nconst app = (id: string, devUrl: string): AppConfig => ({\n $schema: APP_SCHEMA_URL,\n schemaVersion: 1,\n app: id,\n // Public by nature: an address a client calls. No key, no token, no internal host.\n apiBaseUrl: { dev: devUrl, production: null },\n features: {},\n minAppVersion: \"0.0.0\",\n updatedAt: UPDATED,\n});\n\n/** The runtime config a mobile app may know, per live product. The app reads it at start, with a copy built into the binary as fallback. */\nexport const apps: Record<string, AppConfig> = {\n sovkora: app(\"sovkora\", \"https://dev.sovkora.com\"),\n verikora: app(\"verikora\", \"https://dev.verikora.com\"),\n folioviv: app(\"folioviv\", \"https://dev.folioviv.com\"),\n};\n","import type { Localized } from \"./org.types\";\n\n/**\n * The brands of Krizaka (krizaka-internal#2033, #2035; renamed 2026-11-06, krizaka-internal#2659): one id per brand, and the\n * id is the commercial name (`verikora`), the customer reads « Verikora by Krizaka ». Every app, site and template reads\n * them from here — never a literal.\n *\n * These are NOT in `org.json`: the org JSON is service discovery only (the addresses and versions clients resolve). Names,\n * status, stores and the footer are admin configuration of each app (`@krizaka/settings`, audit trail); this module is the\n * seed and the validation vocabulary, not a published file.\n */\n\n/** `product`: sold on its own. `service`: a part the products carry (Kridoc, the managed storage). */\nexport type BrandKind = \"product\" | \"service\";\n\nexport interface OrgBrand {\n /** The id of the brand: its commercial name in lower case (`verikora`) — repositories, packages, hosts, CLI. */\n id: string;\n /** The name the customer reads (`Verikora`). One capital; capitals only in the wordmark. */\n commercialName: string;\n kind: BrandKind;\n /** The endorsement after the name: « by Krizaka » / « par Krizaka ». */\n endorsement: Localized;\n /** The hosts of the brand (https URLs); `null` where it has none. */\n domains: { site: string; app: string | null; shop: string | null; dev: string | null };\n}\n\nconst ENDORSEMENT = { en: \"by Krizaka\", fr: \"par Krizaka\" };\n\nconst brand = (id: string, commercialName: string, kind: BrandKind, domains: OrgBrand[\"domains\"]): OrgBrand => ({\n id,\n commercialName,\n kind,\n endorsement: ENDORSEMENT,\n domains,\n});\n\n/** The brands, one per product or service. */\nexport const brands: readonly OrgBrand[] = [\n brand(\"verikora\", \"Verikora\", \"product\", {\n site: \"https://www.verikora.com\",\n app: null,\n shop: null,\n dev: \"https://dev.verikora.com\",\n }),\n brand(\"folioviv\", \"Folioviv\", \"product\", {\n site: \"https://www.folioviv.com\",\n app: \"https://folioviv.app\",\n shop: \"https://folioviv.shop\",\n dev: \"https://dev.folioviv.com\",\n }),\n brand(\"sovkora\", \"Sovkora\", \"product\", {\n site: \"https://www.sovkora.com\",\n app: null,\n shop: null,\n dev: \"https://dev.sovkora.com\",\n }),\n // Kridoc is the managed storage (Krizaka ECM, krizaka-internal#1916).\n brand(\"kridoc\", \"Kridoc\", \"service\", { site: \"https://www.kridoc.com\", app: null, shop: null, dev: null }),\n];\n\n/**\n * The historic table, and the only place the retired code names are written (founder, 2026-11-06, krizaka-internal#2659):\n * old code name → brand id. History (commits, closed issues, CHANGELOG, released coordinates) keeps the old names; nothing\n * else does — there is no alias, `brandOf(\"yomizaka\")` throws and names the new id.\n */\nexport const CODE_NAMES: Readonly<Record<string, string>> = Object.freeze({\n yomizaka: \"verikora\",\n akinaza: \"folioviv\",\n orazaka: \"sovkora\",\n kachizaka: \"kridoc\",\n});\n\n/** The brand of an id (`brandOf(\"verikora\").commercialName` → « Verikora »). A retired code name is refused, never mapped. */\nexport const brandOf = (id: string): OrgBrand => {\n const found = brands.find((b) => b.id === id);\n if (found) return found;\n const renamed = CODE_NAMES[id.toLowerCase()];\n if (renamed) throw new Error(`\"${id}\" is a retired code name (krizaka-internal#2659): use brandOf(\"${renamed}\").`);\n throw new Error(`Unknown Krizaka brand \"${id}\".`);\n};\n\n/** The longest name an administrator may set (a bar, a store listing and an email subject must hold it). */\n// @fixed: the App Store's display name limit is 30 characters; the bar and the lockup are drawn for it\nexport const DISPLAY_NAME_MAX = 30;\n\n/**\n * The name an app shows: the administrator's choice (`brand.displayName` in its settings) when one is set, else the\n * commercial name. Never a retired code name: a setting that holds one falls back to the commercial name.\n */\nexport const displayName = (id: string, chosen?: string | null): string => {\n const own = chosen?.trim() ?? \"\";\n if (own.length === 0 || own.length > DISPLAY_NAME_MAX || findCodeNames(own).length > 0)\n return brandOf(id).commercialName;\n return own;\n};\n\n/** The lockup in words: « Verikora by Krizaka » / « Verikora par Krizaka ». `fr` reads French, anything else English. */\nexport const lockup = (id: string, locale: string, chosen?: string | null): string => {\n const { endorsement } = brandOf(id);\n return `${displayName(id, chosen)} ${locale === \"fr\" ? endorsement.fr : endorsement.en}`;\n};\n\n/** Retired code name → commercial name (`yomizaka` → « Verikora »): what the guard prints in its hints. */\nexport const codeNameMap = (): Record<string, string> =>\n Object.fromEntries(Object.entries(CODE_NAMES).map(([old, id]) => [old, brandOf(id).commercialName]));\n\n/** Former wordings that are not code names but are retired too. */\nconst FORMER_WORDINGS: readonly [RegExp, string][] = [[/\\bkrizaka\\s+ecm\\b/gi, \"Kridoc\"]];\n\n/** Every retired code name, anywhere in a word, any case (`ORAZAKA_KEY`, `brand-yomizaka`, `dev.akinaza.com`). Linear. */\nconst codeNamePattern = () => new RegExp(`(${Object.keys(CODE_NAMES).join(\"|\")})`, \"gi\");\n\nexport interface CodeNameHit {\n /** The word found, as written. */\n word: string;\n /** What to write instead, in the same case (`ORAZAKA` → `SOVKORA`, `Yomizaka` → `Verikora`, `akinaza` → `folioviv`). */\n use: string;\n /** Up to 40 characters around it. */\n context: string;\n}\n\n/** The replacement of a retired code name, in the case it was written. */\nconst replacementOf = (word: string): string => {\n const id = CODE_NAMES[word.toLowerCase()] ?? \"\";\n if (word === word.toUpperCase()) return id.toUpperCase();\n if (word.startsWith(word.charAt(0).toUpperCase())) return brandOf(id).commercialName;\n return id;\n};\n\n/**\n * The retired code names a text holds (founder, 2026-11-06: none, anywhere): every occurrence in any case, in prose, code,\n * hosts, URLs, package coordinates and code spans alike — there is no allowed span. Only the historic table above and the\n * history (CHANGELOG files, skipped by the `krizaka-code-names` bin) keep them.\n */\nexport const findCodeNames = (text: string): CodeNameHit[] => {\n const hits: CodeNameHit[] = [];\n const around = (i: number, n: number) =>\n text\n .slice(Math.max(0, i - 20), i + n + 20)\n .replace(/\\s+/g, \" \")\n .trim();\n for (const m of text.matchAll(codeNamePattern())) {\n hits.push({ word: m[0], use: replacementOf(m[0]), context: around(m.index, m[0].length) });\n }\n for (const [re, use] of FORMER_WORDINGS) {\n for (const m of text.matchAll(re)) hits.push({ word: m[0], use, context: around(m.index, m[0].length) });\n }\n return hits;\n};\n\n/** The text without the spans from `open` to `close` (an unclosed one runs to the end). Linear: no backtracking regex on page input. */\nconst stripBlocks = (text: string, open: string, close: string): string => {\n let out = \"\";\n let at = 0;\n for (;;) {\n const start = text.indexOf(open, at);\n if (start < 0) return out + text.slice(at);\n out += `${text.slice(at, start)} `;\n const end = text.indexOf(close, start + open.length);\n if (end < 0) return out;\n at = end + close.length;\n }\n};\n\nconst SKIPPED_ELEMENTS = [\"script\", \"style\", \"pre\", \"code\", \"svg\"];\n/** Where the element `name` next opens from `at` (`<code>` or `<code class…>`, never `<codex>`), or -1. */\nconst openingOf = (lower: string, name: string, at: number): number => {\n for (let i = lower.indexOf(`<${name}`, at); i >= 0; i = lower.indexOf(`<${name}`, i + 1)) {\n if (!/[a-z0-9-]/.test(lower[i + name.length + 1] ?? \" \")) return i;\n }\n return -1;\n};\n/** The first skipped element that opens from `at`: its index (-1 when none) and its name. */\nconst nextSkipped = (lower: string, at: number): [number, string] => {\n let found: [number, string] = [-1, \"\"];\n for (const name of SKIPPED_ELEMENTS) {\n const i = openingOf(lower, name, at);\n if (i >= 0 && (found[0] < 0 || i < found[0])) found = [i, name];\n }\n return found;\n};\n/** The text with every tag (`<…>`) replaced by a space, in one linear pass (no backtracking regex on page input). */\nconst stripTags = (html: string): string => {\n let out = \"\";\n let at = 0;\n for (let open = html.indexOf(\"<\"); open >= 0; open = html.indexOf(\"<\", at)) {\n const close = html.indexOf(\">\", open + 1);\n if (close < 0) break;\n out += `${html.slice(at, open)} `;\n at = close + 1;\n }\n return out + html.slice(at);\n};\n/** The text without the elements a visitor does not read as prose (scripts, styles, code, svg), matched case-insensitively. */\nconst stripElements = (html: string): string => {\n const lower = html.toLowerCase();\n let out = \"\";\n let at = 0;\n while (at < html.length) {\n const [next, tag] = nextSkipped(lower, at);\n if (next < 0) return out + html.slice(at);\n out += `${html.slice(at, next)} `;\n const end = lower.indexOf(`</${tag}>`, next);\n if (end < 0) return out;\n at = end + tag.length + 3;\n }\n return out;\n};\n\n/**\n * The text a visitor reads in a built HTML page: the body text, the title, the description and social metadata, and the\n * `alt`, `title` and `aria-label` attributes. Scripts, styles, `<pre>` and `<code>` (developer pages' commands) and\n * comments are left out, and so are class names and links (a `brand-verikora` class or a GitHub href is not shown).\n */\nexport const visibleText = (html: string): string => {\n const attrs: string[] = [];\n for (const m of html.matchAll(/<meta\\b[^>]*>/gi)) {\n if (\n /\\b(?:name|property)\\s*=\\s*[\"'](?:description|og:[\\w:]+|twitter:[\\w:]+|application-name|apple-mobile-web-app-title)[\"']/i.test(\n m[0],\n )\n ) {\n const content = /\\bcontent\\s*=\\s*\"([^\"]*)\"|\\bcontent\\s*=\\s*'([^']*)'/i.exec(m[0]);\n if (content) attrs.push(content[1] ?? content[2] ?? \"\");\n }\n }\n for (const m of html.matchAll(/\\b(?:alt|title|aria-label)\\s*=\\s*\"([^\"]*)\"/gi)) attrs.push(m[1] ?? \"\");\n const body = stripTags(stripElements(stripBlocks(html, \"<!--\", \"-->\")))\n .replaceAll(\" \", \" \")\n .replaceAll(\"&\", \"&\");\n return [body, ...attrs].join(\"\\n\");\n};\n\n/**\n * The values of a message catalogue (EN/FR JSON), keyed by their path. Keys are structure\n * (`site.verikora.title`); only the values are read by a customer.\n */\nexport const catalogueValues = (catalogue: unknown, path = \"\"): [string, string][] => {\n if (typeof catalogue === \"string\") return [[path, catalogue]];\n if (Array.isArray(catalogue)) return catalogue.flatMap((v, i) => catalogueValues(v, `${path}[${i}]`));\n if (catalogue && typeof catalogue === \"object\") {\n return Object.entries(catalogue).flatMap(([k, v]) => catalogueValues(v, path ? `${path}.${k}` : k));\n }\n return [];\n};\n","import { defaultUrl, listDefaults } from \"./defaults\";\nimport type { OrgDefaultItem } from \"./org.types\";\n\n/** The products that have a demo cast. */\nexport type CastProduct = \"sovkora\" | \"verikora\" | \"folioviv\";\n\n/** What a persona does in the app: a member, a shop owner or a customer of one, an administrator. */\nexport type CastRole = \"member\" | \"admin\" | \"owner\" | \"client\";\n\n/** One fictitious person of the demo cast. No e-mail domain and no password: those come from the environment, through the secrets map. */\nexport interface CastPersona {\n /** Stable key, unique in its product: `eric`, `camille`. Seeds, recordings and tests name the persona by it. */\n readonly id: string;\n readonly product: CastProduct;\n readonly firstName: string;\n /** The name every screen, demo and recording shows: never « qa » nor « admin ». */\n readonly displayName: string;\n readonly role: CastRole;\n readonly locale: \"fr\" | \"en\";\n /** Id of a `person` default of the org defaults JSON (`defaults/v1/person/<id>`). */\n readonly avatar: string;\n /** Id of a `banner` default, for the personas whose page has one. */\n readonly banner?: string;\n /** The demo workspace the persona belongs to (a key the app's seed knows: a set of folders, a shop). */\n readonly workspace: string;\n}\n\n/** The versioned cast. Change it here, then re-run each app's `seed --cast`: every environment gets the same people. */\n// @fixed: a schema version of the cast, bumped by hand when its shape changes\nexport const CAST_VERSION = 1;\n\nexport const CAST: readonly CastPersona[] = [\n // The same three people as the deployed QA accounts (Eric, Mira, Camille) in each product, so a laptop and the dev deployment hold the same names.\n {\n id: \"eric\",\n product: \"verikora\",\n firstName: \"Éric\",\n displayName: \"Éric Tremblay\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"community-lead\",\n workspace: \"rosemont-villeray\",\n },\n {\n id: \"mira\",\n product: \"verikora\",\n firstName: \"Mira\",\n displayName: \"Mira Haddad\",\n role: \"admin\",\n locale: \"fr\",\n avatar: \"ai-builder\",\n workspace: \"administration\",\n },\n {\n id: \"camille\",\n product: \"verikora\",\n firstName: \"Camille\",\n displayName: \"Camille Tremblay\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"visual-artist\",\n workspace: \"rosemont-villeray\",\n },\n // Sovkora: the accounts already deployed on dev. Éric is the user (SOVKORA_USER_*, APP_QA_SOVKORA_PERSONA_*), Mira the administrator\n // (SOVKORA_ADMIN_*, APP_QA_SOVKORA_MIRA_*), Krizaka the company as an SME customer (APP_QA_SOVKORA_KRIZAKA_*). The greeting reads the name: never « qa_user ».\n {\n id: \"eric\",\n product: \"sovkora\",\n firstName: \"Éric\",\n displayName: \"Éric Tremblay\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"community-lead\",\n workspace: \"demo\",\n },\n {\n id: \"mira\",\n product: \"sovkora\",\n firstName: \"Mira\",\n displayName: \"Mira Haddad\",\n role: \"admin\",\n locale: \"fr\",\n avatar: \"ai-builder\",\n workspace: \"administration\",\n },\n {\n id: \"krizaka\",\n product: \"sovkora\",\n firstName: \"Krizaka\",\n displayName: \"Krizaka\",\n role: \"member\",\n locale: \"fr\",\n avatar: \"tech-architect\",\n workspace: \"demo\",\n },\n // Folioviv: Éric owns the Krizaka studio, Léa is the Saint-Henri walker, Camille is her first client, Mira administers.\n {\n id: \"eric\",\n product: \"folioviv\",\n firstName: \"Éric\",\n displayName: \"Éric Tremblay\",\n role: \"owner\",\n locale: \"fr\",\n avatar: \"community-lead\",\n banner: \"creator-loft-studio\",\n workspace: \"krizaka-studio\",\n },\n {\n id: \"mira\",\n product: \"folioviv\",\n firstName: \"Mira\",\n displayName: \"Mira Haddad\",\n role: \"admin\",\n locale: \"fr\",\n avatar: \"ai-builder\",\n workspace: \"administration\",\n },\n {\n id: \"lea\",\n product: \"folioviv\",\n firstName: \"Léa\",\n displayName: \"Léa Beaulieu\",\n role: \"owner\",\n locale: \"fr\",\n avatar: \"studio-maker\",\n banner: \"cafe-maker-studio\",\n workspace: \"saint-henri\",\n },\n {\n id: \"camille\",\n product: \"folioviv\",\n firstName: \"Camille\",\n displayName: \"Camille Tremblay\",\n role: \"client\",\n locale: \"fr\",\n avatar: \"visual-artist\",\n workspace: \"saint-henri\",\n },\n {\n id: \"jordan\",\n product: \"folioviv\",\n firstName: \"Jordan\",\n displayName: \"Jordan Lee\",\n role: \"client\",\n locale: \"en\",\n avatar: \"tech-architect\",\n workspace: \"saint-henri\",\n },\n {\n id: \"nadia\",\n product: \"folioviv\",\n firstName: \"Nadia\",\n displayName: \"Nadia Benali\",\n role: \"client\",\n locale: \"fr\",\n avatar: \"digital-creator\",\n workspace: \"saint-henri\",\n },\n {\n id: \"etienne\",\n product: \"folioviv\",\n firstName: \"Étienne\",\n displayName: \"Étienne Gagnon\",\n role: \"client\",\n locale: \"fr\",\n avatar: \"boom-bap\",\n workspace: \"saint-henri\",\n },\n {\n id: \"sofia\",\n product: \"folioviv\",\n firstName: \"Sofia\",\n displayName: \"Sofia Rossi\",\n role: \"client\",\n locale: \"en\",\n avatar: \"salon-tattoo-maker\",\n workspace: \"saint-henri\",\n },\n];\n\n/** The personas of a product, in cast order. */\nexport const castOf = (product: CastProduct): readonly CastPersona[] => CAST.filter((p) => p.product === product);\n\n/** One persona by product and id; throws on an unknown one (a seed or a recording naming a person the cast lacks is a bug). */\nexport function persona(product: CastProduct, id: string): CastPersona {\n const found = CAST.find((p) => p.product === product && p.id === id);\n if (!found)\n throw new Error(\n `cast: no persona \"${id}\" in ${product} (known: ${castOf(product)\n .map((p) => p.id)\n .join(\", \")})`,\n );\n return found;\n}\n\n/** The first persona of a role in a product (the member to sign in as, the administrator). */\nexport function personaByRole(product: CastProduct, role: CastRole): CastPersona {\n const found = castOf(product).find((p) => p.role === role);\n if (!found) throw new Error(`cast: no ${role} in ${product}`);\n return found;\n}\n\nconst urlOf = (kind: \"person\" | \"banner\", id: string, size: number): string => {\n const entry: OrgDefaultItem | undefined = listDefaults(kind).find((d) => d.id === id);\n if (!entry) throw new Error(`cast: no ${kind} default \"${id}\" in the org defaults`);\n return defaultUrl(entry, size);\n};\n\n/** The avatar and banner URLs of a persona, from the org defaults (Bunny, versioned): never typed in an app. */\nexport function castMedia(p: CastPersona, size = 512): { avatar: string; banner?: string } {\n return { avatar: urlOf(\"person\", p.avatar, size), ...(p.banner ? { banner: urlOf(\"banner\", p.banner, 960) } : {}) };\n}\n\n/**\n * The fingerprint of what a seed must leave in a database: counts per table, in a stable order. The seed prints it and\n * a check after the deploy compares the local one with the dev one (same cast and same code give the same string).\n */\nexport function seedFingerprint(counts: Readonly<Record<string, number>>): string {\n return Object.keys(counts)\n .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)) // by code point, never by locale: the same string on every machine\n .map((table) => `${table}=${counts[table]}`)\n .join(\";\");\n}\n","import { CDN, ORG_SCHEMA_URL } from \"./org\";\n\nconst localized = {\n type: \"object\",\n additionalProperties: false,\n required: [\"fr\", \"en\"],\n properties: { fr: { type: \"string\", minLength: 1 }, en: { type: \"string\", minLength: 1 } },\n} as const;\nconst httpsUrl = { type: \"string\", format: \"uri\", pattern: \"^https://\" } as const;\nconst mark = {\n type: \"object\",\n additionalProperties: false,\n required: [\"svg\", \"png64\", \"png256\", \"png512\", \"png1024\"],\n properties: { svg: httpsUrl, png64: httpsUrl, png256: httpsUrl, png512: httpsUrl, png1024: httpsUrl },\n} as const;\nconst slug = { type: \"string\", pattern: \"^[a-z0-9]+(-[a-z0-9]+)*$\" } as const;\nconst themed = {\n type: \"object\",\n additionalProperties: false,\n required: [\"dark\", \"light\"],\n properties: { dark: mark, light: mark },\n} as const;\nconst date = { type: \"string\", pattern: \"^\\\\d{4}-\\\\d{2}-\\\\d{2}$\" } as const;\nconst semver = { type: \"string\", pattern: \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\" } as const;\n\nconst defaultItems = {\n type: \"array\",\n minItems: 1,\n uniqueItems: true,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"alt\", \"urls\"],\n properties: {\n id: slug,\n alt: localized,\n disabled: { const: true },\n urls: {\n type: \"object\",\n additionalProperties: false,\n required: [\"webp\"],\n properties: {\n svg: httpsUrl,\n webp: {\n type: \"object\",\n minProperties: 1,\n propertyNames: { pattern: \"^\\\\d+$\" },\n additionalProperties: httpsUrl,\n },\n },\n },\n },\n },\n} as const;\n\n/** The JSON Schema of `org/v1/org.json`. Nothing outside it is allowed (`additionalProperties: false` everywhere): a new fact is a new line here first. */\nexport const orgSchema = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n $id: ORG_SCHEMA_URL,\n title: \"Krizaka organisation — public facts\",\n type: \"object\",\n additionalProperties: false,\n required: [\n \"$schema\",\n \"schemaVersion\",\n \"version\",\n \"updatedAt\",\n \"company\",\n \"brand\",\n \"people\",\n \"defaults\",\n \"products\",\n \"sites\",\n \"family\",\n \"contact\",\n \"footer\",\n ],\n properties: {\n $schema: { type: \"string\" },\n schemaVersion: { enum: [1, 2] },\n version: semver,\n updatedAt: date,\n company: {\n type: \"object\",\n additionalProperties: false,\n required: [\"legalName\", \"tradeName\", \"neq\", \"city\", \"region\", \"country\", \"license\", \"madeIn\"],\n properties: {\n legalName: { type: \"string\", minLength: 1 },\n tradeName: { type: \"string\", minLength: 1 },\n neq: { type: \"string\", pattern: \"^\\\\d{10}$\" },\n city: { type: \"string\", minLength: 1 },\n region: { type: \"string\", minLength: 1 },\n country: { type: \"string\", pattern: \"^[A-Z]{2}$\" },\n license: { type: \"string\", minLength: 1 },\n madeIn: localized,\n },\n },\n brand: {\n type: \"object\",\n additionalProperties: false,\n required: [\"name\", \"logo\", \"mark\", \"favicon\", \"appleTouchIcon\", \"socialPreview\", \"manifest\"],\n properties: {\n name: { type: \"string\", minLength: 1 },\n logo: themed,\n mark: themed,\n favicon: httpsUrl,\n appleTouchIcon: httpsUrl,\n socialPreview: httpsUrl,\n manifest: httpsUrl,\n },\n },\n people: {\n type: \"object\",\n additionalProperties: false,\n required: [\"defaults\", \"banners\"],\n properties: {\n defaults: {\n type: \"array\",\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"kind\", \"svg\", \"webp256\", \"webp512\", \"alt\"],\n properties: {\n id: slug,\n kind: { enum: [\"person\", \"plain\"] },\n svg: httpsUrl,\n webp256: httpsUrl,\n webp512: httpsUrl,\n alt: localized,\n },\n },\n },\n banners: {\n type: \"array\",\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"url\", \"alt\"],\n properties: { id: slug, url: httpsUrl, alt: localized },\n },\n },\n },\n },\n defaults: {\n type: \"object\",\n additionalProperties: false,\n required: [\"version\", \"base\", \"rule\", \"kinds\"],\n properties: {\n version: { type: \"string\", pattern: \"^v\\\\d+$\" },\n base: httpsUrl,\n rule: {\n type: \"object\",\n additionalProperties: false,\n required: [\"pick\", \"description\"],\n properties: { pick: { const: \"fnv1a32-modulo\" }, description: { type: \"string\", minLength: 1 } },\n },\n kinds: {\n type: \"object\",\n additionalProperties: false,\n required: [\"person\", \"folder\", \"organisation\", \"shop\", \"banner\"],\n properties: Object.fromEntries(\n [\"person\", \"folder\", \"organisation\", \"shop\", \"banner\"].map((kind) => [kind, defaultItems]),\n ),\n },\n },\n },\n products: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"name\", \"status\", \"url\", \"repo\"],\n properties: {\n id: slug,\n name: { type: \"string\", minLength: 1 },\n status: { enum: [\"development\", \"devPreview\"] },\n url: httpsUrl,\n repo: httpsUrl,\n },\n },\n },\n sites: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"name\", \"url\"],\n properties: { id: slug, name: { type: \"string\", minLength: 1 }, url: httpsUrl },\n },\n },\n family: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"name\", \"short\", \"group\", \"status\", \"url\", \"repo\"],\n properties: {\n id: slug,\n name: { type: \"string\", minLength: 1 },\n short: { type: \"string\", minLength: 1 },\n group: { enum: [\"krizaka\", \"products\", \"open-source\", \"github\"] },\n status: { enum: [\"released\", \"development\"] },\n releasedAt: { type: \"string\", pattern: \"^\\\\d{4}-\\\\d{2}-\\\\d{2}$\" },\n url: httpsUrl,\n repo: { anyOf: [httpsUrl, { type: \"null\" }] },\n },\n },\n },\n contact: {\n type: \"object\",\n additionalProperties: false,\n required: [\"page\", \"email\"],\n properties: {\n page: {\n type: \"object\",\n additionalProperties: false,\n required: [\"fr\", \"en\"],\n properties: { fr: httpsUrl, en: httpsUrl },\n },\n email: { type: [\"string\", \"null\"], format: \"email\" },\n },\n },\n footer: {\n type: \"object\",\n additionalProperties: false,\n required: [\"line\", \"legal\"],\n properties: {\n line: localized,\n legal: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"label\", \"url\"],\n properties: {\n id: { enum: [\"privacy\", \"terms\"] },\n label: localized,\n url: {\n type: \"object\",\n additionalProperties: false,\n required: [\"fr\", \"en\"],\n properties: { fr: httpsUrl, en: httpsUrl },\n },\n },\n },\n },\n },\n },\n },\n} as const;\n\n/** The JSON Schema of `apps/<product>.json`. */\nexport const appSchema = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n $id: `${CDN}/org/v1/app.schema.json`,\n title: \"Krizaka mobile app — public runtime config\",\n type: \"object\",\n additionalProperties: false,\n required: [\"$schema\", \"schemaVersion\", \"app\", \"apiBaseUrl\", \"features\", \"minAppVersion\", \"updatedAt\"],\n properties: {\n $schema: { type: \"string\" },\n schemaVersion: { const: 1 },\n app: slug,\n apiBaseUrl: {\n type: \"object\",\n additionalProperties: false,\n required: [\"dev\", \"production\"],\n properties: { dev: { anyOf: [httpsUrl, { type: \"null\" }] }, production: { anyOf: [httpsUrl, { type: \"null\" }] } },\n },\n features: { type: \"object\", additionalProperties: { type: \"boolean\" } },\n minAppVersion: semver,\n updatedAt: date,\n },\n} as const;\n","export { APP_SCHEMA_URL, apps } from \"./apps\";\nexport type { BrandKind, CodeNameHit, OrgBrand } from \"./brands\";\nexport {\n brandOf,\n brands,\n catalogueValues,\n CODE_NAMES,\n codeNameMap,\n DISPLAY_NAME_MAX,\n displayName,\n findCodeNames,\n lockup,\n visibleText,\n} from \"./brands\";\nexport type { CastPersona, CastProduct, CastRole } from \"./cast\";\nexport { CAST, CAST_VERSION, castMedia, castOf, persona, personaByRole, seedFingerprint } from \"./cast\";\nexport { DEFAULT_KINDS, defaultFor, defaults, defaultUrl, fetchDefaults, listDefaults, seedHash } from \"./defaults\";\nexport { CDN, org, ORG_SCHEMA_URL, ORG_URL } from \"./org\";\nexport type {\n AppConfig,\n AppEnvironment,\n FamilyEntry,\n FamilyGroup,\n FamilyStatus,\n Localized,\n Org,\n OrgAvatar,\n OrgBanner,\n OrgDefaultItem,\n OrgDefaultKind,\n OrgDefaults,\n OrgMark,\n OrgProduct,\n OrgSite,\n ProductStatus,\n} from \"./org.types\";\nexport { appSchema, orgSchema } from \"./schema\";\n\nimport { org } from \"./org\";\nimport type { Localized } from \"./org.types\";\n\n/** The text of a localized pair for a language (`fr` or `en`; anything else reads English). */\nexport const localized = (text: Localized, locale: string): string => (locale === \"fr\" ? text.fr : text.en);\n\n/** The footer line of the family, « Une entreprise de Technologies Krizaka · Fait à Montréal ». */\nexport const footerLine = (locale: string): string => localized(org.footer.line, locale);\n\n/** A name of the family by id (`familyName(\"ts\")` → « Krizaka TypeScript »): the only way a site writes one. */\nexport const familyEntry = (id: string) => {\n const entry = org.family.find((e) => e.id === id);\n if (!entry) throw new Error(`Unknown Krizaka family entry \"${id}\".`);\n return entry;\n};\nexport const familyName = (id: string): string => familyEntry(id).name;\n"],"mappings":";AAAA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,UAAY;AAAA,EACZ,MAAQ;AAAA,EACR,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,WAAa;AAAA,EACf;AAAA,EACA,SAAW;AAAA,EACX,QAAU;AAAA,EACV,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,QAAU;AAAA,EACV,OAAS;AAAA,EACT,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,IACZ;AAAA,IACA,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,EACpB;AAAA,EACA,KAAO;AAAA,IACL,sBAAsB;AAAA,EACxB;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,aAAe;AAAA,EACf,SAAW;AAAA,IACT,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,OAAS;AAAA,IACT,eAAe;AAAA,IACf,gBAAkB;AAAA,EACpB;AAAA,EACA,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,iBAAmB;AAAA,IACjB,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,KAAO;AAAA,IACP,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,QAAU;AAAA,EACZ;AACF;;;AC9DA,IAAM,OAAO;AAGN,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,QAAmD;AAAA,EACvD,QAAQ,CAAC,KAAK,KAAK,IAAI;AAAA,EACvB,QAAQ,CAAC,KAAK,KAAK,IAAI;AAAA,EACvB,cAAc,CAAC,KAAK,KAAK,IAAI;AAAA,EAC7B,MAAM,CAAC,KAAK,KAAK,IAAI;AAAA,EACrB,QAAQ,CAAC,KAAK,IAAI;AACpB;AAGO,IAAM,oBAAyC,oBAAI,IAAI,CAAC,0BAA0B,CAAC;AAE1F,IAAM,OAAO,CAAC,MAAsB,IAAY,KAAgB,WAAoC;AAAA,EAClG;AAAA,EACA;AAAA,EACA,GAAI,kBAAkB,IAAI,GAAG,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,KAAc,IAAI,CAAC;AAAA,EAC5E,MAAM;AAAA,IACJ,GAAI,QAAQ,EAAE,KAAK,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,IACpD,MAAM,OAAO,YAAY,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,OAAO,CAAC,CAAC;AAAA,EAC1G;AACF;AAEA,IAAM,QAAQ,CAAC,MAAsB,IAAY,QAC/C,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAAM,KAAK,MAAM,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC;AAGpF,IAAM,SAAgC;AAAA,EACpC;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AACF;AAGA,IAAM,UAAiC;AAAA,EACrC;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AACF;AAEA,IAAM,YAAY;AAAA,EAChB,QAAQ,CAAC,OAA0B;AAAA,IACjC,IAAI,+CAA+C,CAAC;AAAA,IACpD,IAAI,0DAAuD,CAAC;AAAA,EAC9D;AAAA,EACA,QAAQ,CAAC,OAA0B;AAAA,IACjC,IAAI,0CAA0C,CAAC;AAAA,IAC/C,IAAI,uDAAoD,CAAC;AAAA,EAC3D;AAAA,EACA,cAAc,CAAC,OAA0B;AAAA,IACvC,IAAI,kDAAkD,CAAC;AAAA,IACvD,IAAI,4DAAyD,CAAC;AAAA,EAChE;AAAA,EACA,MAAM,CAAC,OAA0B;AAAA,IAC/B,IAAI,4CAA4C,CAAC;AAAA,IACjD,IAAI,2DAAwD,CAAC;AAAA,EAC/D;AACF;AAGO,IAAM,WAAwB;AAAA,EACnC,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,OAAO;AAAA,IACL,QAAQ;AAAA,MACN,GAAG,MAAM,UAAU,cAAc,UAAU,MAAM;AAAA,MACjD,GAAG,OAAO,IAAI,CAAC,CAAC,IAAI,GAAG,MAAM,KAAK,UAAU,IAAI,KAAK,KAAK,CAAC;AAAA,IAC7D;AAAA,IACA,QAAQ,MAAM,UAAU,UAAU,UAAU,MAAM;AAAA,IAClD,cAAc,MAAM,gBAAgB,gBAAgB,UAAU,YAAY;AAAA,IAC1E,MAAM,MAAM,QAAQ,QAAQ,UAAU,IAAI;AAAA,IAC1C,QAAQ,QAAQ,IAAI,CAAC,CAAC,IAAI,GAAG,MAAM,KAAK,UAAU,IAAI,KAAK,KAAK,CAAC;AAAA,EACnE;AACF;AAKO,SAAS,SAAS,MAA+B;AACtD,MAAI,IAAI;AACR,aAAW,MAAM,OAAO,IAAI,GAAG;AAC7B,SAAK,GAAG,YAAY,CAAC,KAAK;AAC1B,QAAI,KAAK,KAAK,GAAG,QAAU,MAAM;AAAA,EACnC;AACA,SAAO;AACT;AAGO,SAAS,aAAa,MAAsB,SAAsB,UAAqC;AAC5G,UAAQ,OAAO,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,CAAC,UAAU,MAAM,aAAa,IAAI;AAC7E;AAGO,SAAS,WACd,MACA,MACA,SAAsB,UACM;AAC5B,QAAM,QAAQ,aAAa,MAAM,MAAM;AACvC,SAAO,MAAM,WAAW,IAAI,SAAY,MAAM,SAAS,IAAI,IAAI,MAAM,MAAM;AAC7E;AAGO,SAAS,WAAW,OAAuB,MAAc,SAAyB,QAAgB;AACvG,MAAI,WAAW,SAAS,MAAM,KAAK,IAAK,QAAO,MAAM,KAAK;AAC1D,QAAM,QAAQ,OAAO,KAAK,MAAM,KAAK,IAAI,EACtC,IAAI,MAAM,EACV,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACvB,QAAM,SAAS,MAAM,KAAK,CAAC,MAAM,KAAK,IAAI,KAAK,MAAM,MAAM,SAAS,CAAC;AACrE,SAAO,MAAM,KAAK,KAAK,OAAO,MAAM,CAAC,KAAK;AAC5C;AAGA,eAAsB,cAAc,KAAa,YAA0B,OAA6B;AACtG,QAAM,MAAM,MAAM,UAAU,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;AAC5E,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,GAAG,GAAG,aAAa,IAAI,MAAM,EAAE;AAC5D,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,CAAC,KAAK,SAAU,OAAM,IAAI,MAAM,GAAG,GAAG,8BAA8B;AACxE,SAAO,KAAK;AACd;;;ACtSO,IAAM,MAAM;AACZ,IAAM,UAAU,GAAG,GAAG;AACtB,IAAM,iBAAiB,GAAG,GAAG;AAEpC,IAAM,MAAM,CAAC,SAAiB,GAAG,GAAG,IAAI,IAAI;AAE5C,IAAM,OAAO,CAAC,MAAuB,WAAsC;AAAA,EACzE,KAAK,IAAI,iBAAiB,IAAI,IAAI,KAAK,MAAM;AAAA,EAC7C,OAAO,IAAI,iBAAiB,IAAI,IAAI,KAAK,SAAS;AAAA,EAClD,QAAQ,IAAI,iBAAiB,IAAI,IAAI,KAAK,UAAU;AAAA,EACpD,QAAQ,IAAI,iBAAiB,IAAI,IAAI,KAAK,UAAU;AAAA,EACpD,SAAS,IAAI,iBAAiB,IAAI,IAAI,KAAK,WAAW;AACxD;AAEA,IAAM,QAAQ,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE/B,IAAM,YAAY,CAAC,MAA0B,MAC3C,SAAS,WACL;AAAA,EACE,IAAI,sDAAmD,CAAC;AAAA,EACxD,IAAI,6CAA6C,CAAC;AACpD,IACA;AAAA,EACE,IAAI,sDAAmD,CAAC;AAAA,EACxD,IAAI,6CAA6C,CAAC;AACpD;AAGN,IAAMA,YAAyB,CAAC,UAAU,OAAO,EAAY;AAAA,EAAQ,CAAC,SACpE,MAAM,IAAI,CAAC,OAAO;AAAA,IAChB,IAAI,GAAG,IAAI,IAAI,CAAC;AAAA,IAChB;AAAA,IACA,KAAK,IAAI,8BAA8B,IAAI,IAAI,CAAC,MAAM;AAAA,IACtD,SAAS,IAAI,8BAA8B,IAAI,IAAI,CAAC,WAAW;AAAA,IAC/D,SAAS,IAAI,8BAA8B,IAAI,IAAI,CAAC,WAAW;AAAA,IAC/D,KAAK,UAAU,MAAM,CAAC;AAAA,EACxB,EAAE;AACJ;AAcA,IAAM,SAAS;AACf,IAAM,KAAK,CAAC,SAAiB,GAAG,MAAM,IAAI,IAAI;AAG9C,IAAM,cAA2B;AAAA,EAC/B,CAAC,WAAW,WAAW,WAAW,WAAW,YAAY,2BAA2B,GAAG,aAAa,CAAC;AAAA,EACrG,CAAC,QAAQ,QAAQ,QAAQ,WAAW,YAAY,4BAA4B,GAAG,cAAc,CAAC;AAAA,EAC9F,CAAC,WAAW,WAAW,WAAW,YAAY,eAAe,2BAA2B,GAAG,SAAS,CAAC;AAAA,EACrG,CAAC,YAAY,YAAY,YAAY,YAAY,eAAe,4BAA4B,GAAG,UAAU,CAAC;AAAA,EAC1G,CAAC,YAAY,YAAY,YAAY,YAAY,eAAe,4BAA4B,GAAG,UAAU,CAAC;AAAA,EAC1G,CAAC,MAAM,cAAc,MAAM,eAAe,eAAe,0BAA0B,GAAG,YAAY,CAAC;AAAA,EACnG,CAAC,QAAQ,gBAAgB,QAAQ,eAAe,eAAe,4BAA4B,GAAG,cAAc,CAAC;AAAA,EAC7G,CAAC,MAAM,sBAAsB,cAAc,eAAe,eAAe,0BAA0B,GAAG,YAAY,CAAC;AAAA,EACnH,CAAC,OAAO,eAAe,OAAO,eAAe,eAAe,2BAA2B,GAAG,aAAa,CAAC;AAAA,EACxG,CAAC,UAAU,UAAU,UAAU,UAAU,YAAY,QAAQ,IAAI;AACnE;AAEA,IAAM,SAAwB,YAAY,IAAI,CAAC,CAAC,IAAI,MAAM,OAAO,OAAO,QAAQ,KAAK,IAAI,OAAO;AAAA,EAC9F;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE;AAEK,IAAM,MAAW;AAAA,EACtB,SAAS;AAAA,EACT,eAAe;AAAA,EACf,SAAS,gBAAI;AAAA,EACb,WAAW;AAAA,EACX,SAAS;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ,EAAE,IAAI,yBAAmB,IAAI,sBAAmB;AAAA,EAC1D;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,EAAE,MAAM,KAAK,QAAQ,MAAM,GAAG,OAAO,KAAK,QAAQ,OAAO,EAAE;AAAA,IACjE,MAAM,EAAE,MAAM,KAAK,QAAQ,MAAM,GAAG,OAAO,KAAK,QAAQ,OAAO,EAAE;AAAA,IACjE,SAAS,IAAI,2BAA2B;AAAA,IACxC,gBAAgB,IAAI,oCAAoC;AAAA,IACxD,eAAe,IAAI,2CAA2C;AAAA,IAC9D,UAAU,IAAI,qBAAqB;AAAA,EACrC;AAAA,EACA,QAAQ;AAAA,IACN,UAAAA;AAAA;AAAA,IAEA,SAAS,CAAC;AAAA,EACZ;AAAA,EACA;AAAA,EACA,UAAU;AAAA,IACR;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,EAAE,IAAI,OAAO,MAAM,eAAe,KAAK,0BAA0B;AAAA,IACjE,EAAE,IAAI,MAAM,MAAM,cAAc,KAAK,yBAAyB;AAAA,IAC9D,EAAE,IAAI,QAAQ,MAAM,gBAAgB,KAAK,2BAA2B;AAAA,IACpE,EAAE,IAAI,MAAM,MAAM,sBAAsB,KAAK,yBAAyB;AAAA,IACtE,EAAE,IAAI,UAAU,MAAM,eAAe,KAAK,0BAA0B;AAAA,IACpE,EAAE,IAAI,QAAQ,MAAM,QAAQ,KAAK,2BAA2B;AAAA,EAC9D;AAAA,EACA;AAAA,EACA,SAAS;AAAA,IACP,MAAM,EAAE,IAAI,sCAAsC,IAAI,qCAAqC;AAAA,IAC3F,OAAO;AAAA,EACT;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,IACA,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,IAAI,sBAAmB,IAAI,UAAU;AAAA,QAC9C,KAAK,EAAE,IAAI,sCAAsC,IAAI,qCAAqC;AAAA,MAC5F;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,IAAI,cAAc,IAAI,QAAQ;AAAA,QACvC,KAAK,EAAE,IAAI,oCAAoC,IAAI,mCAAmC;AAAA,MACxF;AAAA,IACF;AAAA,EACF;AACF;;;ACpKO,IAAM,iBAAiB,GAAG,GAAG;AACpC,IAAM,UAAU;AAEhB,IAAM,MAAM,CAAC,IAAY,YAA+B;AAAA,EACtD,SAAS;AAAA,EACT,eAAe;AAAA,EACf,KAAK;AAAA;AAAA,EAEL,YAAY,EAAE,KAAK,QAAQ,YAAY,KAAK;AAAA,EAC5C,UAAU,CAAC;AAAA,EACX,eAAe;AAAA,EACf,WAAW;AACb;AAGO,IAAM,OAAkC;AAAA,EAC7C,SAAS,IAAI,WAAW,yBAAyB;AAAA,EACjD,UAAU,IAAI,YAAY,0BAA0B;AAAA,EACpD,UAAU,IAAI,YAAY,0BAA0B;AACtD;;;ACKA,IAAM,cAAc,EAAE,IAAI,cAAc,IAAI,cAAc;AAE1D,IAAM,QAAQ,CAAC,IAAY,gBAAwB,MAAiB,aAA4C;AAAA,EAC9G;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AACF;AAGO,IAAM,SAA8B;AAAA,EACzC,MAAM,YAAY,YAAY,WAAW;AAAA,IACvC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,EACP,CAAC;AAAA,EACD,MAAM,YAAY,YAAY,WAAW;AAAA,IACvC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,EACP,CAAC;AAAA,EACD,MAAM,WAAW,WAAW,WAAW;AAAA,IACrC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,EACP,CAAC;AAAA;AAAA,EAED,MAAM,UAAU,UAAU,WAAW,EAAE,MAAM,0BAA0B,KAAK,MAAM,MAAM,MAAM,KAAK,KAAK,CAAC;AAC3G;AAOO,IAAM,aAA+C,OAAO,OAAO;AAAA,EACxE,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AACb,CAAC;AAGM,IAAM,UAAU,CAAC,OAAyB;AAC/C,QAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC5C,MAAI,MAAO,QAAO;AAClB,QAAM,UAAU,WAAW,GAAG,YAAY,CAAC;AAC3C,MAAI,QAAS,OAAM,IAAI,MAAM,IAAI,EAAE,kEAAkE,OAAO,KAAK;AACjH,QAAM,IAAI,MAAM,0BAA0B,EAAE,IAAI;AAClD;AAIO,IAAM,mBAAmB;AAMzB,IAAM,cAAc,CAAC,IAAY,WAAmC;AACzE,QAAM,MAAM,QAAQ,KAAK,KAAK;AAC9B,MAAI,IAAI,WAAW,KAAK,IAAI,SAAS,oBAAoB,cAAc,GAAG,EAAE,SAAS;AACnF,WAAO,QAAQ,EAAE,EAAE;AACrB,SAAO;AACT;AAGO,IAAM,SAAS,CAAC,IAAY,QAAgB,WAAmC;AACpF,QAAM,EAAE,YAAY,IAAI,QAAQ,EAAE;AAClC,SAAO,GAAG,YAAY,IAAI,MAAM,CAAC,IAAI,WAAW,OAAO,YAAY,KAAK,YAAY,EAAE;AACxF;AAGO,IAAM,cAAc,MACzB,OAAO,YAAY,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,QAAQ,EAAE,EAAE,cAAc,CAAC,CAAC;AAGrG,IAAM,kBAA+C,CAAC,CAAC,uBAAuB,QAAQ,CAAC;AAGvF,IAAM,kBAAkB,MAAM,IAAI,OAAO,IAAI,OAAO,KAAK,UAAU,EAAE,KAAK,GAAG,CAAC,KAAK,IAAI;AAYvF,IAAM,gBAAgB,CAAC,SAAyB;AAC9C,QAAM,KAAK,WAAW,KAAK,YAAY,CAAC,KAAK;AAC7C,MAAI,SAAS,KAAK,YAAY,EAAG,QAAO,GAAG,YAAY;AACvD,MAAI,KAAK,WAAW,KAAK,OAAO,CAAC,EAAE,YAAY,CAAC,EAAG,QAAO,QAAQ,EAAE,EAAE;AACtE,SAAO;AACT;AAOO,IAAM,gBAAgB,CAAC,SAAgC;AAC5D,QAAM,OAAsB,CAAC;AAC7B,QAAM,SAAS,CAAC,GAAW,MACzB,KACG,MAAM,KAAK,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,EACrC,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACV,aAAW,KAAK,KAAK,SAAS,gBAAgB,CAAC,GAAG;AAChD,SAAK,KAAK,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,cAAc,EAAE,CAAC,CAAC,GAAG,SAAS,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAAA,EAC3F;AACA,aAAW,CAAC,IAAI,GAAG,KAAK,iBAAiB;AACvC,eAAW,KAAK,KAAK,SAAS,EAAE,EAAG,MAAK,KAAK,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,SAAS,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAAA,EACzG;AACA,SAAO;AACT;AAGA,IAAM,cAAc,CAAC,MAAc,MAAc,UAA0B;AACzE,MAAI,MAAM;AACV,MAAI,KAAK;AACT,aAAS;AACP,UAAM,QAAQ,KAAK,QAAQ,MAAM,EAAE;AACnC,QAAI,QAAQ,EAAG,QAAO,MAAM,KAAK,MAAM,EAAE;AACzC,WAAO,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC;AAC/B,UAAM,MAAM,KAAK,QAAQ,OAAO,QAAQ,KAAK,MAAM;AACnD,QAAI,MAAM,EAAG,QAAO;AACpB,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;AAEA,IAAM,mBAAmB,CAAC,UAAU,SAAS,OAAO,QAAQ,KAAK;AAEjE,IAAM,YAAY,CAAC,OAAe,MAAc,OAAuB;AACrE,WAAS,IAAI,MAAM,QAAQ,IAAI,IAAI,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,MAAM,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG;AACxF,QAAI,CAAC,YAAY,KAAK,MAAM,IAAI,KAAK,SAAS,CAAC,KAAK,GAAG,EAAG,QAAO;AAAA,EACnE;AACA,SAAO;AACT;AAEA,IAAM,cAAc,CAAC,OAAe,OAAiC;AACnE,MAAI,QAA0B,CAAC,IAAI,EAAE;AACrC,aAAW,QAAQ,kBAAkB;AACnC,UAAM,IAAI,UAAU,OAAO,MAAM,EAAE;AACnC,QAAI,KAAK,MAAM,MAAM,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC,GAAI,SAAQ,CAAC,GAAG,IAAI;AAAA,EAChE;AACA,SAAO;AACT;AAEA,IAAM,YAAY,CAAC,SAAyB;AAC1C,MAAI,MAAM;AACV,MAAI,KAAK;AACT,WAAS,OAAO,KAAK,QAAQ,GAAG,GAAG,QAAQ,GAAG,OAAO,KAAK,QAAQ,KAAK,EAAE,GAAG;AAC1E,UAAM,QAAQ,KAAK,QAAQ,KAAK,OAAO,CAAC;AACxC,QAAI,QAAQ,EAAG;AACf,WAAO,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC;AAC9B,SAAK,QAAQ;AAAA,EACf;AACA,SAAO,MAAM,KAAK,MAAM,EAAE;AAC5B;AAEA,IAAM,gBAAgB,CAAC,SAAyB;AAC9C,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,MAAM;AACV,MAAI,KAAK;AACT,SAAO,KAAK,KAAK,QAAQ;AACvB,UAAM,CAAC,MAAM,GAAG,IAAI,YAAY,OAAO,EAAE;AACzC,QAAI,OAAO,EAAG,QAAO,MAAM,KAAK,MAAM,EAAE;AACxC,WAAO,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC;AAC9B,UAAM,MAAM,MAAM,QAAQ,KAAK,GAAG,KAAK,IAAI;AAC3C,QAAI,MAAM,EAAG,QAAO;AACpB,SAAK,MAAM,IAAI,SAAS;AAAA,EAC1B;AACA,SAAO;AACT;AAOO,IAAM,cAAc,CAAC,SAAyB;AACnD,QAAM,QAAkB,CAAC;AACzB,aAAW,KAAK,KAAK,SAAS,iBAAiB,GAAG;AAChD,QACE,0HAA0H;AAAA,MACxH,EAAE,CAAC;AAAA,IACL,GACA;AACA,YAAM,UAAU,uDAAuD,KAAK,EAAE,CAAC,CAAC;AAChF,UAAI,QAAS,OAAM,KAAK,QAAQ,CAAC,KAAK,QAAQ,CAAC,KAAK,EAAE;AAAA,IACxD;AAAA,EACF;AACA,aAAW,KAAK,KAAK,SAAS,8CAA8C,EAAG,OAAM,KAAK,EAAE,CAAC,KAAK,EAAE;AACpG,QAAM,OAAO,UAAU,cAAc,YAAY,MAAM,QAAQ,KAAK,CAAC,CAAC,EACnE,WAAW,UAAU,GAAG,EACxB,WAAW,SAAS,GAAG;AAC1B,SAAO,CAAC,MAAM,GAAG,KAAK,EAAE,KAAK,IAAI;AACnC;AAMO,IAAM,kBAAkB,CAAC,WAAoB,OAAO,OAA2B;AACpF,MAAI,OAAO,cAAc,SAAU,QAAO,CAAC,CAAC,MAAM,SAAS,CAAC;AAC5D,MAAI,MAAM,QAAQ,SAAS,EAAG,QAAO,UAAU,QAAQ,CAAC,GAAG,MAAM,gBAAgB,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;AACpG,MAAI,aAAa,OAAO,cAAc,UAAU;AAC9C,WAAO,OAAO,QAAQ,SAAS,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,gBAAgB,GAAG,OAAO,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;AAAA,EACpG;AACA,SAAO,CAAC;AACV;;;ACxNO,IAAM,eAAe;AAErB,IAAM,OAA+B;AAAA;AAAA,EAE1C;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AACF;AAGO,IAAM,SAAS,CAAC,YAAiD,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,OAAO;AAGzG,SAAS,QAAQ,SAAsB,IAAyB;AACrE,QAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,YAAY,WAAW,EAAE,OAAO,EAAE;AACnE,MAAI,CAAC;AACH,UAAM,IAAI;AAAA,MACR,qBAAqB,EAAE,QAAQ,OAAO,YAAY,OAAO,OAAO,EAC7D,IAAI,CAAC,MAAM,EAAE,EAAE,EACf,KAAK,IAAI,CAAC;AAAA,IACf;AACF,SAAO;AACT;AAGO,SAAS,cAAc,SAAsB,MAA6B;AAC/E,QAAM,QAAQ,OAAO,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACzD,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,YAAY,IAAI,OAAO,OAAO,EAAE;AAC5D,SAAO;AACT;AAEA,IAAM,QAAQ,CAAC,MAA2B,IAAY,SAAyB;AAC7E,QAAM,QAAoC,aAAa,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACpF,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,YAAY,IAAI,aAAa,EAAE,uBAAuB;AAClF,SAAO,WAAW,OAAO,IAAI;AAC/B;AAGO,SAAS,UAAU,GAAgB,OAAO,KAA0C;AACzF,SAAO,EAAE,QAAQ,MAAM,UAAU,EAAE,QAAQ,IAAI,GAAG,GAAI,EAAE,SAAS,EAAE,QAAQ,MAAM,UAAU,EAAE,QAAQ,GAAG,EAAE,IAAI,CAAC,EAAG;AACpH;AAMO,SAAS,gBAAgB,QAAkD;AAChF,SAAO,OAAO,KAAK,MAAM,EACtB,KAAK,CAAC,GAAG,MAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE,EAC3C,IAAI,CAAC,UAAU,GAAG,KAAK,IAAI,OAAO,KAAK,CAAC,EAAE,EAC1C,KAAK,GAAG;AACb;;;AC5NA,IAAM,YAAY;AAAA,EAChB,MAAM;AAAA,EACN,sBAAsB;AAAA,EACtB,UAAU,CAAC,MAAM,IAAI;AAAA,EACrB,YAAY,EAAE,IAAI,EAAE,MAAM,UAAU,WAAW,EAAE,GAAG,IAAI,EAAE,MAAM,UAAU,WAAW,EAAE,EAAE;AAC3F;AACA,IAAM,WAAW,EAAE,MAAM,UAAU,QAAQ,OAAO,SAAS,YAAY;AACvE,IAAMC,QAAO;AAAA,EACX,MAAM;AAAA,EACN,sBAAsB;AAAA,EACtB,UAAU,CAAC,OAAO,SAAS,UAAU,UAAU,SAAS;AAAA,EACxD,YAAY,EAAE,KAAK,UAAU,OAAO,UAAU,QAAQ,UAAU,QAAQ,UAAU,SAAS,SAAS;AACtG;AACA,IAAM,OAAO,EAAE,MAAM,UAAU,SAAS,2BAA2B;AACnE,IAAM,SAAS;AAAA,EACb,MAAM;AAAA,EACN,sBAAsB;AAAA,EACtB,UAAU,CAAC,QAAQ,OAAO;AAAA,EAC1B,YAAY,EAAE,MAAMA,OAAM,OAAOA,MAAK;AACxC;AACA,IAAM,OAAO,EAAE,MAAM,UAAU,SAAS,yBAAyB;AACjE,IAAM,SAAS,EAAE,MAAM,UAAU,SAAS,uBAAuB;AAEjE,IAAM,eAAe;AAAA,EACnB,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AAAA,EACb,OAAO;AAAA,IACL,MAAM;AAAA,IACN,sBAAsB;AAAA,IACtB,UAAU,CAAC,MAAM,OAAO,MAAM;AAAA,IAC9B,YAAY;AAAA,MACV,IAAI;AAAA,MACJ,KAAK;AAAA,MACL,UAAU,EAAE,OAAO,KAAK;AAAA,MACxB,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,sBAAsB;AAAA,QACtB,UAAU,CAAC,MAAM;AAAA,QACjB,YAAY;AAAA,UACV,KAAK;AAAA,UACL,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,eAAe;AAAA,YACf,eAAe,EAAE,SAAS,SAAS;AAAA,YACnC,sBAAsB;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,YAAY;AAAA,EACvB,SAAS;AAAA,EACT,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AAAA,EACN,sBAAsB;AAAA,EACtB,UAAU;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,SAAS,EAAE,MAAM,SAAS;AAAA,IAC1B,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;AAAA,IAC9B,SAAS;AAAA,IACT,WAAW;AAAA,IACX,SAAS;AAAA,MACP,MAAM;AAAA,MACN,sBAAsB;AAAA,MACtB,UAAU,CAAC,aAAa,aAAa,OAAO,QAAQ,UAAU,WAAW,WAAW,QAAQ;AAAA,MAC5F,YAAY;AAAA,QACV,WAAW,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,QAC1C,WAAW,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,QAC1C,KAAK,EAAE,MAAM,UAAU,SAAS,YAAY;AAAA,QAC5C,MAAM,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,QACrC,QAAQ,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,QACvC,SAAS,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,QACjD,SAAS,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,QACxC,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,sBAAsB;AAAA,MACtB,UAAU,CAAC,QAAQ,QAAQ,QAAQ,WAAW,kBAAkB,iBAAiB,UAAU;AAAA,MAC3F,YAAY;AAAA,QACV,MAAM,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,QACrC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,eAAe;AAAA,QACf,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,sBAAsB;AAAA,MACtB,UAAU,CAAC,YAAY,SAAS;AAAA,MAChC,YAAY;AAAA,QACV,UAAU;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,YACL,MAAM;AAAA,YACN,sBAAsB;AAAA,YACtB,UAAU,CAAC,MAAM,QAAQ,OAAO,WAAW,WAAW,KAAK;AAAA,YAC3D,YAAY;AAAA,cACV,IAAI;AAAA,cACJ,MAAM,EAAE,MAAM,CAAC,UAAU,OAAO,EAAE;AAAA,cAClC,KAAK;AAAA,cACL,SAAS;AAAA,cACT,SAAS;AAAA,cACT,KAAK;AAAA,YACP;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,OAAO;AAAA,YACL,MAAM;AAAA,YACN,sBAAsB;AAAA,YACtB,UAAU,CAAC,MAAM,OAAO,KAAK;AAAA,YAC7B,YAAY,EAAE,IAAI,MAAM,KAAK,UAAU,KAAK,UAAU;AAAA,UACxD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,sBAAsB;AAAA,MACtB,UAAU,CAAC,WAAW,QAAQ,QAAQ,OAAO;AAAA,MAC7C,YAAY;AAAA,QACV,SAAS,EAAE,MAAM,UAAU,SAAS,UAAU;AAAA,QAC9C,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,sBAAsB;AAAA,UACtB,UAAU,CAAC,QAAQ,aAAa;AAAA,UAChC,YAAY,EAAE,MAAM,EAAE,OAAO,iBAAiB,GAAG,aAAa,EAAE,MAAM,UAAU,WAAW,EAAE,EAAE;AAAA,QACjG;AAAA,QACA,OAAO;AAAA,UACL,MAAM;AAAA,UACN,sBAAsB;AAAA,UACtB,UAAU,CAAC,UAAU,UAAU,gBAAgB,QAAQ,QAAQ;AAAA,UAC/D,YAAY,OAAO;AAAA,YACjB,CAAC,UAAU,UAAU,gBAAgB,QAAQ,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,YAAY,CAAC;AAAA,UAC3F;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,sBAAsB;AAAA,QACtB,UAAU,CAAC,MAAM,QAAQ,UAAU,OAAO,MAAM;AAAA,QAChD,YAAY;AAAA,UACV,IAAI;AAAA,UACJ,MAAM,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,UACrC,QAAQ,EAAE,MAAM,CAAC,eAAe,YAAY,EAAE;AAAA,UAC9C,KAAK;AAAA,UACL,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,sBAAsB;AAAA,QACtB,UAAU,CAAC,MAAM,QAAQ,KAAK;AAAA,QAC9B,YAAY,EAAE,IAAI,MAAM,MAAM,EAAE,MAAM,UAAU,WAAW,EAAE,GAAG,KAAK,SAAS;AAAA,MAChF;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,sBAAsB;AAAA,QACtB,UAAU,CAAC,MAAM,QAAQ,SAAS,SAAS,UAAU,OAAO,MAAM;AAAA,QAClE,YAAY;AAAA,UACV,IAAI;AAAA,UACJ,MAAM,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,UACrC,OAAO,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,UACtC,OAAO,EAAE,MAAM,CAAC,WAAW,YAAY,eAAe,QAAQ,EAAE;AAAA,UAChE,QAAQ,EAAE,MAAM,CAAC,YAAY,aAAa,EAAE;AAAA,UAC5C,YAAY,EAAE,MAAM,UAAU,SAAS,yBAAyB;AAAA,UAChE,KAAK;AAAA,UACL,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,EAAE;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,sBAAsB;AAAA,MACtB,UAAU,CAAC,QAAQ,OAAO;AAAA,MAC1B,YAAY;AAAA,QACV,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,sBAAsB;AAAA,UACtB,UAAU,CAAC,MAAM,IAAI;AAAA,UACrB,YAAY,EAAE,IAAI,UAAU,IAAI,SAAS;AAAA,QAC3C;AAAA,QACA,OAAO,EAAE,MAAM,CAAC,UAAU,MAAM,GAAG,QAAQ,QAAQ;AAAA,MACrD;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,sBAAsB;AAAA,MACtB,UAAU,CAAC,QAAQ,OAAO;AAAA,MAC1B,YAAY;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,YACL,MAAM;AAAA,YACN,sBAAsB;AAAA,YACtB,UAAU,CAAC,MAAM,SAAS,KAAK;AAAA,YAC/B,YAAY;AAAA,cACV,IAAI,EAAE,MAAM,CAAC,WAAW,OAAO,EAAE;AAAA,cACjC,OAAO;AAAA,cACP,KAAK;AAAA,gBACH,MAAM;AAAA,gBACN,sBAAsB;AAAA,gBACtB,UAAU,CAAC,MAAM,IAAI;AAAA,gBACrB,YAAY,EAAE,IAAI,UAAU,IAAI,SAAS;AAAA,cAC3C;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,YAAY;AAAA,EACvB,SAAS;AAAA,EACT,KAAK,GAAG,GAAG;AAAA,EACX,OAAO;AAAA,EACP,MAAM;AAAA,EACN,sBAAsB;AAAA,EACtB,UAAU,CAAC,WAAW,iBAAiB,OAAO,cAAc,YAAY,iBAAiB,WAAW;AAAA,EACpG,YAAY;AAAA,IACV,SAAS,EAAE,MAAM,SAAS;AAAA,IAC1B,eAAe,EAAE,OAAO,EAAE;AAAA,IAC1B,KAAK;AAAA,IACL,YAAY;AAAA,MACV,MAAM;AAAA,MACN,sBAAsB;AAAA,MACtB,UAAU,CAAC,OAAO,YAAY;AAAA,MAC9B,YAAY,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,EAAE,GAAG,YAAY,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,EAAE,EAAE;AAAA,IAClH;AAAA,IACA,UAAU,EAAE,MAAM,UAAU,sBAAsB,EAAE,MAAM,UAAU,EAAE;AAAA,IACtE,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AACF;;;AC3OO,IAAMC,aAAY,CAAC,MAAiB,WAA4B,WAAW,OAAO,KAAK,KAAK,KAAK;AAGjG,IAAM,aAAa,CAAC,WAA2BA,WAAU,IAAI,OAAO,MAAM,MAAM;AAGhF,IAAM,cAAc,CAAC,OAAe;AACzC,QAAM,QAAQ,IAAI,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAChD,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iCAAiC,EAAE,IAAI;AACnE,SAAO;AACT;AACO,IAAM,aAAa,CAAC,OAAuB,YAAY,EAAE,EAAE;","names":["defaults","mark","localized"]}
|
package/dist/org.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://krizaka-assets.b-cdn.net/org/v1/org.schema.json",
|
|
3
3
|
"schemaVersion": 2,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"updatedAt": "2026-10-30",
|
|
6
6
|
"company": {
|
|
7
7
|
"legalName": "Technologies Krizaka Inc.",
|
|
@@ -899,25 +899,25 @@
|
|
|
899
899
|
},
|
|
900
900
|
"products": [
|
|
901
901
|
{
|
|
902
|
-
"id": "
|
|
903
|
-
"name": "
|
|
902
|
+
"id": "sovkora",
|
|
903
|
+
"name": "Sovkora",
|
|
904
904
|
"status": "development",
|
|
905
|
-
"url": "https://www.
|
|
906
|
-
"repo": "https://github.com/krizaka/
|
|
905
|
+
"url": "https://www.sovkora.com",
|
|
906
|
+
"repo": "https://github.com/krizaka/sovkora"
|
|
907
907
|
},
|
|
908
908
|
{
|
|
909
|
-
"id": "
|
|
910
|
-
"name": "
|
|
909
|
+
"id": "verikora",
|
|
910
|
+
"name": "Verikora",
|
|
911
911
|
"status": "development",
|
|
912
|
-
"url": "https://www.
|
|
913
|
-
"repo": "https://github.com/krizaka/
|
|
912
|
+
"url": "https://www.verikora.com",
|
|
913
|
+
"repo": "https://github.com/krizaka/verikora"
|
|
914
914
|
},
|
|
915
915
|
{
|
|
916
|
-
"id": "
|
|
917
|
-
"name": "
|
|
916
|
+
"id": "folioviv",
|
|
917
|
+
"name": "Folioviv",
|
|
918
918
|
"status": "development",
|
|
919
|
-
"url": "https://www.
|
|
920
|
-
"repo": "https://github.com/krizaka/
|
|
919
|
+
"url": "https://www.folioviv.com",
|
|
920
|
+
"repo": "https://github.com/krizaka/folioviv"
|
|
921
921
|
}
|
|
922
922
|
],
|
|
923
923
|
"sites": [
|
|
@@ -972,31 +972,31 @@
|
|
|
972
972
|
"repo": "https://github.com/krizaka/krizaka-blog"
|
|
973
973
|
},
|
|
974
974
|
{
|
|
975
|
-
"id": "
|
|
976
|
-
"name": "
|
|
977
|
-
"short": "
|
|
975
|
+
"id": "sovkora",
|
|
976
|
+
"name": "Sovkora",
|
|
977
|
+
"short": "Sovkora",
|
|
978
978
|
"group": "products",
|
|
979
979
|
"status": "development",
|
|
980
|
-
"url": "https://www.
|
|
981
|
-
"repo": "https://github.com/krizaka/
|
|
980
|
+
"url": "https://www.sovkora.com",
|
|
981
|
+
"repo": "https://github.com/krizaka/sovkora"
|
|
982
982
|
},
|
|
983
983
|
{
|
|
984
|
-
"id": "
|
|
985
|
-
"name": "
|
|
986
|
-
"short": "
|
|
984
|
+
"id": "verikora",
|
|
985
|
+
"name": "Verikora",
|
|
986
|
+
"short": "Verikora",
|
|
987
987
|
"group": "products",
|
|
988
988
|
"status": "development",
|
|
989
|
-
"url": "https://www.
|
|
990
|
-
"repo": "https://github.com/krizaka/
|
|
989
|
+
"url": "https://www.verikora.com",
|
|
990
|
+
"repo": "https://github.com/krizaka/verikora"
|
|
991
991
|
},
|
|
992
992
|
{
|
|
993
|
-
"id": "
|
|
994
|
-
"name": "
|
|
995
|
-
"short": "
|
|
993
|
+
"id": "folioviv",
|
|
994
|
+
"name": "Folioviv",
|
|
995
|
+
"short": "Folioviv",
|
|
996
996
|
"group": "products",
|
|
997
997
|
"status": "development",
|
|
998
|
-
"url": "https://www.
|
|
999
|
-
"repo": "https://github.com/krizaka/
|
|
998
|
+
"url": "https://www.folioviv.com",
|
|
999
|
+
"repo": "https://github.com/krizaka/folioviv"
|
|
1000
1000
|
},
|
|
1001
1001
|
{
|
|
1002
1002
|
"id": "ui",
|
|
@@ -1014,7 +1014,7 @@
|
|
|
1014
1014
|
"group": "open-source",
|
|
1015
1015
|
"status": "development",
|
|
1016
1016
|
"url": "https://java.krizaka.com",
|
|
1017
|
-
"repo": "https://github.com/krizaka/krizaka-
|
|
1017
|
+
"repo": "https://github.com/krizaka/krizaka-java"
|
|
1018
1018
|
},
|
|
1019
1019
|
{
|
|
1020
1020
|
"id": "ts",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@krizaka/org",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "The public facts about Krizaka, in one validated JSON that every footer, site and app reads: legal name, NEQ, « Fait à Montréal » in French and English, brand marks, default avatars and banners, the live products and sites, the public contact, the footer line and the mobile apps' public runtime config. Typed data, JSON Schema, and the files published on the CDN.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"krizaka",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"tsup": "^8.5.0",
|
|
53
53
|
"typescript": "^5.9.3",
|
|
54
54
|
"vitest": "^4.1.11",
|
|
55
|
-
"@krizaka/config": "^0.
|
|
55
|
+
"@krizaka/config": "^0.21.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsup && node scripts/emit.mjs",
|