@verbaly/studio 0.59.0 → 0.61.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/dist/cli.js +17 -15
- package/dist/cli.js.map +1 -1
- package/dist/index.js +17 -15
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/index-BWCfMFep.js +3 -0
- package/dist/ui/assets/index-BYjBNask.css +1 -0
- package/dist/ui/index.html +2 -2
- package/package.json +3 -3
- package/dist/ui/assets/index-7Azfonq_.css +0 -1
- package/dist/ui/assets/index-CH887S-p.js +0 -3
package/dist/cli.js
CHANGED
|
@@ -313,11 +313,24 @@ async function startTranslate(cfg, locales) {
|
|
|
313
313
|
const run = promisify(execFile);
|
|
314
314
|
const FIELD = "";
|
|
315
315
|
const FORMAT = `--format=%H${FIELD}%an${FIELD}%aI${FIELD}%s`;
|
|
316
|
+
function parseLog(stdout) {
|
|
317
|
+
const commits = [];
|
|
318
|
+
for (const line of stdout.split("\n")) {
|
|
319
|
+
const [sha, author, date, ...rest] = line.split(FIELD);
|
|
320
|
+
if (!sha || !author || !date || !rest.length) continue;
|
|
321
|
+
commits.push({
|
|
322
|
+
sha: sha.slice(0, 7),
|
|
323
|
+
author,
|
|
324
|
+
date,
|
|
325
|
+
subject: rest.join(FIELD)
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
return commits;
|
|
329
|
+
}
|
|
316
330
|
async function catalogHistory(cfg, limit = 5) {
|
|
317
331
|
const dir = relative(cfg.root, cfg.dir).replaceAll("\\", "/") || ".";
|
|
318
|
-
let stdout;
|
|
319
332
|
try {
|
|
320
|
-
stdout =
|
|
333
|
+
const { stdout } = await run("git", [
|
|
321
334
|
"log",
|
|
322
335
|
`-n${limit}`,
|
|
323
336
|
FORMAT,
|
|
@@ -327,22 +340,11 @@ async function catalogHistory(cfg, limit = 5) {
|
|
|
327
340
|
cwd: cfg.root,
|
|
328
341
|
timeout: 3e3,
|
|
329
342
|
windowsHide: true
|
|
330
|
-
})
|
|
343
|
+
});
|
|
344
|
+
return parseLog(stdout);
|
|
331
345
|
} catch {
|
|
332
346
|
return [];
|
|
333
347
|
}
|
|
334
|
-
const commits = [];
|
|
335
|
-
for (const line of stdout.split("\n")) {
|
|
336
|
-
const [sha, author, date, ...rest] = line.split(FIELD);
|
|
337
|
-
if (!sha || !author || !date) continue;
|
|
338
|
-
commits.push({
|
|
339
|
-
sha: sha.slice(0, 7),
|
|
340
|
-
author,
|
|
341
|
-
date,
|
|
342
|
-
subject: rest.join(FIELD)
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
return commits;
|
|
346
348
|
}
|
|
347
349
|
//#endregion
|
|
348
350
|
//#region src/assets.ts
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":["readJob"],"sources":["../src/http.ts","../src/triage.ts","../src/api.ts","../src/jobs.ts","../src/actions.ts","../src/history.ts","../src/assets.ts","../src/guard.ts","../src/server.ts","../src/cli.ts"],"sourcesContent":["// A client mistake is not a server fault, so the status rides with the error, not a blanket 500.\nexport class HttpError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message.startsWith('[verbaly]') ? message : `[verbaly] ${message}`);\n this.status = status;\n this.name = 'HttpError';\n }\n}\n\nexport const badRequest = (message: string) => new HttpError(400, message);\n\n// The absolute path of someone's project is not the browser's business.\nexport function scrub(message: string, root: string): string {\n return root ? message.split(root).join('.') : message;\n}\n","import type { Catalog } from '@verbaly/compiler';\n\nexport type TriageSignal = 'divergent' | 'collision' | 'echo' | 'digits' | 'code' | 'url';\n\nexport interface TriageReason {\n signal: TriageSignal;\n text: string;\n}\n\nexport type TriageResult = Record<string, TriageReason[]>;\n\n// check() already caught the structure, so these only point at the few worth reading first.\nexport interface TriageInput {\n source: Catalog;\n target: Catalog;\n reviewed: Catalog[];\n}\n\nconst DIGITS = /\\d[\\d.,]*/g;\nconst URLS = /https?:\\/\\/[^\\s<)\"']+/g;\nconst CODE = /<code>([^<]+)<\\/code>/g;\n\nfunction bag(text: string, re: RegExp, normalize?: (v: string) => string): string[] {\n const found = text.match(re) ?? [];\n return (normalize ? found.map(normalize) : found).sort();\n}\n\nfunction same(a: string[], b: string[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n\n// A number or a url at the end of a clause takes the punctuation with it, and that is not a signal.\nconst trimPunct = (v: string) => v.replace(/[.,;:!?)\\]]+$/, '');\n// A separator is idiomatic (3.09 is 3,09 in Spanish); canonizing keeps 1.5 apart from 15.\nconst bareDigits = (v: string) => trimPunct(v).replaceAll(/[.,]/g, '.');\n\nfunction push(out: TriageResult, key: string, reason: TriageReason): void {\n (out[key] ??= []).push(reason);\n}\n\nexport function triage({ source, target, reviewed }: TriageInput): TriageResult {\n // null-prototype: a source text of \"__proto__\" or \"toString\" is a string, not a member of Object\n const out: TriageResult = Object.create(null);\n const keys = Object.keys(source);\n\n // One source text that two humans rendered two ways is ambiguous, so the machine had no chance.\n const bySource: Record<string, string[]> = Object.create(null);\n for (const key of keys) {\n const text = source[key]?.trim();\n if (text) (bySource[text] ??= []).push(key);\n }\n for (const [text, group] of Object.entries(bySource)) {\n if (group.length < 2) continue;\n const divergent = reviewed.some(\n (catalog) => new Set(group.map((k) => catalog[k]?.trim() ?? '').filter(Boolean)).size > 1,\n );\n if (divergent) {\n for (const key of group) {\n push(out, key, { signal: 'divergent', text: `\"${text}\" was already translated two ways` });\n }\n }\n // The same ambiguity seen from the result instead of from the history.\n const targets = new Set(group.map((key) => target[key]?.trim() ?? '').filter(Boolean));\n if (!divergent && targets.size > 1) {\n for (const key of group) {\n push(out, key, { signal: 'collision', text: `\"${text}\" came back as two different translations` });\n }\n }\n }\n\n for (const key of keys) {\n const src = source[key]?.trim() ?? '';\n const trg = target[key]?.trim() ?? '';\n if (!src || !trg) continue;\n\n // Only the locales with an opinion on this key vote: alone it fires on every do-not-translate.\n const opinions = reviewed.map((c) => c[key]?.trim()).filter((v) => v !== undefined && v !== '');\n if (trg === src && opinions.length > 0 && opinions.every((v) => v !== src)) {\n push(out, key, { signal: 'echo', text: 'still identical to the source' });\n }\n\n // a translation that adds a number is idiomatic (\"refresh\" is \"F5\"); one that changes it is not\n const srcDigits = bag(src, DIGITS, bareDigits);\n if (srcDigits.length > 0 && !same(srcDigits, bag(trg, DIGITS, bareDigits))) {\n push(out, key, { signal: 'digits', text: 'the numbers do not match the source' });\n }\n if (!same(bag(src, URLS, trimPunct), bag(trg, URLS, trimPunct))) {\n push(out, key, { signal: 'url', text: 'a URL changed' });\n }\n if (!same(bag(src, CODE), bag(trg, CODE))) {\n push(out, key, { signal: 'code', text: 'the contents of a <code> span changed' });\n }\n }\n\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport {\n check,\n clearDrafts,\n collectOrigins,\n doctor,\n effectiveDrafts,\n extractProject,\n loadDrafts,\n markDrafts,\n readCatalog,\n saveDrafts,\n status,\n targetLocales,\n validateMessage,\n validatePair,\n writeCatalog,\n} from '@verbaly/compiler';\nimport { DRAFTS_FILE } from '@verbaly/compiler';\nimport type {\n Catalog,\n Catalogs,\n CheckResult,\n DoctorResult,\n Drafts,\n ResolvedConfig,\n StatusResult,\n} from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { triage, type TriageResult } from './triage';\n\nexport interface StudioProblem {\n scope: string;\n message: string;\n}\n\nexport interface StudioState {\n root: string;\n dir: string;\n sourceLocale: string;\n locales: string[];\n scanning: boolean;\n catalogs: Catalogs;\n origins: Record<string, string[]>;\n status: StatusResult;\n check: CheckResult;\n drafts: Drafts;\n triage: Record<string, TriageResult>;\n problems: StudioProblem[];\n}\n\n// A locale nobody can parse must not take the panel down: Studio is what you open to fix it.\nfunction readAll(cfg: ResolvedConfig): { catalogs: Catalogs; problems: StudioProblem[] } {\n const catalogs: Catalogs = {};\n const problems: StudioProblem[] = [];\n // an empty green panel and a wrong --root look identical, and only this line tells them apart\n if (!existsSync(cfg.dir)) {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/');\n problems.push({ scope: dir, message: '[verbaly] no catalogs here, run npx verbaly init or check --root' });\n }\n for (const locale of cfg.locales) {\n try {\n catalogs[locale] = readCatalog(cfg, locale);\n } catch (error) {\n catalogs[locale] = {};\n problems.push({\n scope: locale,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return { catalogs, problems };\n}\n\n// A sidecar nobody can parse is the other file Studio exists to fix, so it degrades like a catalog.\nfunction readDrafts(cfg: ResolvedConfig): { drafts: Drafts; problems: StudioProblem[] } {\n try {\n return { drafts: loadDrafts(cfg), problems: [] };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { drafts: {}, problems: [{ scope: DRAFTS_FILE, message }] };\n }\n}\n\n// check() reports the file a stray key was used in as an absolute path, origins already do not.\nfunction relativize(cfg: ResolvedConfig, result: CheckResult): CheckResult {\n return {\n ...result,\n unknown: result.unknown.map((entry) => ({\n ...entry,\n files: entry.files.map((file) => relative(cfg.root, file).replaceAll('\\\\', '/')),\n })),\n };\n}\n\n// One shot and unpaginated: the biggest catalog we know is past 1600 messages, instant locally.\nexport async function buildState(cfg: ResolvedConfig): Promise<StudioState> {\n const { catalogs, problems } = readAll(cfg);\n const registry = await extractProject(cfg);\n const sidecar = readDrafts(cfg);\n problems.push(...sidecar.problems);\n const live = effectiveDrafts(sidecar.drafts, catalogs);\n const source = (catalogs[cfg.sourceLocale] ?? {}) as Catalog;\n const targets = targetLocales(cfg);\n\n for (const { file, message } of registry.parseErrors()) {\n problems.push({ scope: relative(cfg.root, file).replaceAll('\\\\', '/'), message });\n }\n\n const perLocale: Record<string, TriageResult> = {};\n for (const locale of targets) {\n perLocale[locale] = triage({\n source,\n target: (catalogs[locale] ?? {}) as Catalog,\n // a locale still carrying drafts has not been reviewed, so it cannot be the control\n reviewed: targets\n .filter((other) => other !== locale && !(live[other] ?? []).length)\n .map((other) => (catalogs[other] ?? {}) as Catalog),\n });\n }\n\n return {\n root: cfg.root,\n dir: cfg.dir,\n sourceLocale: cfg.sourceLocale,\n locales: cfg.locales,\n // with include: [] nothing is scanned, so an empty origins map is off, not \"none found\"\n scanning: cfg.include.length > 0,\n catalogs,\n origins: await collectOrigins(cfg, registry),\n status: status(cfg, catalogs, registry, live),\n check: relativize(cfg, check(cfg, catalogs, registry)),\n drafts: live,\n triage: perLocale,\n problems,\n };\n}\n\nexport function health(cfg: ResolvedConfig): Promise<DoctorResult> {\n return doctor(cfg);\n}\n\nexport interface WriteMessageResult {\n locale: string;\n key: string;\n clearedDraft: boolean;\n}\n\n// A human wrote it, so it is reviewed: the rule import already applies in run.ts:447.\nexport function writeMessage(\n cfg: ResolvedConfig,\n locale: string,\n key: string,\n text: string,\n): WriteMessageResult {\n if (locale === cfg.sourceLocale) {\n throw badRequest('the source text lives in your code, Studio never edits it');\n }\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const source = readCatalog(cfg, cfg.sourceLocale);\n // hasOwn, not `in`: `in` walks the prototype, so toString and __proto__ would pass this guard\n if (!Object.hasOwn(source, key)) {\n throw badRequest(`\"${key}\" is not in the source catalog, so Studio will not create it`);\n }\n // '' is untranslated everywhere else, so whitespace is that and not a translation to validate\n const value = text.trim() ? text : '';\n // the same two calls check() makes: validatePair alone misses a plural block with no other case\n const issues = value\n ? [...validateMessage(value, locale), ...validatePair(source[key] as string, value)]\n : [];\n const errors = issues.filter((issue) => issue.severity === 'error');\n if (errors.length) {\n throw badRequest(`${errors.map((issue) => issue.message).join('; ')}`);\n }\n\n const catalog = { ...readCatalog(cfg, locale), [key]: value };\n writeCatalog(cfg, locale, catalog);\n\n const drafts = loadDrafts(cfg);\n const clearedDraft = (drafts[locale] ?? []).includes(key);\n clearDrafts(drafts, locale, [key]);\n saveDrafts(cfg, drafts);\n return { locale, key, clearedDraft };\n}\n\nexport interface ApproveResult {\n locale: string;\n approved: number;\n keys: string[];\n}\n\n// The sidecar is re-read here: saveDrafts writes every locale, so a stale copy drops another's.\nexport function approve(cfg: ResolvedConfig, locale: string, keys?: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n const had = drafts[locale] ?? [];\n // the keys it really cleared, because undo has to put back exactly those and nothing else\n const cleared = keys ? had.filter((key) => keys.includes(key)) : [...had];\n clearDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: cleared.length, keys: cleared };\n}\n\n// Undo is not a nicety here: the flag records who wrote the text, so restoring it restores a fact.\nexport function unapprove(cfg: ResolvedConfig, locale: string, keys: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n markDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: keys.length, keys };\n}\n","import { badRequest, HttpError } from './http';\n\nexport type JobState = 'running' | 'done' | 'failed';\n\nexport interface Job {\n id: string;\n kind: 'translate';\n state: JobState;\n total: number;\n done: number;\n locale?: string;\n message?: string;\n result?: unknown;\n}\n\n// One at a time, because two runs over the same catalogs is a race over the same files.\nlet current: Job | null = null;\nlet counter = 0;\n\nexport function running(): Job | null {\n return current?.state === 'running' ? current : null;\n}\n\nexport function read(id: string): Job {\n if (!current || current.id !== id) throw new HttpError(404, `no job called \"${id}\"`);\n return current;\n}\n\nexport function start(kind: Job['kind'], total: number): Job {\n if (running()) throw badRequest('a job is already running, wait for it or read its progress');\n counter += 1;\n current = { id: `${kind}-${counter}`, kind, state: 'running', total, done: 0 };\n return current;\n}\n\n// A batch that failed still finishes: the bar reports work attempted, and message says what broke.\nexport function advance(id: string, keys: number, locale: string, error?: string): void {\n if (current?.id !== id) return;\n current.done = Math.min(current.done + keys, current.total);\n current.locale = locale;\n if (error) current.message = error;\n}\n\n// A run that writes part of its work and then fails is a success for what it wrote, so both land.\nexport function finish(id: string, state: 'done' | 'failed', patch: Partial<Job> = {}): void {\n if (current?.id === id) Object.assign(current, patch, { state });\n}\n","import {\n collectOrigins,\n extractProject,\n loadCatalogs,\n resolveProvider,\n syncCatalogs,\n translateCatalogs,\n writeCatalog,\n writeDts,\n markDrafts,\n loadDrafts,\n saveDrafts,\n} from '@verbaly/compiler';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { advance, finish, start, type Job } from './jobs';\n\nexport interface ExtractResult {\n added: Record<string, string[]>;\n // only the source locale counts as new text: a target gains a blank for every gap it had\n found: number;\n messages: number;\n}\n\n// Local, fast and free, so it answers in the same request instead of becoming a job.\nexport async function runExtract(cfg: ResolvedConfig): Promise<ExtractResult> {\n if (!cfg.include.length) {\n throw badRequest('source scanning is off (include: []), so there is nothing to extract');\n }\n const registry = await extractProject(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = syncCatalogs(cfg, catalogs, registry);\n for (const locale of cfg.locales) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n // the types come from the source catalog, and cfg.dts false means the project opted out\n if (cfg.dts !== false) writeDts(cfg, catalogs[cfg.sourceLocale] ?? {}, cfg.dts);\n const found = result.added[cfg.sourceLocale]?.length ?? 0;\n return { added: result.added, found, messages: registry.messages().size };\n}\n\nexport interface Plan {\n pending: Record<string, string[]>;\n total: number;\n}\n\n// translate is the one command that spends money and minutes, so the panel always shows the bill.\nexport async function planTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Plan> {\n const provider = await resolveProvider(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, { locales, dryRun: true });\n const total = Object.values(result.pending).reduce((n, keys) => n + keys.length, 0);\n return { pending: result.pending, total };\n}\n\nexport async function startTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Job> {\n const provider = await resolveProvider(cfg);\n // the job carries its own denominator, so progress reads the same whether or not you asked first\n const plan = await planTranslate(cfg, locales);\n const job = start('translate', plan.total);\n const id = job.id;\n\n // the run outlives this request on purpose: the client asks the job how it is going\n void (async () => {\n try {\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, {\n locales,\n batchSize: cfg.translate.batchSize,\n concurrency: cfg.translate.concurrency,\n retries: cfg.translate.retries,\n origins: await collectOrigins(cfg),\n onProgress: (p) => advance(id, p.keys, p.locale, p.error),\n });\n for (const [locale, keys] of Object.entries(result.translated)) {\n if (keys.length) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n }\n // what a machine wrote stays a draft: the panel does not get to change that rule\n const drafts = loadDrafts(cfg);\n for (const [locale, keys] of Object.entries(result.translated)) {\n markDrafts(drafts, locale, keys);\n }\n saveDrafts(cfg, drafts);\n finish(id, result.failed.length ? 'failed' : 'done', {\n result,\n message: result.failed.length ? `${result.failed.length} batches did not answer` : undefined,\n });\n } catch (error) {\n finish(id, 'failed', { message: error instanceof Error ? error.message : String(error) });\n }\n })();\n\n return job;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { relative } from 'node:path';\nimport type { ResolvedConfig } from '@verbaly/compiler';\n\nconst run = promisify(execFile);\n\nexport interface Commit {\n sha: string;\n author: string;\n date: string;\n subject: string;\n}\n\n// one field separator that no subject can contain, written as the escape and never as the byte\nconst FIELD = '\u001f';\nconst FORMAT = `--format=%H${FIELD}%an${FIELD}%aI${FIELD}%s`;\n\n// git is asked, never assumed: no repository and no git both mean there is no history to show\nexport async function catalogHistory(cfg: ResolvedConfig, limit = 5): Promise<Commit[]> {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/') || '.';\n let stdout: string;\n try {\n const result = await run('git', ['log', `-n${limit}`, FORMAT, '--', dir], {\n cwd: cfg.root,\n timeout: 3000,\n windowsHide: true,\n });\n stdout = result.stdout;\n } catch {\n return [];\n }\n\n const commits: Commit[] = [];\n for (const line of stdout.split('\\n')) {\n const [sha, author, date, ...rest] = line.split(FIELD);\n // a subject can hold anything but a newline, so it is the last field and is rejoined\n if (!sha || !author || !date) continue;\n commits.push({ sha: sha.slice(0, 7), author, date, subject: rest.join(FIELD) });\n }\n return commits;\n}\n","import { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, normalize, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// the built panel sits beside the compiled server, so it is found relative to this file, never cwd\nconst UI = resolve(fileURLToPath(new URL('.', import.meta.url)), 'ui');\n\nconst TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.woff2': 'font/woff2',\n '.json': 'application/json; charset=utf-8',\n '.ico': 'image/x-icon',\n};\n\nexport interface Asset {\n body: Buffer;\n type: string;\n}\n\nexport const uiBuilt = (): boolean => existsSync(join(UI, 'index.html'));\n\n// A path is resolved and then checked to still be inside UI: ../ and an absolute one both land out.\nexport function readAsset(pathname: string): Asset | undefined {\n const wanted = pathname === '/' ? '/index.html' : pathname;\n const target = resolve(join(UI, normalize(wanted)));\n if (target !== UI && !target.startsWith(UI + (process.platform === 'win32' ? '\\\\' : '/'))) {\n return undefined;\n }\n if (!existsSync(target) || !statSync(target).isFile()) return undefined;\n const dot = target.lastIndexOf('.');\n return {\n body: readFileSync(target),\n type: TYPES[target.slice(dot).toLowerCase()] ?? 'application/octet-stream',\n };\n}\n","import { randomBytes, timingSafeEqual } from 'node:crypto';\n\nexport interface GuardOptions {\n port: number;\n token: string;\n}\n\n// A local server that writes files is reachable from any page the browser has open.\nexport function newToken(): string {\n return randomBytes(9).toString('base64url');\n}\n\n// Only the two names that resolve to this machine. A DNS rebind arrives with a foreign Host.\nexport function hostAllowed(host: string | undefined, port: number): boolean {\n // a browser omits the port when it is the scheme default, so :80 would 403 every real request\n const names = port === 80 ? ['127.0.0.1', 'localhost'] : [];\n return [`127.0.0.1:${port}`, `localhost:${port}`, ...names].includes(host ?? '');\n}\n\n// No Origin at all is a same-origin navigation or a curl, both fine; a foreign one never is.\nexport function originAllowed(origin: string | undefined, port: number): boolean {\n if (origin === undefined) return true;\n return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;\n}\n\n// Compared in constant time so the token cannot be guessed one character at a time.\nexport function tokenMatches(given: string | null, expected: string): boolean {\n if (given === null) return false;\n const a = Buffer.from(given);\n const b = Buffer.from(expected);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nexport interface GuardVerdict {\n ok: boolean;\n status: number;\n reason: string;\n}\n\nconst PASS: GuardVerdict = { ok: true, status: 200, reason: '' };\n\nexport function guardRequest(\n headers: { host?: string; origin?: string },\n url: URL,\n { port, token }: GuardOptions,\n): GuardVerdict {\n if (!hostAllowed(headers.host, port)) {\n return { ok: false, status: 403, reason: '[verbaly] unexpected Host header' };\n }\n if (!originAllowed(headers.origin, port)) {\n return { ok: false, status: 403, reason: '[verbaly] cross-origin request' };\n }\n if (!tokenMatches(url.searchParams.get('t'), token)) {\n return { ok: false, status: 401, reason: '[verbaly] missing or wrong token, open the printed url' };\n }\n return PASS;\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { approve, buildState, health, unapprove, writeMessage } from './api';\nimport { planTranslate, runExtract, startTranslate } from './actions';\nimport { read as readJob, running } from './jobs';\nimport { catalogHistory } from './history';\nimport { readAsset, uiBuilt } from './assets';\nimport { guardRequest, newToken } from './guard';\nimport { HttpError, badRequest, scrub } from './http';\n\nexport interface StudioServer {\n server: Server;\n port: number;\n token: string;\n url: string;\n close: () => Promise<void>;\n}\n\nexport interface StartOptions {\n port?: number;\n token?: string;\n}\n\nconst DEFAULT_PORT = 4747;\nconst MAX_BODY = 1_000_000;\n\nfunction send(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-store',\n });\n res.end(JSON.stringify(body));\n}\n\nasync function readJson(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of req) {\n size += (chunk as Buffer).length;\n if (size > MAX_BODY) throw new HttpError(413, 'request body too large');\n chunks.push(chunk as Buffer);\n }\n if (!chunks.length) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));\n } catch {\n throw badRequest('body is not valid JSON');\n }\n // null and an array both pass typeof 'object', and reading .text off them is a 500\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw badRequest('body must be a JSON object');\n }\n return parsed as Record<string, unknown>;\n}\n\nfunction segment(raw: string | undefined, what: string): string {\n let value: string;\n try {\n value = decodeURIComponent(raw ?? '');\n } catch {\n throw badRequest(`the ${what} in the url is not valid percent-encoding`);\n }\n if (!value) throw badRequest(`the url is missing a ${what}`);\n return value;\n}\n\n// One page, JSON on every route: a framework would only add a dependency to a local tool.\nexport function createStudioApp(cfg: ResolvedConfig, port: number, token: string) {\n return async function handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // The url is built inside the try: `GET //` throws, and out here that would kill the process.\n try {\n let url: URL;\n try {\n url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);\n } catch {\n throw badRequest('the request target is not a valid url');\n }\n\n const api = url.pathname.startsWith('/api/');\n const verdict = guardRequest({ host: req.headers.host, origin: req.headers.origin }, url, {\n port,\n token,\n });\n // the panel files are the published npm package: only the project data needs a token\n if (!verdict.ok && (api || verdict.status !== 401)) {\n send(res, verdict.status, { error: verdict.reason });\n return;\n }\n\n if (!api && req.method === 'GET') {\n const asset = readAsset(url.pathname);\n if (asset) {\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'no-store' });\n res.end(asset.body);\n return;\n }\n if (url.pathname === '/' && !uiBuilt()) {\n throw new HttpError(500, 'the panel is not in this install, so only /api/* answers here');\n }\n }\n\n if (req.method === 'GET' && url.pathname === '/api/state') {\n send(res, 200, await buildState(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/history') {\n send(res, 200, { commits: await catalogHistory(cfg) });\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/health') {\n send(res, 200, await health(cfg));\n return;\n }\n if (req.method === 'PUT' && url.pathname.startsWith('/api/message/')) {\n const rest = url.pathname.slice('/api/message/'.length).split('/');\n const locale = segment(rest[0], 'locale');\n const key = segment(rest.slice(1).join('/'), 'key');\n const body = await readJson(req);\n if (typeof body.text !== 'string') throw badRequest('body needs a \"text\" string');\n send(res, 200, writeMessage(cfg, locale, key, body.text));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/approve') {\n const body = await readJson(req);\n if (typeof body.locale !== 'string') throw badRequest('body needs a \"locale\" string');\n const keys = Array.isArray(body.keys)\n ? body.keys.filter((k): k is string => typeof k === 'string')\n : undefined;\n if (body.undo === true) {\n if (!keys?.length) throw badRequest('undoing needs the \"keys\" it should put back');\n send(res, 200, unapprove(cfg, body.locale, keys));\n return;\n }\n send(res, 200, approve(cfg, body.locale, keys));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/extract') {\n send(res, 200, await runExtract(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/translate') {\n const locales = url.searchParams.getAll('locale');\n send(res, 200, await planTranslate(cfg, locales.length ? locales : undefined));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/translate') {\n const body = await readJson(req);\n const locales = Array.isArray(body.locales)\n ? body.locales.filter((l): l is string => typeof l === 'string')\n : undefined;\n send(res, 200, await startTranslate(cfg, locales?.length ? locales : undefined));\n return;\n }\n // a reload loses the id, so the panel asks what is running rather than losing the bar\n if (req.method === 'GET' && url.pathname === '/api/job') {\n send(res, 200, running());\n return;\n }\n if (req.method === 'GET' && url.pathname.startsWith('/api/job/')) {\n send(res, 200, readJob(segment(url.pathname.slice('/api/job/'.length), 'job id')));\n return;\n }\n\n send(res, 404, { error: `[verbaly] no route for ${req.method} ${url.pathname}` });\n } catch (error) {\n const status = error instanceof HttpError ? error.status : 500;\n const message = error instanceof Error ? error.message : String(error);\n send(res, status, { error: scrub(message, cfg.root) });\n }\n };\n}\n\n// A busy port climbs instead of failing: this is a local tool, not a service on a fixed address.\nfunction listen(server: Server, port: number, attemptsLeft: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const onError = (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE' && attemptsLeft > 0) {\n server.removeListener('error', onError);\n resolve(listen(server, port + 1, attemptsLeft - 1));\n return;\n }\n reject(error);\n };\n server.once('error', onError);\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', onError);\n // port 0 asks the system to pick, so the bound address is the only place the answer is\n const bound = server.address() as AddressInfo | string | null;\n resolve(typeof bound === 'object' && bound !== null ? bound.port : port);\n });\n });\n}\n\nexport async function startStudio(\n cfg: ResolvedConfig,\n options: StartOptions = {},\n): Promise<StudioServer> {\n const token = options.token ?? newToken();\n const server = createServer();\n // The handler is attached before listen so no request can arrive without one.\n let port = options.port ?? DEFAULT_PORT;\n server.on('request', (req, res) => void createStudioApp(cfg, port, token)(req, res));\n port = await listen(server, port, 20);\n\n return {\n server,\n port,\n token,\n url: `http://127.0.0.1:${port}/?t=${token}`,\n close: () =>\n new Promise<void>((resolve, reject) =>\n server.close((error) => (error ? reject(error) : resolve())),\n ),\n };\n}\n","#!/usr/bin/env node\nimport { parseArgs } from 'node:util';\nimport { counted, formatCliError, loadConfig } from '@verbaly/compiler';\nimport { buildState } from './api';\nimport { startStudio } from './server';\n\ntry {\n const { values } = parseArgs({\n options: {\n root: { type: 'string' },\n port: { type: 'string' },\n json: { type: 'boolean' },\n },\n });\n const port = values.port === undefined ? undefined : Number(values.port);\n if (port !== undefined && !Number.isInteger(port)) {\n throw new Error(`[verbaly] --port needs a number, got \"${values.port}\"`);\n }\n const cfg = await loadConfig(values.root ?? process.cwd());\n\n // --json is the state the interface reads, on stdout, before any interface exists.\n if (values.json) {\n console.log(JSON.stringify(await buildState(cfg), null, 2));\n } else {\n const studio = await startStudio(cfg, { port });\n const state = await buildState(cfg);\n const missing = state.status.locales.reduce((n, l) => n + (l.total - l.translated), 0);\n const drafts = Object.values(state.drafts).reduce((n, keys) => n + keys.length, 0);\n console.log(`\\n Verbaly Studio ${studio.url}`);\n console.log(` Project ${cfg.root}`);\n console.log(\n ` Catalog ${counted(state.status.messages, 'message')} · ` +\n `${missing} untranslated · ${counted(drafts, 'draft')}`,\n );\n for (const problem of state.problems) console.log(` ! ${problem.scope}: ${problem.message}`);\n console.log('\\n Ctrl+C to stop\\n');\n }\n} catch (error) {\n console.error(formatCliError(error));\n process.exitCode = 1;\n}\n"],"mappings":";;;;;;;;;;AACA,IAAa,YAAb,cAA+B,MAAM;CACnC;CAEA,YAAY,QAAgB,SAAiB;EAC3C,MAAM,QAAQ,WAAW,WAAW,IAAI,UAAU,aAAa,SAAS;EACxE,KAAK,SAAS;EACd,KAAK,OAAO;CACd;AACF;AAEA,MAAa,cAAc,YAAoB,IAAI,UAAU,KAAK,OAAO;AAGzE,SAAgB,MAAM,SAAiB,MAAsB;CAC3D,OAAO,OAAO,QAAQ,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI;AAChD;;;ACEA,MAAM,SAAS;AACf,MAAM,OAAO;AACb,MAAM,OAAO;AAEb,SAAS,IAAI,MAAc,IAAY,WAA6C;CAClF,MAAM,QAAQ,KAAK,MAAM,EAAE,KAAK,CAAC;CACjC,QAAQ,YAAY,MAAM,IAAI,SAAS,IAAI,MAAA,CAAO,KAAK;AACzD;AAEA,SAAS,KAAK,GAAa,GAAsB;CAC/C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,MAAM,EAAE,EAAE;AAC9D;AAGA,MAAM,aAAa,MAAc,EAAE,QAAQ,iBAAiB,EAAE;AAE9D,MAAM,cAAc,MAAc,UAAU,CAAC,CAAC,CAAC,WAAW,SAAS,GAAG;AAEtE,SAAS,KAAK,KAAmB,KAAa,QAA4B;CACxE,CAAC,IAAI,SAAS,CAAC,EAAA,CAAG,KAAK,MAAM;AAC/B;AAEA,SAAgB,OAAO,EAAE,QAAQ,QAAQ,YAAuC;CAE9E,MAAM,MAAoB,OAAO,OAAO,IAAI;CAC5C,MAAM,OAAO,OAAO,KAAK,MAAM;CAG/B,MAAM,WAAqC,OAAO,OAAO,IAAI;CAC7D,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,OAAO,OAAO,IAAI,EAAE,KAAK;EAC/B,IAAI,MAAM,CAAC,SAAS,UAAU,CAAC,EAAA,CAAG,KAAK,GAAG;CAC5C;CACA,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,GAAG;EACpD,IAAI,MAAM,SAAS,GAAG;EACtB,MAAM,YAAY,SAAS,MACxB,YAAY,IAAI,IAAI,MAAM,KAAK,MAAM,QAAQ,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAC1F;EACA,IAAI,WACF,KAAK,MAAM,OAAO,OAChB,KAAK,KAAK,KAAK;GAAE,QAAQ;GAAa,MAAM,IAAI,KAAK;EAAmC,CAAC;EAI7F,MAAM,UAAU,IAAI,IAAI,MAAM,KAAK,QAAQ,OAAO,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC;EACrF,IAAI,CAAC,aAAa,QAAQ,OAAO,GAC/B,KAAK,MAAM,OAAO,OAChB,KAAK,KAAK,KAAK;GAAE,QAAQ;GAAa,MAAM,IAAI,KAAK;EAA2C,CAAC;CAGvG;CAEA,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,MAAM,OAAO,IAAI,EAAE,KAAK,KAAK;EACnC,MAAM,MAAM,OAAO,IAAI,EAAE,KAAK,KAAK;EACnC,IAAI,CAAC,OAAO,CAAC,KAAK;EAGlB,MAAM,WAAW,SAAS,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,MAAM,MAAM,KAAA,KAAa,MAAM,EAAE;EAC9F,IAAI,QAAQ,OAAO,SAAS,SAAS,KAAK,SAAS,OAAO,MAAM,MAAM,GAAG,GACvE,KAAK,KAAK,KAAK;GAAE,QAAQ;GAAQ,MAAM;EAAgC,CAAC;EAI1E,MAAM,YAAY,IAAI,KAAK,QAAQ,UAAU;EAC7C,IAAI,UAAU,SAAS,KAAK,CAAC,KAAK,WAAW,IAAI,KAAK,QAAQ,UAAU,CAAC,GACvE,KAAK,KAAK,KAAK;GAAE,QAAQ;GAAU,MAAM;EAAsC,CAAC;EAElF,IAAI,CAAC,KAAK,IAAI,KAAK,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM,SAAS,CAAC,GAC5D,KAAK,KAAK,KAAK;GAAE,QAAQ;GAAO,MAAM;EAAgB,CAAC;EAEzD,IAAI,CAAC,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC,GACtC,KAAK,KAAK,KAAK;GAAE,QAAQ;GAAQ,MAAM;EAAwC,CAAC;CAEpF;CAEA,OAAO;AACT;;;AC1CA,SAAS,QAAQ,KAAwE;CACvF,MAAM,WAAqB,CAAC;CAC5B,MAAM,WAA4B,CAAC;CAEnC,IAAI,CAAC,WAAW,IAAI,GAAG,GAAG;EACxB,MAAM,MAAM,SAAS,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,MAAM,GAAG;EAC5D,SAAS,KAAK;GAAE,OAAO;GAAK,SAAS;EAAmE,CAAC;CAC3G;CACA,KAAK,MAAM,UAAU,IAAI,SACvB,IAAI;EACF,SAAS,UAAU,YAAY,KAAK,MAAM;CAC5C,SAAS,OAAO;EACd,SAAS,UAAU,CAAC;EACpB,SAAS,KAAK;GACZ,OAAO;GACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAChE,CAAC;CACH;CAEF,OAAO;EAAE;EAAU;CAAS;AAC9B;AAGA,SAAS,WAAW,KAAoE;CACtF,IAAI;EACF,OAAO;GAAE,QAAQ,WAAW,GAAG;GAAG,UAAU,CAAC;EAAE;CACjD,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,OAAO;GAAE,QAAQ,CAAC;GAAG,UAAU,CAAC;IAAE,OAAO;IAAa;GAAQ,CAAC;EAAE;CACnE;AACF;AAGA,SAAS,WAAW,KAAqB,QAAkC;CACzE,OAAO;EACL,GAAG;EACH,SAAS,OAAO,QAAQ,KAAK,WAAW;GACtC,GAAG;GACH,OAAO,MAAM,MAAM,KAAK,SAAS,SAAS,IAAI,MAAM,IAAI,CAAC,CAAC,WAAW,MAAM,GAAG,CAAC;EACjF,EAAE;CACJ;AACF;AAGA,eAAsB,WAAW,KAA2C;CAC1E,MAAM,EAAE,UAAU,aAAa,QAAQ,GAAG;CAC1C,MAAM,WAAW,MAAM,eAAe,GAAG;CACzC,MAAM,UAAU,WAAW,GAAG;CAC9B,SAAS,KAAK,GAAG,QAAQ,QAAQ;CACjC,MAAM,OAAO,gBAAgB,QAAQ,QAAQ,QAAQ;CACrD,MAAM,SAAU,SAAS,IAAI,iBAAiB,CAAC;CAC/C,MAAM,UAAU,cAAc,GAAG;CAEjC,KAAK,MAAM,EAAE,MAAM,aAAa,SAAS,YAAY,GACnD,SAAS,KAAK;EAAE,OAAO,SAAS,IAAI,MAAM,IAAI,CAAC,CAAC,WAAW,MAAM,GAAG;EAAG;CAAQ,CAAC;CAGlF,MAAM,YAA0C,CAAC;CACjD,KAAK,MAAM,UAAU,SACnB,UAAU,UAAU,OAAO;EACzB;EACA,QAAS,SAAS,WAAW,CAAC;EAE9B,UAAU,QACP,QAAQ,UAAU,UAAU,UAAU,EAAE,KAAK,UAAU,CAAC,EAAA,CAAG,MAAM,CAAC,CAClE,KAAK,UAAW,SAAS,UAAU,CAAC,CAAa;CACtD,CAAC;CAGH,OAAO;EACL,MAAM,IAAI;EACV,KAAK,IAAI;EACT,cAAc,IAAI;EAClB,SAAS,IAAI;EAEb,UAAU,IAAI,QAAQ,SAAS;EAC/B;EACA,SAAS,MAAM,eAAe,KAAK,QAAQ;EAC3C,QAAQ,OAAO,KAAK,UAAU,UAAU,IAAI;EAC5C,OAAO,WAAW,KAAK,MAAM,KAAK,UAAU,QAAQ,CAAC;EACrD,QAAQ;EACR,QAAQ;EACR;CACF;AACF;AAEA,SAAgB,OAAO,KAA4C;CACjE,OAAO,OAAO,GAAG;AACnB;AASA,SAAgB,aACd,KACA,QACA,KACA,MACoB;CACpB,IAAI,WAAW,IAAI,cACjB,MAAM,WAAW,2DAA2D;CAE9E,IAAI,CAAC,IAAI,QAAQ,SAAS,MAAM,GAC9B,MAAM,WAAW,GAAG,OAAO,sCAAsC;CAEnE,MAAM,SAAS,YAAY,KAAK,IAAI,YAAY;CAEhD,IAAI,CAAC,OAAO,OAAO,QAAQ,GAAG,GAC5B,MAAM,WAAW,IAAI,IAAI,6DAA6D;CAGxF,MAAM,QAAQ,KAAK,KAAK,IAAI,OAAO;CAKnC,MAAM,UAHS,QACX,CAAC,GAAG,gBAAgB,OAAO,MAAM,GAAG,GAAG,aAAa,OAAO,MAAgB,KAAK,CAAC,IACjF,CAAC,EAAA,CACiB,QAAQ,UAAU,MAAM,aAAa,OAAO;CAClE,IAAI,OAAO,QACT,MAAM,WAAW,GAAG,OAAO,KAAK,UAAU,MAAM,OAAO,CAAC,CAAC,KAAK,IAAI,GAAG;CAGvE,MAAM,UAAU;EAAE,GAAG,YAAY,KAAK,MAAM;GAAI,MAAM;CAAM;CAC5D,aAAa,KAAK,QAAQ,OAAO;CAEjC,MAAM,SAAS,WAAW,GAAG;CAC7B,MAAM,gBAAgB,OAAO,WAAW,CAAC,EAAA,CAAG,SAAS,GAAG;CACxD,YAAY,QAAQ,QAAQ,CAAC,GAAG,CAAC;CACjC,WAAW,KAAK,MAAM;CACtB,OAAO;EAAE;EAAQ;EAAK;CAAa;AACrC;AASA,SAAgB,QAAQ,KAAqB,QAAgB,MAAgC;CAC3F,IAAI,CAAC,IAAI,QAAQ,SAAS,MAAM,GAC9B,MAAM,WAAW,GAAG,OAAO,sCAAsC;CAEnE,MAAM,SAAS,WAAW,GAAG;CAC7B,MAAM,MAAM,OAAO,WAAW,CAAC;CAE/B,MAAM,UAAU,OAAO,IAAI,QAAQ,QAAQ,KAAK,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG;CACxE,YAAY,QAAQ,QAAQ,IAAI;CAChC,WAAW,KAAK,MAAM;CACtB,OAAO;EAAE;EAAQ,UAAU,QAAQ;EAAQ,MAAM;CAAQ;AAC3D;AAGA,SAAgB,UAAU,KAAqB,QAAgB,MAA+B;CAC5F,IAAI,CAAC,IAAI,QAAQ,SAAS,MAAM,GAC9B,MAAM,WAAW,GAAG,OAAO,sCAAsC;CAEnE,MAAM,SAAS,WAAW,GAAG;CAC7B,WAAW,QAAQ,QAAQ,IAAI;CAC/B,WAAW,KAAK,MAAM;CACtB,OAAO;EAAE;EAAQ,UAAU,KAAK;EAAQ;CAAK;AAC/C;;;ACzMA,IAAI,UAAsB;AAC1B,IAAI,UAAU;AAEd,SAAgB,UAAsB;CACpC,OAAO,SAAS,UAAU,YAAY,UAAU;AAClD;AAEA,SAAgB,KAAK,IAAiB;CACpC,IAAI,CAAC,WAAW,QAAQ,OAAO,IAAI,MAAM,IAAI,UAAU,KAAK,kBAAkB,GAAG,EAAE;CACnF,OAAO;AACT;AAEA,SAAgB,MAAM,MAAmB,OAAoB;CAC3D,IAAI,QAAQ,GAAG,MAAM,WAAW,4DAA4D;CAC5F,WAAW;CACX,UAAU;EAAE,IAAI,GAAG,KAAK,GAAG;EAAW;EAAM,OAAO;EAAW;EAAO,MAAM;CAAE;CAC7E,OAAO;AACT;AAGA,SAAgB,QAAQ,IAAY,MAAc,QAAgB,OAAsB;CACtF,IAAI,SAAS,OAAO,IAAI;CACxB,QAAQ,OAAO,KAAK,IAAI,QAAQ,OAAO,MAAM,QAAQ,KAAK;CAC1D,QAAQ,SAAS;CACjB,IAAI,OAAO,QAAQ,UAAU;AAC/B;AAGA,SAAgB,OAAO,IAAY,OAA0B,QAAsB,CAAC,GAAS;CAC3F,IAAI,SAAS,OAAO,IAAI,OAAO,OAAO,SAAS,OAAO,EAAE,MAAM,CAAC;AACjE;;;ACrBA,eAAsB,WAAW,KAA6C;CAC5E,IAAI,CAAC,IAAI,QAAQ,QACf,MAAM,WAAW,sEAAsE;CAEzF,MAAM,WAAW,MAAM,eAAe,GAAG;CACzC,MAAM,WAAW,aAAa,GAAG;CACjC,MAAM,SAAS,aAAa,KAAK,UAAU,QAAQ;CACnD,KAAK,MAAM,UAAU,IAAI,SAAS,aAAa,KAAK,QAAQ,SAAS,WAAW,CAAC,CAAC;CAElF,IAAI,IAAI,QAAQ,OAAO,SAAS,KAAK,SAAS,IAAI,iBAAiB,CAAC,GAAG,IAAI,GAAG;CAC9E,MAAM,QAAQ,OAAO,MAAM,IAAI,aAAa,EAAE,UAAU;CACxD,OAAO;EAAE,OAAO,OAAO;EAAO;EAAO,UAAU,SAAS,SAAS,CAAC,CAAC;CAAK;AAC1E;AAQA,eAAsB,cAAc,KAAqB,SAAmC;CAC1F,MAAM,WAAW,MAAM,gBAAgB,GAAG;CAC1C,MAAM,WAAW,aAAa,GAAG;CACjC,MAAM,SAAS,MAAM,kBAAkB,KAAK,UAAU,UAAU;EAAE;EAAS,QAAQ;CAAK,CAAC;CACzF,MAAM,QAAQ,OAAO,OAAO,OAAO,OAAO,CAAC,CAAC,QAAQ,GAAG,SAAS,IAAI,KAAK,QAAQ,CAAC;CAClF,OAAO;EAAE,SAAS,OAAO;EAAS;CAAM;AAC1C;AAEA,eAAsB,eAAe,KAAqB,SAAkC;CAC1F,MAAM,WAAW,MAAM,gBAAgB,GAAG;CAG1C,MAAM,MAAM,MAAM,cAAa,MADZ,cAAc,KAAK,OAAO,EACd,CAAK,KAAK;CACzC,MAAM,KAAK,IAAI;CAGf,CAAM,YAAY;EAChB,IAAI;GACF,MAAM,WAAW,aAAa,GAAG;GACjC,MAAM,SAAS,MAAM,kBAAkB,KAAK,UAAU,UAAU;IAC9D;IACA,WAAW,IAAI,UAAU;IACzB,aAAa,IAAI,UAAU;IAC3B,SAAS,IAAI,UAAU;IACvB,SAAS,MAAM,eAAe,GAAG;IACjC,aAAa,MAAM,QAAQ,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK;GAC1D,CAAC;GACD,KAAK,MAAM,CAAC,QAAQ,SAAS,OAAO,QAAQ,OAAO,UAAU,GAC3D,IAAI,KAAK,QAAQ,aAAa,KAAK,QAAQ,SAAS,WAAW,CAAC,CAAC;GAGnE,MAAM,SAAS,WAAW,GAAG;GAC7B,KAAK,MAAM,CAAC,QAAQ,SAAS,OAAO,QAAQ,OAAO,UAAU,GAC3D,WAAW,QAAQ,QAAQ,IAAI;GAEjC,WAAW,KAAK,MAAM;GACtB,OAAO,IAAI,OAAO,OAAO,SAAS,WAAW,QAAQ;IACnD;IACA,SAAS,OAAO,OAAO,SAAS,GAAG,OAAO,OAAO,OAAO,2BAA2B,KAAA;GACrF,CAAC;EACH,SAAS,OAAO;GACd,OAAO,IAAI,UAAU,EAAE,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;EAC1F;CACF,EAAA,CAAG;CAEH,OAAO;AACT;;;ACtFA,MAAM,MAAM,UAAU,QAAQ;AAU9B,MAAM,QAAQ;AACd,MAAM,SAAS,cAAc,MAAM,KAAK,MAAM,KAAK,MAAM;AAGzD,eAAsB,eAAe,KAAqB,QAAQ,GAAsB;CACtF,MAAM,MAAM,SAAS,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,MAAM,GAAG,KAAK;CACjE,IAAI;CACJ,IAAI;EAMF,UAAS,MALY,IAAI,OAAO;GAAC;GAAO,KAAK;GAAS;GAAQ;GAAM;EAAG,GAAG;GACxE,KAAK,IAAI;GACT,SAAS;GACT,aAAa;EACf,CAAC,EAAA,CACe;CAClB,QAAQ;EACN,OAAO,CAAC;CACV;CAEA,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,QAAQ,OAAO,MAAM,IAAI,GAAG;EACrC,MAAM,CAAC,KAAK,QAAQ,MAAM,GAAG,QAAQ,KAAK,MAAM,KAAK;EAErD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM;EAC9B,QAAQ,KAAK;GAAE,KAAK,IAAI,MAAM,GAAG,CAAC;GAAG;GAAQ;GAAM,SAAS,KAAK,KAAK,KAAK;EAAE,CAAC;CAChF;CACA,OAAO;AACT;;;ACpCA,MAAM,KAAK,QAAQ,cAAc,IAAI,IAAI,KAAK,YAAY,GAAG,CAAC,GAAG,IAAI;AAErE,MAAM,QAAgC;CACpC,SAAS;CACT,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,SAAS;CACT,QAAQ;AACV;AAOA,MAAa,gBAAyB,WAAW,KAAK,IAAI,YAAY,CAAC;AAGvE,SAAgB,UAAU,UAAqC;CAE7D,MAAM,SAAS,QAAQ,KAAK,IAAI,UADjB,aAAa,MAAM,gBAAgB,QACF,CAAC,CAAC;CAClD,IAAI,WAAW,MAAM,CAAC,OAAO,WAAW,MAAM,QAAQ,aAAa,UAAU,OAAO,IAAI,GACtF;CAEF,IAAI,CAAC,WAAW,MAAM,KAAK,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO,GAAG,OAAO,KAAA;CAC9D,MAAM,MAAM,OAAO,YAAY,GAAG;CAClC,OAAO;EACL,MAAM,aAAa,MAAM;EACzB,MAAM,MAAM,OAAO,MAAM,GAAG,CAAC,CAAC,YAAY,MAAM;CAClD;AACF;;;AC7BA,SAAgB,WAAmB;CACjC,OAAO,YAAY,CAAC,CAAC,CAAC,SAAS,WAAW;AAC5C;AAGA,SAAgB,YAAY,MAA0B,MAAuB;CAE3E,MAAM,QAAQ,SAAS,KAAK,CAAC,aAAa,WAAW,IAAI,CAAC;CAC1D,OAAO;EAAC,aAAa;EAAQ,aAAa;EAAQ,GAAG;CAAK,CAAC,CAAC,SAAS,QAAQ,EAAE;AACjF;AAGA,SAAgB,cAAc,QAA4B,MAAuB;CAC/E,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,OAAO,WAAW,oBAAoB,UAAU,WAAW,oBAAoB;AACjF;AAGA,SAAgB,aAAa,OAAsB,UAA2B;CAC5E,IAAI,UAAU,MAAM,OAAO;CAC3B,MAAM,IAAI,OAAO,KAAK,KAAK;CAC3B,MAAM,IAAI,OAAO,KAAK,QAAQ;CAC9B,OAAO,EAAE,WAAW,EAAE,UAAU,gBAAgB,GAAG,CAAC;AACtD;AAQA,MAAM,OAAqB;CAAE,IAAI;CAAM,QAAQ;CAAK,QAAQ;AAAG;AAE/D,SAAgB,aACd,SACA,KACA,EAAE,MAAM,SACM;CACd,IAAI,CAAC,YAAY,QAAQ,MAAM,IAAI,GACjC,OAAO;EAAE,IAAI;EAAO,QAAQ;EAAK,QAAQ;CAAmC;CAE9E,IAAI,CAAC,cAAc,QAAQ,QAAQ,IAAI,GACrC,OAAO;EAAE,IAAI;EAAO,QAAQ;EAAK,QAAQ;CAAiC;CAE5E,IAAI,CAAC,aAAa,IAAI,aAAa,IAAI,GAAG,GAAG,KAAK,GAChD,OAAO;EAAE,IAAI;EAAO,QAAQ;EAAK,QAAQ;CAAyD;CAEpG,OAAO;AACT;;;AChCA,MAAM,eAAe;AACrB,MAAM,WAAW;AAEjB,SAAS,KAAK,KAAqB,QAAgB,MAAqB;CACtE,IAAI,UAAU,QAAQ;EACpB,gBAAgB;EAChB,iBAAiB;CACnB,CAAC;CACD,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC9B;AAEA,eAAe,SAAS,KAAwD;CAC9E,MAAM,SAAmB,CAAC;CAC1B,IAAI,OAAO;CACX,WAAW,MAAM,SAAS,KAAK;EAC7B,QAAS,MAAiB;EAC1B,IAAI,OAAO,UAAU,MAAM,IAAI,UAAU,KAAK,wBAAwB;EACtE,OAAO,KAAK,KAAe;CAC7B;CACA,IAAI,CAAC,OAAO,QAAQ,OAAO,CAAC;CAC5B,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,OAAO,OAAO,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC;CAC5D,QAAQ;EACN,MAAM,WAAW,wBAAwB;CAC3C;CAEA,IAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GACvE,MAAM,WAAW,4BAA4B;CAE/C,OAAO;AACT;AAEA,SAAS,QAAQ,KAAyB,MAAsB;CAC9D,IAAI;CACJ,IAAI;EACF,QAAQ,mBAAmB,OAAO,EAAE;CACtC,QAAQ;EACN,MAAM,WAAW,OAAO,KAAK,0CAA0C;CACzE;CACA,IAAI,CAAC,OAAO,MAAM,WAAW,wBAAwB,MAAM;CAC3D,OAAO;AACT;AAGA,SAAgB,gBAAgB,KAAqB,MAAc,OAAe;CAChF,OAAO,eAAe,OAAO,KAAsB,KAAoC;EAErF,IAAI;GACF,IAAI;GACJ,IAAI;IACF,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,oBAAoB,MAAM;GAC1D,QAAQ;IACN,MAAM,WAAW,uCAAuC;GAC1D;GAEA,MAAM,MAAM,IAAI,SAAS,WAAW,OAAO;GAC3C,MAAM,UAAU,aAAa;IAAE,MAAM,IAAI,QAAQ;IAAM,QAAQ,IAAI,QAAQ;GAAO,GAAG,KAAK;IACxF;IACA;GACF,CAAC;GAED,IAAI,CAAC,QAAQ,OAAO,OAAO,QAAQ,WAAW,MAAM;IAClD,KAAK,KAAK,QAAQ,QAAQ,EAAE,OAAO,QAAQ,OAAO,CAAC;IACnD;GACF;GAEA,IAAI,CAAC,OAAO,IAAI,WAAW,OAAO;IAChC,MAAM,QAAQ,UAAU,IAAI,QAAQ;IACpC,IAAI,OAAO;KACT,IAAI,UAAU,KAAK;MAAE,gBAAgB,MAAM;MAAM,iBAAiB;KAAW,CAAC;KAC9E,IAAI,IAAI,MAAM,IAAI;KAClB;IACF;IACA,IAAI,IAAI,aAAa,OAAO,CAAC,QAAQ,GACnC,MAAM,IAAI,UAAU,KAAK,+DAA+D;GAE5F;GAEA,IAAI,IAAI,WAAW,SAAS,IAAI,aAAa,cAAc;IACzD,KAAK,KAAK,KAAK,MAAM,WAAW,GAAG,CAAC;IACpC;GACF;GACA,IAAI,IAAI,WAAW,SAAS,IAAI,aAAa,gBAAgB;IAC3D,KAAK,KAAK,KAAK,EAAE,SAAS,MAAM,eAAe,GAAG,EAAE,CAAC;IACrD;GACF;GACA,IAAI,IAAI,WAAW,SAAS,IAAI,aAAa,eAAe;IAC1D,KAAK,KAAK,KAAK,MAAM,OAAO,GAAG,CAAC;IAChC;GACF;GACA,IAAI,IAAI,WAAW,SAAS,IAAI,SAAS,WAAW,eAAe,GAAG;IACpE,MAAM,OAAO,IAAI,SAAS,MAAM,EAAsB,CAAC,CAAC,MAAM,GAAG;IACjE,MAAM,SAAS,QAAQ,KAAK,IAAI,QAAQ;IACxC,MAAM,MAAM,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,KAAK;IAClD,MAAM,OAAO,MAAM,SAAS,GAAG;IAC/B,IAAI,OAAO,KAAK,SAAS,UAAU,MAAM,WAAW,8BAA4B;IAChF,KAAK,KAAK,KAAK,aAAa,KAAK,QAAQ,KAAK,KAAK,IAAI,CAAC;IACxD;GACF;GACA,IAAI,IAAI,WAAW,UAAU,IAAI,aAAa,gBAAgB;IAC5D,MAAM,OAAO,MAAM,SAAS,GAAG;IAC/B,IAAI,OAAO,KAAK,WAAW,UAAU,MAAM,WAAW,gCAA8B;IACpF,MAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,IAChC,KAAK,KAAK,QAAQ,MAAmB,OAAO,MAAM,QAAQ,IAC1D,KAAA;IACJ,IAAI,KAAK,SAAS,MAAM;KACtB,IAAI,CAAC,MAAM,QAAQ,MAAM,WAAW,+CAA6C;KACjF,KAAK,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ,IAAI,CAAC;KAChD;IACF;IACA,KAAK,KAAK,KAAK,QAAQ,KAAK,KAAK,QAAQ,IAAI,CAAC;IAC9C;GACF;GACA,IAAI,IAAI,WAAW,UAAU,IAAI,aAAa,gBAAgB;IAC5D,KAAK,KAAK,KAAK,MAAM,WAAW,GAAG,CAAC;IACpC;GACF;GACA,IAAI,IAAI,WAAW,SAAS,IAAI,aAAa,kBAAkB;IAC7D,MAAM,UAAU,IAAI,aAAa,OAAO,QAAQ;IAChD,KAAK,KAAK,KAAK,MAAM,cAAc,KAAK,QAAQ,SAAS,UAAU,KAAA,CAAS,CAAC;IAC7E;GACF;GACA,IAAI,IAAI,WAAW,UAAU,IAAI,aAAa,kBAAkB;IAC9D,MAAM,OAAO,MAAM,SAAS,GAAG;IAC/B,MAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,IACtC,KAAK,QAAQ,QAAQ,MAAmB,OAAO,MAAM,QAAQ,IAC7D,KAAA;IACJ,KAAK,KAAK,KAAK,MAAM,eAAe,KAAK,SAAS,SAAS,UAAU,KAAA,CAAS,CAAC;IAC/E;GACF;GAEA,IAAI,IAAI,WAAW,SAAS,IAAI,aAAa,YAAY;IACvD,KAAK,KAAK,KAAK,QAAQ,CAAC;IACxB;GACF;GACA,IAAI,IAAI,WAAW,SAAS,IAAI,SAAS,WAAW,WAAW,GAAG;IAChE,KAAK,KAAK,KAAKA,KAAQ,QAAQ,IAAI,SAAS,MAAM,CAAkB,GAAG,QAAQ,CAAC,CAAC;IACjF;GACF;GAEA,KAAK,KAAK,KAAK,EAAE,OAAO,0BAA0B,IAAI,OAAO,GAAG,IAAI,WAAW,CAAC;EAClF,SAAS,OAAO;GAGd,KAAK,KAFU,iBAAiB,YAAY,MAAM,SAAS,KAEzC,EAAE,OAAO,MADX,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC3B,IAAI,IAAI,EAAE,CAAC;EACvD;CACF;AACF;AAGA,SAAS,OAAO,QAAgB,MAAc,cAAuC;CACnF,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,WAAW,UAAiC;GAChD,IAAI,MAAM,SAAS,gBAAgB,eAAe,GAAG;IACnD,OAAO,eAAe,SAAS,OAAO;IACtC,QAAQ,OAAO,QAAQ,OAAO,GAAG,eAAe,CAAC,CAAC;IAClD;GACF;GACA,OAAO,KAAK;EACd;EACA,OAAO,KAAK,SAAS,OAAO;EAC5B,OAAO,OAAO,MAAM,mBAAmB;GACrC,OAAO,eAAe,SAAS,OAAO;GAEtC,MAAM,QAAQ,OAAO,QAAQ;GAC7B,QAAQ,OAAO,UAAU,YAAY,UAAU,OAAO,MAAM,OAAO,IAAI;EACzE,CAAC;CACH,CAAC;AACH;AAEA,eAAsB,YACpB,KACA,UAAwB,CAAC,GACF;CACvB,MAAM,QAAQ,QAAQ,SAAS,SAAS;CACxC,MAAM,SAAS,aAAa;CAE5B,IAAI,OAAO,QAAQ,QAAQ;CAC3B,OAAO,GAAG,YAAY,KAAK,QAAQ,KAAK,gBAAgB,KAAK,MAAM,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC;CACnF,OAAO,MAAM,OAAO,QAAQ,MAAM,EAAE;CAEpC,OAAO;EACL;EACA;EACA;EACA,KAAK,oBAAoB,KAAK,MAAM;EACpC,aACE,IAAI,SAAe,SAAS,WAC1B,OAAO,OAAO,UAAW,QAAQ,OAAO,KAAK,IAAI,QAAQ,CAAE,CAC7D;CACJ;AACF;;;AClNA,IAAI;CACF,MAAM,EAAE,WAAW,UAAU,EAC3B,SAAS;EACP,MAAM,EAAE,MAAM,SAAS;EACvB,MAAM,EAAE,MAAM,SAAS;EACvB,MAAM,EAAE,MAAM,UAAU;CAC1B,EACF,CAAC;CACD,MAAM,OAAO,OAAO,SAAS,KAAA,IAAY,KAAA,IAAY,OAAO,OAAO,IAAI;CACvE,IAAI,SAAS,KAAA,KAAa,CAAC,OAAO,UAAU,IAAI,GAC9C,MAAM,IAAI,MAAM,yCAAyC,OAAO,KAAK,EAAE;CAEzE,MAAM,MAAM,MAAM,WAAW,OAAO,QAAQ,QAAQ,IAAI,CAAC;CAGzD,IAAI,OAAO,MACT,QAAQ,IAAI,KAAK,UAAU,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,CAAC;MACrD;EACL,MAAM,SAAS,MAAM,YAAY,KAAK,EAAE,KAAK,CAAC;EAC9C,MAAM,QAAQ,MAAM,WAAW,GAAG;EAClC,MAAM,UAAU,MAAM,OAAO,QAAQ,QAAQ,GAAG,MAAM,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC;EACrF,MAAM,SAAS,OAAO,OAAO,MAAM,MAAM,CAAC,CAAC,QAAQ,GAAG,SAAS,IAAI,KAAK,QAAQ,CAAC;EACjF,QAAQ,IAAI,wBAAwB,OAAO,KAAK;EAChD,QAAQ,IAAI,sBAAsB,IAAI,MAAM;EAC5C,QAAQ,IACN,sBAAsB,QAAQ,MAAM,OAAO,UAAU,SAAS,EAAE,KAC3D,QAAQ,kBAAkB,QAAQ,QAAQ,OAAO,GACxD;EACA,KAAK,MAAM,WAAW,MAAM,UAAU,QAAQ,IAAI,OAAO,QAAQ,MAAM,IAAI,QAAQ,SAAS;EAC5F,QAAQ,IAAI,sBAAsB;CACpC;AACF,SAAS,OAAO;CACd,QAAQ,MAAM,eAAe,KAAK,CAAC;CACnC,QAAQ,WAAW;AACrB"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":["readJob"],"sources":["../src/http.ts","../src/triage.ts","../src/api.ts","../src/jobs.ts","../src/actions.ts","../src/history.ts","../src/assets.ts","../src/guard.ts","../src/server.ts","../src/cli.ts"],"sourcesContent":["// A client mistake is not a server fault, so the status rides with the error, not a blanket 500.\nexport class HttpError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message.startsWith('[verbaly]') ? message : `[verbaly] ${message}`);\n this.status = status;\n this.name = 'HttpError';\n }\n}\n\nexport const badRequest = (message: string) => new HttpError(400, message);\n\n// The absolute path of someone's project is not the browser's business.\nexport function scrub(message: string, root: string): string {\n return root ? message.split(root).join('.') : message;\n}\n","import type { Catalog } from '@verbaly/compiler';\n\nexport type TriageSignal = 'divergent' | 'collision' | 'echo' | 'digits' | 'code' | 'url';\n\nexport interface TriageReason {\n signal: TriageSignal;\n text: string;\n}\n\nexport type TriageResult = Record<string, TriageReason[]>;\n\n// check() already caught the structure, so these only point at the few worth reading first.\nexport interface TriageInput {\n source: Catalog;\n target: Catalog;\n reviewed: Catalog[];\n}\n\nconst DIGITS = /\\d[\\d.,]*/g;\nconst URLS = /https?:\\/\\/[^\\s<)\"']+/g;\nconst CODE = /<code>([^<]+)<\\/code>/g;\n\nfunction bag(text: string, re: RegExp, normalize?: (v: string) => string): string[] {\n const found = text.match(re) ?? [];\n return (normalize ? found.map(normalize) : found).sort();\n}\n\nfunction same(a: string[], b: string[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n\n// A number or a url at the end of a clause takes the punctuation with it, and that is not a signal.\nconst trimPunct = (v: string) => v.replace(/[.,;:!?)\\]]+$/, '');\n// A separator is idiomatic (3.09 is 3,09 in Spanish); canonizing keeps 1.5 apart from 15.\nconst bareDigits = (v: string) => trimPunct(v).replaceAll(/[.,]/g, '.');\n\nfunction push(out: TriageResult, key: string, reason: TriageReason): void {\n (out[key] ??= []).push(reason);\n}\n\nexport function triage({ source, target, reviewed }: TriageInput): TriageResult {\n // null-prototype: a source text of \"__proto__\" or \"toString\" is a string, not a member of Object\n const out: TriageResult = Object.create(null);\n const keys = Object.keys(source);\n\n // One source text that two humans rendered two ways is ambiguous, so the machine had no chance.\n const bySource: Record<string, string[]> = Object.create(null);\n for (const key of keys) {\n const text = source[key]?.trim();\n if (text) (bySource[text] ??= []).push(key);\n }\n for (const [text, group] of Object.entries(bySource)) {\n if (group.length < 2) continue;\n const divergent = reviewed.some(\n (catalog) => new Set(group.map((k) => catalog[k]?.trim() ?? '').filter(Boolean)).size > 1,\n );\n if (divergent) {\n for (const key of group) {\n push(out, key, { signal: 'divergent', text: `\"${text}\" was already translated two ways` });\n }\n }\n // The same ambiguity seen from the result instead of from the history.\n const targets = new Set(group.map((key) => target[key]?.trim() ?? '').filter(Boolean));\n if (!divergent && targets.size > 1) {\n for (const key of group) {\n push(out, key, { signal: 'collision', text: `\"${text}\" came back as two different translations` });\n }\n }\n }\n\n for (const key of keys) {\n const src = source[key]?.trim() ?? '';\n const trg = target[key]?.trim() ?? '';\n if (!src || !trg) continue;\n\n // Only the locales with an opinion on this key vote: alone it fires on every do-not-translate.\n const opinions = reviewed.map((c) => c[key]?.trim()).filter((v) => v !== undefined && v !== '');\n if (trg === src && opinions.length > 0 && opinions.every((v) => v !== src)) {\n push(out, key, { signal: 'echo', text: 'still identical to the source' });\n }\n\n // a translation that adds a number is idiomatic (\"refresh\" is \"F5\"); one that changes it is not\n const srcDigits = bag(src, DIGITS, bareDigits);\n if (srcDigits.length > 0 && !same(srcDigits, bag(trg, DIGITS, bareDigits))) {\n push(out, key, { signal: 'digits', text: 'the numbers do not match the source' });\n }\n if (!same(bag(src, URLS, trimPunct), bag(trg, URLS, trimPunct))) {\n push(out, key, { signal: 'url', text: 'a URL changed' });\n }\n if (!same(bag(src, CODE), bag(trg, CODE))) {\n push(out, key, { signal: 'code', text: 'the contents of a <code> span changed' });\n }\n }\n\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport {\n check,\n clearDrafts,\n collectOrigins,\n doctor,\n effectiveDrafts,\n extractProject,\n loadDrafts,\n markDrafts,\n readCatalog,\n saveDrafts,\n status,\n targetLocales,\n validateMessage,\n validatePair,\n writeCatalog,\n} from '@verbaly/compiler';\nimport { DRAFTS_FILE } from '@verbaly/compiler';\nimport type {\n Catalog,\n Catalogs,\n CheckResult,\n DoctorResult,\n Drafts,\n ResolvedConfig,\n StatusResult,\n} from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { triage, type TriageResult } from './triage';\n\nexport interface StudioProblem {\n scope: string;\n message: string;\n}\n\nexport interface StudioState {\n root: string;\n dir: string;\n sourceLocale: string;\n locales: string[];\n scanning: boolean;\n catalogs: Catalogs;\n origins: Record<string, string[]>;\n status: StatusResult;\n check: CheckResult;\n drafts: Drafts;\n triage: Record<string, TriageResult>;\n problems: StudioProblem[];\n}\n\n// A locale nobody can parse must not take the panel down: Studio is what you open to fix it.\nfunction readAll(cfg: ResolvedConfig): { catalogs: Catalogs; problems: StudioProblem[] } {\n const catalogs: Catalogs = {};\n const problems: StudioProblem[] = [];\n // an empty green panel and a wrong --root look identical, and only this line tells them apart\n if (!existsSync(cfg.dir)) {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/');\n problems.push({ scope: dir, message: '[verbaly] no catalogs here, run npx verbaly init or check --root' });\n }\n for (const locale of cfg.locales) {\n try {\n catalogs[locale] = readCatalog(cfg, locale);\n } catch (error) {\n catalogs[locale] = {};\n problems.push({\n scope: locale,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return { catalogs, problems };\n}\n\n// A sidecar nobody can parse is the other file Studio exists to fix, so it degrades like a catalog.\nfunction readDrafts(cfg: ResolvedConfig): { drafts: Drafts; problems: StudioProblem[] } {\n try {\n return { drafts: loadDrafts(cfg), problems: [] };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { drafts: {}, problems: [{ scope: DRAFTS_FILE, message }] };\n }\n}\n\n// check() reports the file a stray key was used in as an absolute path, origins already do not.\nfunction relativize(cfg: ResolvedConfig, result: CheckResult): CheckResult {\n return {\n ...result,\n unknown: result.unknown.map((entry) => ({\n ...entry,\n files: entry.files.map((file) => relative(cfg.root, file).replaceAll('\\\\', '/')),\n })),\n };\n}\n\n// One shot and unpaginated: the biggest catalog we know is past 1600 messages, instant locally.\nexport async function buildState(cfg: ResolvedConfig): Promise<StudioState> {\n const { catalogs, problems } = readAll(cfg);\n const registry = await extractProject(cfg);\n const sidecar = readDrafts(cfg);\n problems.push(...sidecar.problems);\n const live = effectiveDrafts(sidecar.drafts, catalogs);\n const source = (catalogs[cfg.sourceLocale] ?? {}) as Catalog;\n const targets = targetLocales(cfg);\n\n for (const { file, message } of registry.parseErrors()) {\n problems.push({ scope: relative(cfg.root, file).replaceAll('\\\\', '/'), message });\n }\n\n const perLocale: Record<string, TriageResult> = {};\n for (const locale of targets) {\n perLocale[locale] = triage({\n source,\n target: (catalogs[locale] ?? {}) as Catalog,\n // a locale still carrying drafts has not been reviewed, so it cannot be the control\n reviewed: targets\n .filter((other) => other !== locale && !(live[other] ?? []).length)\n .map((other) => (catalogs[other] ?? {}) as Catalog),\n });\n }\n\n return {\n root: cfg.root,\n dir: cfg.dir,\n sourceLocale: cfg.sourceLocale,\n locales: cfg.locales,\n // with include: [] nothing is scanned, so an empty origins map is off, not \"none found\"\n scanning: cfg.include.length > 0,\n catalogs,\n origins: await collectOrigins(cfg, registry),\n status: status(cfg, catalogs, registry, live),\n check: relativize(cfg, check(cfg, catalogs, registry)),\n drafts: live,\n triage: perLocale,\n problems,\n };\n}\n\nexport function health(cfg: ResolvedConfig): Promise<DoctorResult> {\n return doctor(cfg);\n}\n\nexport interface WriteMessageResult {\n locale: string;\n key: string;\n clearedDraft: boolean;\n}\n\n// A human wrote it, so it is reviewed: the rule import already applies in run.ts:447.\nexport function writeMessage(\n cfg: ResolvedConfig,\n locale: string,\n key: string,\n text: string,\n): WriteMessageResult {\n if (locale === cfg.sourceLocale) {\n throw badRequest('the source text lives in your code, Studio never edits it');\n }\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const source = readCatalog(cfg, cfg.sourceLocale);\n // hasOwn, not `in`: `in` walks the prototype, so toString and __proto__ would pass this guard\n if (!Object.hasOwn(source, key)) {\n throw badRequest(`\"${key}\" is not in the source catalog, so Studio will not create it`);\n }\n // '' is untranslated everywhere else, so whitespace is that and not a translation to validate\n const value = text.trim() ? text : '';\n // the same two calls check() makes: validatePair alone misses a plural block with no other case\n const issues = value\n ? [...validateMessage(value, locale), ...validatePair(source[key] as string, value)]\n : [];\n const errors = issues.filter((issue) => issue.severity === 'error');\n if (errors.length) {\n throw badRequest(`${errors.map((issue) => issue.message).join('; ')}`);\n }\n\n const catalog = { ...readCatalog(cfg, locale), [key]: value };\n writeCatalog(cfg, locale, catalog);\n\n const drafts = loadDrafts(cfg);\n const clearedDraft = (drafts[locale] ?? []).includes(key);\n clearDrafts(drafts, locale, [key]);\n saveDrafts(cfg, drafts);\n return { locale, key, clearedDraft };\n}\n\nexport interface ApproveResult {\n locale: string;\n approved: number;\n keys: string[];\n}\n\n// The sidecar is re-read here: saveDrafts writes every locale, so a stale copy drops another's.\nexport function approve(cfg: ResolvedConfig, locale: string, keys?: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n const had = drafts[locale] ?? [];\n // the keys it really cleared, because undo has to put back exactly those and nothing else\n const cleared = keys ? had.filter((key) => keys.includes(key)) : [...had];\n clearDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: cleared.length, keys: cleared };\n}\n\n// Undo is not a nicety here: the flag records who wrote the text, so restoring it restores a fact.\nexport function unapprove(cfg: ResolvedConfig, locale: string, keys: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n markDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: keys.length, keys };\n}\n","import { badRequest, HttpError } from './http';\n\nexport type JobState = 'running' | 'done' | 'failed';\n\nexport interface Job {\n id: string;\n kind: 'translate';\n state: JobState;\n total: number;\n done: number;\n locale?: string;\n message?: string;\n result?: unknown;\n}\n\n// One at a time, because two runs over the same catalogs is a race over the same files.\nlet current: Job | null = null;\nlet counter = 0;\n\nexport function running(): Job | null {\n return current?.state === 'running' ? current : null;\n}\n\nexport function read(id: string): Job {\n if (!current || current.id !== id) throw new HttpError(404, `no job called \"${id}\"`);\n return current;\n}\n\nexport function start(kind: Job['kind'], total: number): Job {\n if (running()) throw badRequest('a job is already running, wait for it or read its progress');\n counter += 1;\n current = { id: `${kind}-${counter}`, kind, state: 'running', total, done: 0 };\n return current;\n}\n\n// A batch that failed still finishes: the bar reports work attempted, and message says what broke.\nexport function advance(id: string, keys: number, locale: string, error?: string): void {\n if (current?.id !== id) return;\n current.done = Math.min(current.done + keys, current.total);\n current.locale = locale;\n if (error) current.message = error;\n}\n\n// A run that writes part of its work and then fails is a success for what it wrote, so both land.\nexport function finish(id: string, state: 'done' | 'failed', patch: Partial<Job> = {}): void {\n if (current?.id === id) Object.assign(current, patch, { state });\n}\n","import {\n collectOrigins,\n extractProject,\n loadCatalogs,\n resolveProvider,\n syncCatalogs,\n translateCatalogs,\n writeCatalog,\n writeDts,\n markDrafts,\n loadDrafts,\n saveDrafts,\n} from '@verbaly/compiler';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { advance, finish, start, type Job } from './jobs';\n\nexport interface ExtractResult {\n added: Record<string, string[]>;\n // only the source locale counts as new text: a target gains a blank for every gap it had\n found: number;\n messages: number;\n}\n\n// Local, fast and free, so it answers in the same request instead of becoming a job.\nexport async function runExtract(cfg: ResolvedConfig): Promise<ExtractResult> {\n if (!cfg.include.length) {\n throw badRequest('source scanning is off (include: []), so there is nothing to extract');\n }\n const registry = await extractProject(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = syncCatalogs(cfg, catalogs, registry);\n for (const locale of cfg.locales) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n // the types come from the source catalog, and cfg.dts false means the project opted out\n if (cfg.dts !== false) writeDts(cfg, catalogs[cfg.sourceLocale] ?? {}, cfg.dts);\n const found = result.added[cfg.sourceLocale]?.length ?? 0;\n return { added: result.added, found, messages: registry.messages().size };\n}\n\nexport interface Plan {\n pending: Record<string, string[]>;\n total: number;\n}\n\n// translate is the one command that spends money and minutes, so the panel always shows the bill.\nexport async function planTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Plan> {\n const provider = await resolveProvider(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, { locales, dryRun: true });\n const total = Object.values(result.pending).reduce((n, keys) => n + keys.length, 0);\n return { pending: result.pending, total };\n}\n\nexport async function startTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Job> {\n const provider = await resolveProvider(cfg);\n // the job carries its own denominator, so progress reads the same whether or not you asked first\n const plan = await planTranslate(cfg, locales);\n const job = start('translate', plan.total);\n const id = job.id;\n\n // the run outlives this request on purpose: the client asks the job how it is going\n void (async () => {\n try {\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, {\n locales,\n batchSize: cfg.translate.batchSize,\n concurrency: cfg.translate.concurrency,\n retries: cfg.translate.retries,\n origins: await collectOrigins(cfg),\n onProgress: (p) => advance(id, p.keys, p.locale, p.error),\n });\n for (const [locale, keys] of Object.entries(result.translated)) {\n if (keys.length) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n }\n // what a machine wrote stays a draft: the panel does not get to change that rule\n const drafts = loadDrafts(cfg);\n for (const [locale, keys] of Object.entries(result.translated)) {\n markDrafts(drafts, locale, keys);\n }\n saveDrafts(cfg, drafts);\n finish(id, result.failed.length ? 'failed' : 'done', {\n result,\n message: result.failed.length ? `${result.failed.length} batches did not answer` : undefined,\n });\n } catch (error) {\n finish(id, 'failed', { message: error instanceof Error ? error.message : String(error) });\n }\n })();\n\n return job;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { relative } from 'node:path';\nimport type { ResolvedConfig } from '@verbaly/compiler';\n\nconst run = promisify(execFile);\n\nexport interface Commit {\n sha: string;\n author: string;\n date: string;\n subject: string;\n}\n\n// one field separator that no subject can contain, written as the escape and never as the byte\nconst FIELD = '\\u001f';\nconst FORMAT = `--format=%H${FIELD}%an${FIELD}%aI${FIELD}%s`;\n\n// split out so the shape of a log line is tested without a repository and without writing one\nexport function parseLog(stdout: string): Commit[] {\n const commits: Commit[] = [];\n for (const line of stdout.split('\\n')) {\n const [sha, author, date, ...rest] = line.split(FIELD);\n // a subject holds anything but a newline, so it is the last field and is rejoined\n if (!sha || !author || !date || !rest.length) continue;\n commits.push({ sha: sha.slice(0, 7), author, date, subject: rest.join(FIELD) });\n }\n return commits;\n}\n\n// git is asked, never assumed: no repository and no git both mean there is no history to show\nexport async function catalogHistory(cfg: ResolvedConfig, limit = 5): Promise<Commit[]> {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/') || '.';\n try {\n const { stdout } = await run('git', ['log', `-n${limit}`, FORMAT, '--', dir], {\n cwd: cfg.root,\n timeout: 3000,\n windowsHide: true,\n });\n return parseLog(stdout);\n } catch {\n return [];\n }\n}\n","import { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, normalize, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// the built panel sits beside the compiled server, so it is found relative to this file, never cwd\nconst UI = resolve(fileURLToPath(new URL('.', import.meta.url)), 'ui');\n\nconst TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.woff2': 'font/woff2',\n '.json': 'application/json; charset=utf-8',\n '.ico': 'image/x-icon',\n};\n\nexport interface Asset {\n body: Buffer;\n type: string;\n}\n\nexport const uiBuilt = (): boolean => existsSync(join(UI, 'index.html'));\n\n// A path is resolved and then checked to still be inside UI: ../ and an absolute one both land out.\nexport function readAsset(pathname: string): Asset | undefined {\n const wanted = pathname === '/' ? '/index.html' : pathname;\n const target = resolve(join(UI, normalize(wanted)));\n if (target !== UI && !target.startsWith(UI + (process.platform === 'win32' ? '\\\\' : '/'))) {\n return undefined;\n }\n if (!existsSync(target) || !statSync(target).isFile()) return undefined;\n const dot = target.lastIndexOf('.');\n return {\n body: readFileSync(target),\n type: TYPES[target.slice(dot).toLowerCase()] ?? 'application/octet-stream',\n };\n}\n","import { randomBytes, timingSafeEqual } from 'node:crypto';\n\nexport interface GuardOptions {\n port: number;\n token: string;\n}\n\n// A local server that writes files is reachable from any page the browser has open.\nexport function newToken(): string {\n return randomBytes(9).toString('base64url');\n}\n\n// Only the two names that resolve to this machine. A DNS rebind arrives with a foreign Host.\nexport function hostAllowed(host: string | undefined, port: number): boolean {\n // a browser omits the port when it is the scheme default, so :80 would 403 every real request\n const names = port === 80 ? ['127.0.0.1', 'localhost'] : [];\n return [`127.0.0.1:${port}`, `localhost:${port}`, ...names].includes(host ?? '');\n}\n\n// No Origin at all is a same-origin navigation or a curl, both fine; a foreign one never is.\nexport function originAllowed(origin: string | undefined, port: number): boolean {\n if (origin === undefined) return true;\n return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;\n}\n\n// Compared in constant time so the token cannot be guessed one character at a time.\nexport function tokenMatches(given: string | null, expected: string): boolean {\n if (given === null) return false;\n const a = Buffer.from(given);\n const b = Buffer.from(expected);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nexport interface GuardVerdict {\n ok: boolean;\n status: number;\n reason: string;\n}\n\nconst PASS: GuardVerdict = { ok: true, status: 200, reason: '' };\n\nexport function guardRequest(\n headers: { host?: string; origin?: string },\n url: URL,\n { port, token }: GuardOptions,\n): GuardVerdict {\n if (!hostAllowed(headers.host, port)) {\n return { ok: false, status: 403, reason: '[verbaly] unexpected Host header' };\n }\n if (!originAllowed(headers.origin, port)) {\n return { ok: false, status: 403, reason: '[verbaly] cross-origin request' };\n }\n if (!tokenMatches(url.searchParams.get('t'), token)) {\n return { ok: false, status: 401, reason: '[verbaly] missing or wrong token, open the printed url' };\n }\n return PASS;\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { approve, buildState, health, unapprove, writeMessage } from './api';\nimport { planTranslate, runExtract, startTranslate } from './actions';\nimport { read as readJob, running } from './jobs';\nimport { catalogHistory } from './history';\nimport { readAsset, uiBuilt } from './assets';\nimport { guardRequest, newToken } from './guard';\nimport { HttpError, badRequest, scrub } from './http';\n\nexport interface StudioServer {\n server: Server;\n port: number;\n token: string;\n url: string;\n close: () => Promise<void>;\n}\n\nexport interface StartOptions {\n port?: number;\n token?: string;\n}\n\nconst DEFAULT_PORT = 4747;\nconst MAX_BODY = 1_000_000;\n\nfunction send(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-store',\n });\n res.end(JSON.stringify(body));\n}\n\nasync function readJson(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of req) {\n size += (chunk as Buffer).length;\n if (size > MAX_BODY) throw new HttpError(413, 'request body too large');\n chunks.push(chunk as Buffer);\n }\n if (!chunks.length) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));\n } catch {\n throw badRequest('body is not valid JSON');\n }\n // null and an array both pass typeof 'object', and reading .text off them is a 500\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw badRequest('body must be a JSON object');\n }\n return parsed as Record<string, unknown>;\n}\n\nfunction segment(raw: string | undefined, what: string): string {\n let value: string;\n try {\n value = decodeURIComponent(raw ?? '');\n } catch {\n throw badRequest(`the ${what} in the url is not valid percent-encoding`);\n }\n if (!value) throw badRequest(`the url is missing a ${what}`);\n return value;\n}\n\n// One page, JSON on every route: a framework would only add a dependency to a local tool.\nexport function createStudioApp(cfg: ResolvedConfig, port: number, token: string) {\n return async function handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // The url is built inside the try: `GET //` throws, and out here that would kill the process.\n try {\n let url: URL;\n try {\n url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);\n } catch {\n throw badRequest('the request target is not a valid url');\n }\n\n const api = url.pathname.startsWith('/api/');\n const verdict = guardRequest({ host: req.headers.host, origin: req.headers.origin }, url, {\n port,\n token,\n });\n // the panel files are the published npm package: only the project data needs a token\n if (!verdict.ok && (api || verdict.status !== 401)) {\n send(res, verdict.status, { error: verdict.reason });\n return;\n }\n\n if (!api && req.method === 'GET') {\n const asset = readAsset(url.pathname);\n if (asset) {\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'no-store' });\n res.end(asset.body);\n return;\n }\n if (url.pathname === '/' && !uiBuilt()) {\n throw new HttpError(500, 'the panel is not in this install, so only /api/* answers here');\n }\n }\n\n if (req.method === 'GET' && url.pathname === '/api/state') {\n send(res, 200, await buildState(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/history') {\n send(res, 200, { commits: await catalogHistory(cfg) });\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/health') {\n send(res, 200, await health(cfg));\n return;\n }\n if (req.method === 'PUT' && url.pathname.startsWith('/api/message/')) {\n const rest = url.pathname.slice('/api/message/'.length).split('/');\n const locale = segment(rest[0], 'locale');\n const key = segment(rest.slice(1).join('/'), 'key');\n const body = await readJson(req);\n if (typeof body.text !== 'string') throw badRequest('body needs a \"text\" string');\n send(res, 200, writeMessage(cfg, locale, key, body.text));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/approve') {\n const body = await readJson(req);\n if (typeof body.locale !== 'string') throw badRequest('body needs a \"locale\" string');\n const keys = Array.isArray(body.keys)\n ? body.keys.filter((k): k is string => typeof k === 'string')\n : undefined;\n if (body.undo === true) {\n if (!keys?.length) throw badRequest('undoing needs the \"keys\" it should put back');\n send(res, 200, unapprove(cfg, body.locale, keys));\n return;\n }\n send(res, 200, approve(cfg, body.locale, keys));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/extract') {\n send(res, 200, await runExtract(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/translate') {\n const locales = url.searchParams.getAll('locale');\n send(res, 200, await planTranslate(cfg, locales.length ? locales : undefined));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/translate') {\n const body = await readJson(req);\n const locales = Array.isArray(body.locales)\n ? body.locales.filter((l): l is string => typeof l === 'string')\n : undefined;\n send(res, 200, await startTranslate(cfg, locales?.length ? locales : undefined));\n return;\n }\n // a reload loses the id, so the panel asks what is running rather than losing the bar\n if (req.method === 'GET' && url.pathname === '/api/job') {\n send(res, 200, running());\n return;\n }\n if (req.method === 'GET' && url.pathname.startsWith('/api/job/')) {\n send(res, 200, readJob(segment(url.pathname.slice('/api/job/'.length), 'job id')));\n return;\n }\n\n send(res, 404, { error: `[verbaly] no route for ${req.method} ${url.pathname}` });\n } catch (error) {\n const status = error instanceof HttpError ? error.status : 500;\n const message = error instanceof Error ? error.message : String(error);\n send(res, status, { error: scrub(message, cfg.root) });\n }\n };\n}\n\n// A busy port climbs instead of failing: this is a local tool, not a service on a fixed address.\nfunction listen(server: Server, port: number, attemptsLeft: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const onError = (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE' && attemptsLeft > 0) {\n server.removeListener('error', onError);\n resolve(listen(server, port + 1, attemptsLeft - 1));\n return;\n }\n reject(error);\n };\n server.once('error', onError);\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', onError);\n // port 0 asks the system to pick, so the bound address is the only place the answer is\n const bound = server.address() as AddressInfo | string | null;\n resolve(typeof bound === 'object' && bound !== null ? bound.port : port);\n });\n });\n}\n\nexport async function startStudio(\n cfg: ResolvedConfig,\n options: StartOptions = {},\n): Promise<StudioServer> {\n const token = options.token ?? newToken();\n const server = createServer();\n // The handler is attached before listen so no request can arrive without one.\n let port = options.port ?? DEFAULT_PORT;\n server.on('request', (req, res) => void createStudioApp(cfg, port, token)(req, res));\n port = await listen(server, port, 20);\n\n return {\n server,\n port,\n token,\n url: `http://127.0.0.1:${port}/?t=${token}`,\n close: () =>\n new Promise<void>((resolve, reject) =>\n server.close((error) => (error ? reject(error) : resolve())),\n ),\n };\n}\n","#!/usr/bin/env node\nimport { parseArgs } from 'node:util';\nimport { counted, formatCliError, loadConfig } from '@verbaly/compiler';\nimport { buildState } from './api';\nimport { startStudio } from './server';\n\ntry {\n const { values } = parseArgs({\n options: {\n root: { type: 'string' },\n port: { type: 'string' },\n json: { type: 'boolean' },\n },\n });\n const port = values.port === undefined ? undefined : Number(values.port);\n if (port !== undefined && !Number.isInteger(port)) {\n throw new Error(`[verbaly] --port needs a number, got \"${values.port}\"`);\n }\n const cfg = await loadConfig(values.root ?? process.cwd());\n\n // --json is the state the interface reads, on stdout, before any interface exists.\n if (values.json) {\n console.log(JSON.stringify(await buildState(cfg), null, 2));\n } else {\n const studio = await startStudio(cfg, { port });\n const state = await buildState(cfg);\n const missing = state.status.locales.reduce((n, l) => n + (l.total - l.translated), 0);\n const drafts = Object.values(state.drafts).reduce((n, keys) => n + keys.length, 0);\n console.log(`\\n Verbaly Studio ${studio.url}`);\n console.log(` Project ${cfg.root}`);\n console.log(\n ` Catalog ${counted(state.status.messages, 'message')} · ` +\n `${missing} untranslated · ${counted(drafts, 'draft')}`,\n );\n for (const problem of state.problems) console.log(` ! ${problem.scope}: ${problem.message}`);\n console.log('\\n Ctrl+C to stop\\n');\n }\n} catch (error) {\n console.error(formatCliError(error));\n process.exitCode = 1;\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -312,11 +312,24 @@ async function startTranslate(cfg, locales) {
|
|
|
312
312
|
const run = promisify(execFile);
|
|
313
313
|
const FIELD = "";
|
|
314
314
|
const FORMAT = `--format=%H${FIELD}%an${FIELD}%aI${FIELD}%s`;
|
|
315
|
+
function parseLog(stdout) {
|
|
316
|
+
const commits = [];
|
|
317
|
+
for (const line of stdout.split("\n")) {
|
|
318
|
+
const [sha, author, date, ...rest] = line.split(FIELD);
|
|
319
|
+
if (!sha || !author || !date || !rest.length) continue;
|
|
320
|
+
commits.push({
|
|
321
|
+
sha: sha.slice(0, 7),
|
|
322
|
+
author,
|
|
323
|
+
date,
|
|
324
|
+
subject: rest.join(FIELD)
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
return commits;
|
|
328
|
+
}
|
|
315
329
|
async function catalogHistory(cfg, limit = 5) {
|
|
316
330
|
const dir = relative(cfg.root, cfg.dir).replaceAll("\\", "/") || ".";
|
|
317
|
-
let stdout;
|
|
318
331
|
try {
|
|
319
|
-
stdout =
|
|
332
|
+
const { stdout } = await run("git", [
|
|
320
333
|
"log",
|
|
321
334
|
`-n${limit}`,
|
|
322
335
|
FORMAT,
|
|
@@ -326,22 +339,11 @@ async function catalogHistory(cfg, limit = 5) {
|
|
|
326
339
|
cwd: cfg.root,
|
|
327
340
|
timeout: 3e3,
|
|
328
341
|
windowsHide: true
|
|
329
|
-
})
|
|
342
|
+
});
|
|
343
|
+
return parseLog(stdout);
|
|
330
344
|
} catch {
|
|
331
345
|
return [];
|
|
332
346
|
}
|
|
333
|
-
const commits = [];
|
|
334
|
-
for (const line of stdout.split("\n")) {
|
|
335
|
-
const [sha, author, date, ...rest] = line.split(FIELD);
|
|
336
|
-
if (!sha || !author || !date) continue;
|
|
337
|
-
commits.push({
|
|
338
|
-
sha: sha.slice(0, 7),
|
|
339
|
-
author,
|
|
340
|
-
date,
|
|
341
|
-
subject: rest.join(FIELD)
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
return commits;
|
|
345
347
|
}
|
|
346
348
|
//#endregion
|
|
347
349
|
//#region src/assets.ts
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["readJob"],"sources":["../src/http.ts","../src/triage.ts","../src/api.ts","../src/jobs.ts","../src/actions.ts","../src/history.ts","../src/assets.ts","../src/guard.ts","../src/server.ts"],"sourcesContent":["// A client mistake is not a server fault, so the status rides with the error, not a blanket 500.\nexport class HttpError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message.startsWith('[verbaly]') ? message : `[verbaly] ${message}`);\n this.status = status;\n this.name = 'HttpError';\n }\n}\n\nexport const badRequest = (message: string) => new HttpError(400, message);\n\n// The absolute path of someone's project is not the browser's business.\nexport function scrub(message: string, root: string): string {\n return root ? message.split(root).join('.') : message;\n}\n","import type { Catalog } from '@verbaly/compiler';\n\nexport type TriageSignal = 'divergent' | 'collision' | 'echo' | 'digits' | 'code' | 'url';\n\nexport interface TriageReason {\n signal: TriageSignal;\n text: string;\n}\n\nexport type TriageResult = Record<string, TriageReason[]>;\n\n// check() already caught the structure, so these only point at the few worth reading first.\nexport interface TriageInput {\n source: Catalog;\n target: Catalog;\n reviewed: Catalog[];\n}\n\nconst DIGITS = /\\d[\\d.,]*/g;\nconst URLS = /https?:\\/\\/[^\\s<)\"']+/g;\nconst CODE = /<code>([^<]+)<\\/code>/g;\n\nfunction bag(text: string, re: RegExp, normalize?: (v: string) => string): string[] {\n const found = text.match(re) ?? [];\n return (normalize ? found.map(normalize) : found).sort();\n}\n\nfunction same(a: string[], b: string[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n\n// A number or a url at the end of a clause takes the punctuation with it, and that is not a signal.\nconst trimPunct = (v: string) => v.replace(/[.,;:!?)\\]]+$/, '');\n// A separator is idiomatic (3.09 is 3,09 in Spanish); canonizing keeps 1.5 apart from 15.\nconst bareDigits = (v: string) => trimPunct(v).replaceAll(/[.,]/g, '.');\n\nfunction push(out: TriageResult, key: string, reason: TriageReason): void {\n (out[key] ??= []).push(reason);\n}\n\nexport function triage({ source, target, reviewed }: TriageInput): TriageResult {\n // null-prototype: a source text of \"__proto__\" or \"toString\" is a string, not a member of Object\n const out: TriageResult = Object.create(null);\n const keys = Object.keys(source);\n\n // One source text that two humans rendered two ways is ambiguous, so the machine had no chance.\n const bySource: Record<string, string[]> = Object.create(null);\n for (const key of keys) {\n const text = source[key]?.trim();\n if (text) (bySource[text] ??= []).push(key);\n }\n for (const [text, group] of Object.entries(bySource)) {\n if (group.length < 2) continue;\n const divergent = reviewed.some(\n (catalog) => new Set(group.map((k) => catalog[k]?.trim() ?? '').filter(Boolean)).size > 1,\n );\n if (divergent) {\n for (const key of group) {\n push(out, key, { signal: 'divergent', text: `\"${text}\" was already translated two ways` });\n }\n }\n // The same ambiguity seen from the result instead of from the history.\n const targets = new Set(group.map((key) => target[key]?.trim() ?? '').filter(Boolean));\n if (!divergent && targets.size > 1) {\n for (const key of group) {\n push(out, key, { signal: 'collision', text: `\"${text}\" came back as two different translations` });\n }\n }\n }\n\n for (const key of keys) {\n const src = source[key]?.trim() ?? '';\n const trg = target[key]?.trim() ?? '';\n if (!src || !trg) continue;\n\n // Only the locales with an opinion on this key vote: alone it fires on every do-not-translate.\n const opinions = reviewed.map((c) => c[key]?.trim()).filter((v) => v !== undefined && v !== '');\n if (trg === src && opinions.length > 0 && opinions.every((v) => v !== src)) {\n push(out, key, { signal: 'echo', text: 'still identical to the source' });\n }\n\n // a translation that adds a number is idiomatic (\"refresh\" is \"F5\"); one that changes it is not\n const srcDigits = bag(src, DIGITS, bareDigits);\n if (srcDigits.length > 0 && !same(srcDigits, bag(trg, DIGITS, bareDigits))) {\n push(out, key, { signal: 'digits', text: 'the numbers do not match the source' });\n }\n if (!same(bag(src, URLS, trimPunct), bag(trg, URLS, trimPunct))) {\n push(out, key, { signal: 'url', text: 'a URL changed' });\n }\n if (!same(bag(src, CODE), bag(trg, CODE))) {\n push(out, key, { signal: 'code', text: 'the contents of a <code> span changed' });\n }\n }\n\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport {\n check,\n clearDrafts,\n collectOrigins,\n doctor,\n effectiveDrafts,\n extractProject,\n loadDrafts,\n markDrafts,\n readCatalog,\n saveDrafts,\n status,\n targetLocales,\n validateMessage,\n validatePair,\n writeCatalog,\n} from '@verbaly/compiler';\nimport { DRAFTS_FILE } from '@verbaly/compiler';\nimport type {\n Catalog,\n Catalogs,\n CheckResult,\n DoctorResult,\n Drafts,\n ResolvedConfig,\n StatusResult,\n} from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { triage, type TriageResult } from './triage';\n\nexport interface StudioProblem {\n scope: string;\n message: string;\n}\n\nexport interface StudioState {\n root: string;\n dir: string;\n sourceLocale: string;\n locales: string[];\n scanning: boolean;\n catalogs: Catalogs;\n origins: Record<string, string[]>;\n status: StatusResult;\n check: CheckResult;\n drafts: Drafts;\n triage: Record<string, TriageResult>;\n problems: StudioProblem[];\n}\n\n// A locale nobody can parse must not take the panel down: Studio is what you open to fix it.\nfunction readAll(cfg: ResolvedConfig): { catalogs: Catalogs; problems: StudioProblem[] } {\n const catalogs: Catalogs = {};\n const problems: StudioProblem[] = [];\n // an empty green panel and a wrong --root look identical, and only this line tells them apart\n if (!existsSync(cfg.dir)) {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/');\n problems.push({ scope: dir, message: '[verbaly] no catalogs here, run npx verbaly init or check --root' });\n }\n for (const locale of cfg.locales) {\n try {\n catalogs[locale] = readCatalog(cfg, locale);\n } catch (error) {\n catalogs[locale] = {};\n problems.push({\n scope: locale,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return { catalogs, problems };\n}\n\n// A sidecar nobody can parse is the other file Studio exists to fix, so it degrades like a catalog.\nfunction readDrafts(cfg: ResolvedConfig): { drafts: Drafts; problems: StudioProblem[] } {\n try {\n return { drafts: loadDrafts(cfg), problems: [] };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { drafts: {}, problems: [{ scope: DRAFTS_FILE, message }] };\n }\n}\n\n// check() reports the file a stray key was used in as an absolute path, origins already do not.\nfunction relativize(cfg: ResolvedConfig, result: CheckResult): CheckResult {\n return {\n ...result,\n unknown: result.unknown.map((entry) => ({\n ...entry,\n files: entry.files.map((file) => relative(cfg.root, file).replaceAll('\\\\', '/')),\n })),\n };\n}\n\n// One shot and unpaginated: the biggest catalog we know is past 1600 messages, instant locally.\nexport async function buildState(cfg: ResolvedConfig): Promise<StudioState> {\n const { catalogs, problems } = readAll(cfg);\n const registry = await extractProject(cfg);\n const sidecar = readDrafts(cfg);\n problems.push(...sidecar.problems);\n const live = effectiveDrafts(sidecar.drafts, catalogs);\n const source = (catalogs[cfg.sourceLocale] ?? {}) as Catalog;\n const targets = targetLocales(cfg);\n\n for (const { file, message } of registry.parseErrors()) {\n problems.push({ scope: relative(cfg.root, file).replaceAll('\\\\', '/'), message });\n }\n\n const perLocale: Record<string, TriageResult> = {};\n for (const locale of targets) {\n perLocale[locale] = triage({\n source,\n target: (catalogs[locale] ?? {}) as Catalog,\n // a locale still carrying drafts has not been reviewed, so it cannot be the control\n reviewed: targets\n .filter((other) => other !== locale && !(live[other] ?? []).length)\n .map((other) => (catalogs[other] ?? {}) as Catalog),\n });\n }\n\n return {\n root: cfg.root,\n dir: cfg.dir,\n sourceLocale: cfg.sourceLocale,\n locales: cfg.locales,\n // with include: [] nothing is scanned, so an empty origins map is off, not \"none found\"\n scanning: cfg.include.length > 0,\n catalogs,\n origins: await collectOrigins(cfg, registry),\n status: status(cfg, catalogs, registry, live),\n check: relativize(cfg, check(cfg, catalogs, registry)),\n drafts: live,\n triage: perLocale,\n problems,\n };\n}\n\nexport function health(cfg: ResolvedConfig): Promise<DoctorResult> {\n return doctor(cfg);\n}\n\nexport interface WriteMessageResult {\n locale: string;\n key: string;\n clearedDraft: boolean;\n}\n\n// A human wrote it, so it is reviewed: the rule import already applies in run.ts:447.\nexport function writeMessage(\n cfg: ResolvedConfig,\n locale: string,\n key: string,\n text: string,\n): WriteMessageResult {\n if (locale === cfg.sourceLocale) {\n throw badRequest('the source text lives in your code, Studio never edits it');\n }\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const source = readCatalog(cfg, cfg.sourceLocale);\n // hasOwn, not `in`: `in` walks the prototype, so toString and __proto__ would pass this guard\n if (!Object.hasOwn(source, key)) {\n throw badRequest(`\"${key}\" is not in the source catalog, so Studio will not create it`);\n }\n // '' is untranslated everywhere else, so whitespace is that and not a translation to validate\n const value = text.trim() ? text : '';\n // the same two calls check() makes: validatePair alone misses a plural block with no other case\n const issues = value\n ? [...validateMessage(value, locale), ...validatePair(source[key] as string, value)]\n : [];\n const errors = issues.filter((issue) => issue.severity === 'error');\n if (errors.length) {\n throw badRequest(`${errors.map((issue) => issue.message).join('; ')}`);\n }\n\n const catalog = { ...readCatalog(cfg, locale), [key]: value };\n writeCatalog(cfg, locale, catalog);\n\n const drafts = loadDrafts(cfg);\n const clearedDraft = (drafts[locale] ?? []).includes(key);\n clearDrafts(drafts, locale, [key]);\n saveDrafts(cfg, drafts);\n return { locale, key, clearedDraft };\n}\n\nexport interface ApproveResult {\n locale: string;\n approved: number;\n keys: string[];\n}\n\n// The sidecar is re-read here: saveDrafts writes every locale, so a stale copy drops another's.\nexport function approve(cfg: ResolvedConfig, locale: string, keys?: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n const had = drafts[locale] ?? [];\n // the keys it really cleared, because undo has to put back exactly those and nothing else\n const cleared = keys ? had.filter((key) => keys.includes(key)) : [...had];\n clearDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: cleared.length, keys: cleared };\n}\n\n// Undo is not a nicety here: the flag records who wrote the text, so restoring it restores a fact.\nexport function unapprove(cfg: ResolvedConfig, locale: string, keys: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n markDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: keys.length, keys };\n}\n","import { badRequest, HttpError } from './http';\n\nexport type JobState = 'running' | 'done' | 'failed';\n\nexport interface Job {\n id: string;\n kind: 'translate';\n state: JobState;\n total: number;\n done: number;\n locale?: string;\n message?: string;\n result?: unknown;\n}\n\n// One at a time, because two runs over the same catalogs is a race over the same files.\nlet current: Job | null = null;\nlet counter = 0;\n\nexport function running(): Job | null {\n return current?.state === 'running' ? current : null;\n}\n\nexport function read(id: string): Job {\n if (!current || current.id !== id) throw new HttpError(404, `no job called \"${id}\"`);\n return current;\n}\n\nexport function start(kind: Job['kind'], total: number): Job {\n if (running()) throw badRequest('a job is already running, wait for it or read its progress');\n counter += 1;\n current = { id: `${kind}-${counter}`, kind, state: 'running', total, done: 0 };\n return current;\n}\n\n// A batch that failed still finishes: the bar reports work attempted, and message says what broke.\nexport function advance(id: string, keys: number, locale: string, error?: string): void {\n if (current?.id !== id) return;\n current.done = Math.min(current.done + keys, current.total);\n current.locale = locale;\n if (error) current.message = error;\n}\n\n// A run that writes part of its work and then fails is a success for what it wrote, so both land.\nexport function finish(id: string, state: 'done' | 'failed', patch: Partial<Job> = {}): void {\n if (current?.id === id) Object.assign(current, patch, { state });\n}\n","import {\n collectOrigins,\n extractProject,\n loadCatalogs,\n resolveProvider,\n syncCatalogs,\n translateCatalogs,\n writeCatalog,\n writeDts,\n markDrafts,\n loadDrafts,\n saveDrafts,\n} from '@verbaly/compiler';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { advance, finish, start, type Job } from './jobs';\n\nexport interface ExtractResult {\n added: Record<string, string[]>;\n // only the source locale counts as new text: a target gains a blank for every gap it had\n found: number;\n messages: number;\n}\n\n// Local, fast and free, so it answers in the same request instead of becoming a job.\nexport async function runExtract(cfg: ResolvedConfig): Promise<ExtractResult> {\n if (!cfg.include.length) {\n throw badRequest('source scanning is off (include: []), so there is nothing to extract');\n }\n const registry = await extractProject(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = syncCatalogs(cfg, catalogs, registry);\n for (const locale of cfg.locales) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n // the types come from the source catalog, and cfg.dts false means the project opted out\n if (cfg.dts !== false) writeDts(cfg, catalogs[cfg.sourceLocale] ?? {}, cfg.dts);\n const found = result.added[cfg.sourceLocale]?.length ?? 0;\n return { added: result.added, found, messages: registry.messages().size };\n}\n\nexport interface Plan {\n pending: Record<string, string[]>;\n total: number;\n}\n\n// translate is the one command that spends money and minutes, so the panel always shows the bill.\nexport async function planTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Plan> {\n const provider = await resolveProvider(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, { locales, dryRun: true });\n const total = Object.values(result.pending).reduce((n, keys) => n + keys.length, 0);\n return { pending: result.pending, total };\n}\n\nexport async function startTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Job> {\n const provider = await resolveProvider(cfg);\n // the job carries its own denominator, so progress reads the same whether or not you asked first\n const plan = await planTranslate(cfg, locales);\n const job = start('translate', plan.total);\n const id = job.id;\n\n // the run outlives this request on purpose: the client asks the job how it is going\n void (async () => {\n try {\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, {\n locales,\n batchSize: cfg.translate.batchSize,\n concurrency: cfg.translate.concurrency,\n retries: cfg.translate.retries,\n origins: await collectOrigins(cfg),\n onProgress: (p) => advance(id, p.keys, p.locale, p.error),\n });\n for (const [locale, keys] of Object.entries(result.translated)) {\n if (keys.length) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n }\n // what a machine wrote stays a draft: the panel does not get to change that rule\n const drafts = loadDrafts(cfg);\n for (const [locale, keys] of Object.entries(result.translated)) {\n markDrafts(drafts, locale, keys);\n }\n saveDrafts(cfg, drafts);\n finish(id, result.failed.length ? 'failed' : 'done', {\n result,\n message: result.failed.length ? `${result.failed.length} batches did not answer` : undefined,\n });\n } catch (error) {\n finish(id, 'failed', { message: error instanceof Error ? error.message : String(error) });\n }\n })();\n\n return job;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { relative } from 'node:path';\nimport type { ResolvedConfig } from '@verbaly/compiler';\n\nconst run = promisify(execFile);\n\nexport interface Commit {\n sha: string;\n author: string;\n date: string;\n subject: string;\n}\n\n// one field separator that no subject can contain, written as the escape and never as the byte\nconst FIELD = '\u001f';\nconst FORMAT = `--format=%H${FIELD}%an${FIELD}%aI${FIELD}%s`;\n\n// git is asked, never assumed: no repository and no git both mean there is no history to show\nexport async function catalogHistory(cfg: ResolvedConfig, limit = 5): Promise<Commit[]> {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/') || '.';\n let stdout: string;\n try {\n const result = await run('git', ['log', `-n${limit}`, FORMAT, '--', dir], {\n cwd: cfg.root,\n timeout: 3000,\n windowsHide: true,\n });\n stdout = result.stdout;\n } catch {\n return [];\n }\n\n const commits: Commit[] = [];\n for (const line of stdout.split('\\n')) {\n const [sha, author, date, ...rest] = line.split(FIELD);\n // a subject can hold anything but a newline, so it is the last field and is rejoined\n if (!sha || !author || !date) continue;\n commits.push({ sha: sha.slice(0, 7), author, date, subject: rest.join(FIELD) });\n }\n return commits;\n}\n","import { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, normalize, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// the built panel sits beside the compiled server, so it is found relative to this file, never cwd\nconst UI = resolve(fileURLToPath(new URL('.', import.meta.url)), 'ui');\n\nconst TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.woff2': 'font/woff2',\n '.json': 'application/json; charset=utf-8',\n '.ico': 'image/x-icon',\n};\n\nexport interface Asset {\n body: Buffer;\n type: string;\n}\n\nexport const uiBuilt = (): boolean => existsSync(join(UI, 'index.html'));\n\n// A path is resolved and then checked to still be inside UI: ../ and an absolute one both land out.\nexport function readAsset(pathname: string): Asset | undefined {\n const wanted = pathname === '/' ? '/index.html' : pathname;\n const target = resolve(join(UI, normalize(wanted)));\n if (target !== UI && !target.startsWith(UI + (process.platform === 'win32' ? '\\\\' : '/'))) {\n return undefined;\n }\n if (!existsSync(target) || !statSync(target).isFile()) return undefined;\n const dot = target.lastIndexOf('.');\n return {\n body: readFileSync(target),\n type: TYPES[target.slice(dot).toLowerCase()] ?? 'application/octet-stream',\n };\n}\n","import { randomBytes, timingSafeEqual } from 'node:crypto';\n\nexport interface GuardOptions {\n port: number;\n token: string;\n}\n\n// A local server that writes files is reachable from any page the browser has open.\nexport function newToken(): string {\n return randomBytes(9).toString('base64url');\n}\n\n// Only the two names that resolve to this machine. A DNS rebind arrives with a foreign Host.\nexport function hostAllowed(host: string | undefined, port: number): boolean {\n // a browser omits the port when it is the scheme default, so :80 would 403 every real request\n const names = port === 80 ? ['127.0.0.1', 'localhost'] : [];\n return [`127.0.0.1:${port}`, `localhost:${port}`, ...names].includes(host ?? '');\n}\n\n// No Origin at all is a same-origin navigation or a curl, both fine; a foreign one never is.\nexport function originAllowed(origin: string | undefined, port: number): boolean {\n if (origin === undefined) return true;\n return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;\n}\n\n// Compared in constant time so the token cannot be guessed one character at a time.\nexport function tokenMatches(given: string | null, expected: string): boolean {\n if (given === null) return false;\n const a = Buffer.from(given);\n const b = Buffer.from(expected);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nexport interface GuardVerdict {\n ok: boolean;\n status: number;\n reason: string;\n}\n\nconst PASS: GuardVerdict = { ok: true, status: 200, reason: '' };\n\nexport function guardRequest(\n headers: { host?: string; origin?: string },\n url: URL,\n { port, token }: GuardOptions,\n): GuardVerdict {\n if (!hostAllowed(headers.host, port)) {\n return { ok: false, status: 403, reason: '[verbaly] unexpected Host header' };\n }\n if (!originAllowed(headers.origin, port)) {\n return { ok: false, status: 403, reason: '[verbaly] cross-origin request' };\n }\n if (!tokenMatches(url.searchParams.get('t'), token)) {\n return { ok: false, status: 401, reason: '[verbaly] missing or wrong token, open the printed url' };\n }\n return PASS;\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { approve, buildState, health, unapprove, writeMessage } from './api';\nimport { planTranslate, runExtract, startTranslate } from './actions';\nimport { read as readJob, running } from './jobs';\nimport { catalogHistory } from './history';\nimport { readAsset, uiBuilt } from './assets';\nimport { guardRequest, newToken } from './guard';\nimport { HttpError, badRequest, scrub } from './http';\n\nexport interface StudioServer {\n server: Server;\n port: number;\n token: string;\n url: string;\n close: () => Promise<void>;\n}\n\nexport interface StartOptions {\n port?: number;\n token?: string;\n}\n\nconst DEFAULT_PORT = 4747;\nconst MAX_BODY = 1_000_000;\n\nfunction send(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-store',\n });\n res.end(JSON.stringify(body));\n}\n\nasync function readJson(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of req) {\n size += (chunk as Buffer).length;\n if (size > MAX_BODY) throw new HttpError(413, 'request body too large');\n chunks.push(chunk as Buffer);\n }\n if (!chunks.length) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));\n } catch {\n throw badRequest('body is not valid JSON');\n }\n // null and an array both pass typeof 'object', and reading .text off them is a 500\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw badRequest('body must be a JSON object');\n }\n return parsed as Record<string, unknown>;\n}\n\nfunction segment(raw: string | undefined, what: string): string {\n let value: string;\n try {\n value = decodeURIComponent(raw ?? '');\n } catch {\n throw badRequest(`the ${what} in the url is not valid percent-encoding`);\n }\n if (!value) throw badRequest(`the url is missing a ${what}`);\n return value;\n}\n\n// One page, JSON on every route: a framework would only add a dependency to a local tool.\nexport function createStudioApp(cfg: ResolvedConfig, port: number, token: string) {\n return async function handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // The url is built inside the try: `GET //` throws, and out here that would kill the process.\n try {\n let url: URL;\n try {\n url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);\n } catch {\n throw badRequest('the request target is not a valid url');\n }\n\n const api = url.pathname.startsWith('/api/');\n const verdict = guardRequest({ host: req.headers.host, origin: req.headers.origin }, url, {\n port,\n token,\n });\n // the panel files are the published npm package: only the project data needs a token\n if (!verdict.ok && (api || verdict.status !== 401)) {\n send(res, verdict.status, { error: verdict.reason });\n return;\n }\n\n if (!api && req.method === 'GET') {\n const asset = readAsset(url.pathname);\n if (asset) {\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'no-store' });\n res.end(asset.body);\n return;\n }\n if (url.pathname === '/' && !uiBuilt()) {\n throw new HttpError(500, 'the panel is not in this install, so only /api/* answers here');\n }\n }\n\n if (req.method === 'GET' && url.pathname === '/api/state') {\n send(res, 200, await buildState(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/history') {\n send(res, 200, { commits: await catalogHistory(cfg) });\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/health') {\n send(res, 200, await health(cfg));\n return;\n }\n if (req.method === 'PUT' && url.pathname.startsWith('/api/message/')) {\n const rest = url.pathname.slice('/api/message/'.length).split('/');\n const locale = segment(rest[0], 'locale');\n const key = segment(rest.slice(1).join('/'), 'key');\n const body = await readJson(req);\n if (typeof body.text !== 'string') throw badRequest('body needs a \"text\" string');\n send(res, 200, writeMessage(cfg, locale, key, body.text));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/approve') {\n const body = await readJson(req);\n if (typeof body.locale !== 'string') throw badRequest('body needs a \"locale\" string');\n const keys = Array.isArray(body.keys)\n ? body.keys.filter((k): k is string => typeof k === 'string')\n : undefined;\n if (body.undo === true) {\n if (!keys?.length) throw badRequest('undoing needs the \"keys\" it should put back');\n send(res, 200, unapprove(cfg, body.locale, keys));\n return;\n }\n send(res, 200, approve(cfg, body.locale, keys));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/extract') {\n send(res, 200, await runExtract(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/translate') {\n const locales = url.searchParams.getAll('locale');\n send(res, 200, await planTranslate(cfg, locales.length ? locales : undefined));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/translate') {\n const body = await readJson(req);\n const locales = Array.isArray(body.locales)\n ? body.locales.filter((l): l is string => typeof l === 'string')\n : undefined;\n send(res, 200, await startTranslate(cfg, locales?.length ? locales : undefined));\n return;\n }\n // a reload loses the id, so the panel asks what is running rather than losing the bar\n if (req.method === 'GET' && url.pathname === '/api/job') {\n send(res, 200, running());\n return;\n }\n if (req.method === 'GET' && url.pathname.startsWith('/api/job/')) {\n send(res, 200, readJob(segment(url.pathname.slice('/api/job/'.length), 'job id')));\n return;\n }\n\n send(res, 404, { error: `[verbaly] no route for ${req.method} ${url.pathname}` });\n } catch (error) {\n const status = error instanceof HttpError ? error.status : 500;\n const message = error instanceof Error ? error.message : String(error);\n send(res, status, { error: scrub(message, cfg.root) });\n }\n };\n}\n\n// A busy port climbs instead of failing: this is a local tool, not a service on a fixed address.\nfunction listen(server: Server, port: number, attemptsLeft: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const onError = (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE' && attemptsLeft > 0) {\n server.removeListener('error', onError);\n resolve(listen(server, port + 1, attemptsLeft - 1));\n return;\n }\n reject(error);\n };\n server.once('error', onError);\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', onError);\n // port 0 asks the system to pick, so the bound address is the only place the answer is\n const bound = server.address() as AddressInfo | string | null;\n resolve(typeof bound === 'object' && bound !== null ? bound.port : port);\n });\n });\n}\n\nexport async function startStudio(\n cfg: ResolvedConfig,\n options: StartOptions = {},\n): Promise<StudioServer> {\n const token = options.token ?? newToken();\n const server = createServer();\n // The handler is attached before listen so no request can arrive without one.\n let port = options.port ?? DEFAULT_PORT;\n server.on('request', (req, res) => void createStudioApp(cfg, port, token)(req, res));\n port = await listen(server, port, 20);\n\n return {\n server,\n port,\n token,\n url: `http://127.0.0.1:${port}/?t=${token}`,\n close: () =>\n new Promise<void>((resolve, reject) =>\n server.close((error) => (error ? reject(error) : resolve())),\n ),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["readJob"],"sources":["../src/http.ts","../src/triage.ts","../src/api.ts","../src/jobs.ts","../src/actions.ts","../src/history.ts","../src/assets.ts","../src/guard.ts","../src/server.ts"],"sourcesContent":["// A client mistake is not a server fault, so the status rides with the error, not a blanket 500.\nexport class HttpError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message.startsWith('[verbaly]') ? message : `[verbaly] ${message}`);\n this.status = status;\n this.name = 'HttpError';\n }\n}\n\nexport const badRequest = (message: string) => new HttpError(400, message);\n\n// The absolute path of someone's project is not the browser's business.\nexport function scrub(message: string, root: string): string {\n return root ? message.split(root).join('.') : message;\n}\n","import type { Catalog } from '@verbaly/compiler';\n\nexport type TriageSignal = 'divergent' | 'collision' | 'echo' | 'digits' | 'code' | 'url';\n\nexport interface TriageReason {\n signal: TriageSignal;\n text: string;\n}\n\nexport type TriageResult = Record<string, TriageReason[]>;\n\n// check() already caught the structure, so these only point at the few worth reading first.\nexport interface TriageInput {\n source: Catalog;\n target: Catalog;\n reviewed: Catalog[];\n}\n\nconst DIGITS = /\\d[\\d.,]*/g;\nconst URLS = /https?:\\/\\/[^\\s<)\"']+/g;\nconst CODE = /<code>([^<]+)<\\/code>/g;\n\nfunction bag(text: string, re: RegExp, normalize?: (v: string) => string): string[] {\n const found = text.match(re) ?? [];\n return (normalize ? found.map(normalize) : found).sort();\n}\n\nfunction same(a: string[], b: string[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n\n// A number or a url at the end of a clause takes the punctuation with it, and that is not a signal.\nconst trimPunct = (v: string) => v.replace(/[.,;:!?)\\]]+$/, '');\n// A separator is idiomatic (3.09 is 3,09 in Spanish); canonizing keeps 1.5 apart from 15.\nconst bareDigits = (v: string) => trimPunct(v).replaceAll(/[.,]/g, '.');\n\nfunction push(out: TriageResult, key: string, reason: TriageReason): void {\n (out[key] ??= []).push(reason);\n}\n\nexport function triage({ source, target, reviewed }: TriageInput): TriageResult {\n // null-prototype: a source text of \"__proto__\" or \"toString\" is a string, not a member of Object\n const out: TriageResult = Object.create(null);\n const keys = Object.keys(source);\n\n // One source text that two humans rendered two ways is ambiguous, so the machine had no chance.\n const bySource: Record<string, string[]> = Object.create(null);\n for (const key of keys) {\n const text = source[key]?.trim();\n if (text) (bySource[text] ??= []).push(key);\n }\n for (const [text, group] of Object.entries(bySource)) {\n if (group.length < 2) continue;\n const divergent = reviewed.some(\n (catalog) => new Set(group.map((k) => catalog[k]?.trim() ?? '').filter(Boolean)).size > 1,\n );\n if (divergent) {\n for (const key of group) {\n push(out, key, { signal: 'divergent', text: `\"${text}\" was already translated two ways` });\n }\n }\n // The same ambiguity seen from the result instead of from the history.\n const targets = new Set(group.map((key) => target[key]?.trim() ?? '').filter(Boolean));\n if (!divergent && targets.size > 1) {\n for (const key of group) {\n push(out, key, { signal: 'collision', text: `\"${text}\" came back as two different translations` });\n }\n }\n }\n\n for (const key of keys) {\n const src = source[key]?.trim() ?? '';\n const trg = target[key]?.trim() ?? '';\n if (!src || !trg) continue;\n\n // Only the locales with an opinion on this key vote: alone it fires on every do-not-translate.\n const opinions = reviewed.map((c) => c[key]?.trim()).filter((v) => v !== undefined && v !== '');\n if (trg === src && opinions.length > 0 && opinions.every((v) => v !== src)) {\n push(out, key, { signal: 'echo', text: 'still identical to the source' });\n }\n\n // a translation that adds a number is idiomatic (\"refresh\" is \"F5\"); one that changes it is not\n const srcDigits = bag(src, DIGITS, bareDigits);\n if (srcDigits.length > 0 && !same(srcDigits, bag(trg, DIGITS, bareDigits))) {\n push(out, key, { signal: 'digits', text: 'the numbers do not match the source' });\n }\n if (!same(bag(src, URLS, trimPunct), bag(trg, URLS, trimPunct))) {\n push(out, key, { signal: 'url', text: 'a URL changed' });\n }\n if (!same(bag(src, CODE), bag(trg, CODE))) {\n push(out, key, { signal: 'code', text: 'the contents of a <code> span changed' });\n }\n }\n\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport {\n check,\n clearDrafts,\n collectOrigins,\n doctor,\n effectiveDrafts,\n extractProject,\n loadDrafts,\n markDrafts,\n readCatalog,\n saveDrafts,\n status,\n targetLocales,\n validateMessage,\n validatePair,\n writeCatalog,\n} from '@verbaly/compiler';\nimport { DRAFTS_FILE } from '@verbaly/compiler';\nimport type {\n Catalog,\n Catalogs,\n CheckResult,\n DoctorResult,\n Drafts,\n ResolvedConfig,\n StatusResult,\n} from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { triage, type TriageResult } from './triage';\n\nexport interface StudioProblem {\n scope: string;\n message: string;\n}\n\nexport interface StudioState {\n root: string;\n dir: string;\n sourceLocale: string;\n locales: string[];\n scanning: boolean;\n catalogs: Catalogs;\n origins: Record<string, string[]>;\n status: StatusResult;\n check: CheckResult;\n drafts: Drafts;\n triage: Record<string, TriageResult>;\n problems: StudioProblem[];\n}\n\n// A locale nobody can parse must not take the panel down: Studio is what you open to fix it.\nfunction readAll(cfg: ResolvedConfig): { catalogs: Catalogs; problems: StudioProblem[] } {\n const catalogs: Catalogs = {};\n const problems: StudioProblem[] = [];\n // an empty green panel and a wrong --root look identical, and only this line tells them apart\n if (!existsSync(cfg.dir)) {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/');\n problems.push({ scope: dir, message: '[verbaly] no catalogs here, run npx verbaly init or check --root' });\n }\n for (const locale of cfg.locales) {\n try {\n catalogs[locale] = readCatalog(cfg, locale);\n } catch (error) {\n catalogs[locale] = {};\n problems.push({\n scope: locale,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return { catalogs, problems };\n}\n\n// A sidecar nobody can parse is the other file Studio exists to fix, so it degrades like a catalog.\nfunction readDrafts(cfg: ResolvedConfig): { drafts: Drafts; problems: StudioProblem[] } {\n try {\n return { drafts: loadDrafts(cfg), problems: [] };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { drafts: {}, problems: [{ scope: DRAFTS_FILE, message }] };\n }\n}\n\n// check() reports the file a stray key was used in as an absolute path, origins already do not.\nfunction relativize(cfg: ResolvedConfig, result: CheckResult): CheckResult {\n return {\n ...result,\n unknown: result.unknown.map((entry) => ({\n ...entry,\n files: entry.files.map((file) => relative(cfg.root, file).replaceAll('\\\\', '/')),\n })),\n };\n}\n\n// One shot and unpaginated: the biggest catalog we know is past 1600 messages, instant locally.\nexport async function buildState(cfg: ResolvedConfig): Promise<StudioState> {\n const { catalogs, problems } = readAll(cfg);\n const registry = await extractProject(cfg);\n const sidecar = readDrafts(cfg);\n problems.push(...sidecar.problems);\n const live = effectiveDrafts(sidecar.drafts, catalogs);\n const source = (catalogs[cfg.sourceLocale] ?? {}) as Catalog;\n const targets = targetLocales(cfg);\n\n for (const { file, message } of registry.parseErrors()) {\n problems.push({ scope: relative(cfg.root, file).replaceAll('\\\\', '/'), message });\n }\n\n const perLocale: Record<string, TriageResult> = {};\n for (const locale of targets) {\n perLocale[locale] = triage({\n source,\n target: (catalogs[locale] ?? {}) as Catalog,\n // a locale still carrying drafts has not been reviewed, so it cannot be the control\n reviewed: targets\n .filter((other) => other !== locale && !(live[other] ?? []).length)\n .map((other) => (catalogs[other] ?? {}) as Catalog),\n });\n }\n\n return {\n root: cfg.root,\n dir: cfg.dir,\n sourceLocale: cfg.sourceLocale,\n locales: cfg.locales,\n // with include: [] nothing is scanned, so an empty origins map is off, not \"none found\"\n scanning: cfg.include.length > 0,\n catalogs,\n origins: await collectOrigins(cfg, registry),\n status: status(cfg, catalogs, registry, live),\n check: relativize(cfg, check(cfg, catalogs, registry)),\n drafts: live,\n triage: perLocale,\n problems,\n };\n}\n\nexport function health(cfg: ResolvedConfig): Promise<DoctorResult> {\n return doctor(cfg);\n}\n\nexport interface WriteMessageResult {\n locale: string;\n key: string;\n clearedDraft: boolean;\n}\n\n// A human wrote it, so it is reviewed: the rule import already applies in run.ts:447.\nexport function writeMessage(\n cfg: ResolvedConfig,\n locale: string,\n key: string,\n text: string,\n): WriteMessageResult {\n if (locale === cfg.sourceLocale) {\n throw badRequest('the source text lives in your code, Studio never edits it');\n }\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const source = readCatalog(cfg, cfg.sourceLocale);\n // hasOwn, not `in`: `in` walks the prototype, so toString and __proto__ would pass this guard\n if (!Object.hasOwn(source, key)) {\n throw badRequest(`\"${key}\" is not in the source catalog, so Studio will not create it`);\n }\n // '' is untranslated everywhere else, so whitespace is that and not a translation to validate\n const value = text.trim() ? text : '';\n // the same two calls check() makes: validatePair alone misses a plural block with no other case\n const issues = value\n ? [...validateMessage(value, locale), ...validatePair(source[key] as string, value)]\n : [];\n const errors = issues.filter((issue) => issue.severity === 'error');\n if (errors.length) {\n throw badRequest(`${errors.map((issue) => issue.message).join('; ')}`);\n }\n\n const catalog = { ...readCatalog(cfg, locale), [key]: value };\n writeCatalog(cfg, locale, catalog);\n\n const drafts = loadDrafts(cfg);\n const clearedDraft = (drafts[locale] ?? []).includes(key);\n clearDrafts(drafts, locale, [key]);\n saveDrafts(cfg, drafts);\n return { locale, key, clearedDraft };\n}\n\nexport interface ApproveResult {\n locale: string;\n approved: number;\n keys: string[];\n}\n\n// The sidecar is re-read here: saveDrafts writes every locale, so a stale copy drops another's.\nexport function approve(cfg: ResolvedConfig, locale: string, keys?: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n const had = drafts[locale] ?? [];\n // the keys it really cleared, because undo has to put back exactly those and nothing else\n const cleared = keys ? had.filter((key) => keys.includes(key)) : [...had];\n clearDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: cleared.length, keys: cleared };\n}\n\n// Undo is not a nicety here: the flag records who wrote the text, so restoring it restores a fact.\nexport function unapprove(cfg: ResolvedConfig, locale: string, keys: string[]): ApproveResult {\n if (!cfg.locales.includes(locale)) {\n throw badRequest(`${locale} is not one of this project's locales`);\n }\n const drafts = loadDrafts(cfg);\n markDrafts(drafts, locale, keys);\n saveDrafts(cfg, drafts);\n return { locale, approved: keys.length, keys };\n}\n","import { badRequest, HttpError } from './http';\n\nexport type JobState = 'running' | 'done' | 'failed';\n\nexport interface Job {\n id: string;\n kind: 'translate';\n state: JobState;\n total: number;\n done: number;\n locale?: string;\n message?: string;\n result?: unknown;\n}\n\n// One at a time, because two runs over the same catalogs is a race over the same files.\nlet current: Job | null = null;\nlet counter = 0;\n\nexport function running(): Job | null {\n return current?.state === 'running' ? current : null;\n}\n\nexport function read(id: string): Job {\n if (!current || current.id !== id) throw new HttpError(404, `no job called \"${id}\"`);\n return current;\n}\n\nexport function start(kind: Job['kind'], total: number): Job {\n if (running()) throw badRequest('a job is already running, wait for it or read its progress');\n counter += 1;\n current = { id: `${kind}-${counter}`, kind, state: 'running', total, done: 0 };\n return current;\n}\n\n// A batch that failed still finishes: the bar reports work attempted, and message says what broke.\nexport function advance(id: string, keys: number, locale: string, error?: string): void {\n if (current?.id !== id) return;\n current.done = Math.min(current.done + keys, current.total);\n current.locale = locale;\n if (error) current.message = error;\n}\n\n// A run that writes part of its work and then fails is a success for what it wrote, so both land.\nexport function finish(id: string, state: 'done' | 'failed', patch: Partial<Job> = {}): void {\n if (current?.id === id) Object.assign(current, patch, { state });\n}\n","import {\n collectOrigins,\n extractProject,\n loadCatalogs,\n resolveProvider,\n syncCatalogs,\n translateCatalogs,\n writeCatalog,\n writeDts,\n markDrafts,\n loadDrafts,\n saveDrafts,\n} from '@verbaly/compiler';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { badRequest } from './http';\nimport { advance, finish, start, type Job } from './jobs';\n\nexport interface ExtractResult {\n added: Record<string, string[]>;\n // only the source locale counts as new text: a target gains a blank for every gap it had\n found: number;\n messages: number;\n}\n\n// Local, fast and free, so it answers in the same request instead of becoming a job.\nexport async function runExtract(cfg: ResolvedConfig): Promise<ExtractResult> {\n if (!cfg.include.length) {\n throw badRequest('source scanning is off (include: []), so there is nothing to extract');\n }\n const registry = await extractProject(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = syncCatalogs(cfg, catalogs, registry);\n for (const locale of cfg.locales) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n // the types come from the source catalog, and cfg.dts false means the project opted out\n if (cfg.dts !== false) writeDts(cfg, catalogs[cfg.sourceLocale] ?? {}, cfg.dts);\n const found = result.added[cfg.sourceLocale]?.length ?? 0;\n return { added: result.added, found, messages: registry.messages().size };\n}\n\nexport interface Plan {\n pending: Record<string, string[]>;\n total: number;\n}\n\n// translate is the one command that spends money and minutes, so the panel always shows the bill.\nexport async function planTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Plan> {\n const provider = await resolveProvider(cfg);\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, { locales, dryRun: true });\n const total = Object.values(result.pending).reduce((n, keys) => n + keys.length, 0);\n return { pending: result.pending, total };\n}\n\nexport async function startTranslate(cfg: ResolvedConfig, locales?: string[]): Promise<Job> {\n const provider = await resolveProvider(cfg);\n // the job carries its own denominator, so progress reads the same whether or not you asked first\n const plan = await planTranslate(cfg, locales);\n const job = start('translate', plan.total);\n const id = job.id;\n\n // the run outlives this request on purpose: the client asks the job how it is going\n void (async () => {\n try {\n const catalogs = loadCatalogs(cfg);\n const result = await translateCatalogs(cfg, catalogs, provider, {\n locales,\n batchSize: cfg.translate.batchSize,\n concurrency: cfg.translate.concurrency,\n retries: cfg.translate.retries,\n origins: await collectOrigins(cfg),\n onProgress: (p) => advance(id, p.keys, p.locale, p.error),\n });\n for (const [locale, keys] of Object.entries(result.translated)) {\n if (keys.length) writeCatalog(cfg, locale, catalogs[locale] ?? {});\n }\n // what a machine wrote stays a draft: the panel does not get to change that rule\n const drafts = loadDrafts(cfg);\n for (const [locale, keys] of Object.entries(result.translated)) {\n markDrafts(drafts, locale, keys);\n }\n saveDrafts(cfg, drafts);\n finish(id, result.failed.length ? 'failed' : 'done', {\n result,\n message: result.failed.length ? `${result.failed.length} batches did not answer` : undefined,\n });\n } catch (error) {\n finish(id, 'failed', { message: error instanceof Error ? error.message : String(error) });\n }\n })();\n\n return job;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { relative } from 'node:path';\nimport type { ResolvedConfig } from '@verbaly/compiler';\n\nconst run = promisify(execFile);\n\nexport interface Commit {\n sha: string;\n author: string;\n date: string;\n subject: string;\n}\n\n// one field separator that no subject can contain, written as the escape and never as the byte\nconst FIELD = '\\u001f';\nconst FORMAT = `--format=%H${FIELD}%an${FIELD}%aI${FIELD}%s`;\n\n// split out so the shape of a log line is tested without a repository and without writing one\nexport function parseLog(stdout: string): Commit[] {\n const commits: Commit[] = [];\n for (const line of stdout.split('\\n')) {\n const [sha, author, date, ...rest] = line.split(FIELD);\n // a subject holds anything but a newline, so it is the last field and is rejoined\n if (!sha || !author || !date || !rest.length) continue;\n commits.push({ sha: sha.slice(0, 7), author, date, subject: rest.join(FIELD) });\n }\n return commits;\n}\n\n// git is asked, never assumed: no repository and no git both mean there is no history to show\nexport async function catalogHistory(cfg: ResolvedConfig, limit = 5): Promise<Commit[]> {\n const dir = relative(cfg.root, cfg.dir).replaceAll('\\\\', '/') || '.';\n try {\n const { stdout } = await run('git', ['log', `-n${limit}`, FORMAT, '--', dir], {\n cwd: cfg.root,\n timeout: 3000,\n windowsHide: true,\n });\n return parseLog(stdout);\n } catch {\n return [];\n }\n}\n","import { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, normalize, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// the built panel sits beside the compiled server, so it is found relative to this file, never cwd\nconst UI = resolve(fileURLToPath(new URL('.', import.meta.url)), 'ui');\n\nconst TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.woff2': 'font/woff2',\n '.json': 'application/json; charset=utf-8',\n '.ico': 'image/x-icon',\n};\n\nexport interface Asset {\n body: Buffer;\n type: string;\n}\n\nexport const uiBuilt = (): boolean => existsSync(join(UI, 'index.html'));\n\n// A path is resolved and then checked to still be inside UI: ../ and an absolute one both land out.\nexport function readAsset(pathname: string): Asset | undefined {\n const wanted = pathname === '/' ? '/index.html' : pathname;\n const target = resolve(join(UI, normalize(wanted)));\n if (target !== UI && !target.startsWith(UI + (process.platform === 'win32' ? '\\\\' : '/'))) {\n return undefined;\n }\n if (!existsSync(target) || !statSync(target).isFile()) return undefined;\n const dot = target.lastIndexOf('.');\n return {\n body: readFileSync(target),\n type: TYPES[target.slice(dot).toLowerCase()] ?? 'application/octet-stream',\n };\n}\n","import { randomBytes, timingSafeEqual } from 'node:crypto';\n\nexport interface GuardOptions {\n port: number;\n token: string;\n}\n\n// A local server that writes files is reachable from any page the browser has open.\nexport function newToken(): string {\n return randomBytes(9).toString('base64url');\n}\n\n// Only the two names that resolve to this machine. A DNS rebind arrives with a foreign Host.\nexport function hostAllowed(host: string | undefined, port: number): boolean {\n // a browser omits the port when it is the scheme default, so :80 would 403 every real request\n const names = port === 80 ? ['127.0.0.1', 'localhost'] : [];\n return [`127.0.0.1:${port}`, `localhost:${port}`, ...names].includes(host ?? '');\n}\n\n// No Origin at all is a same-origin navigation or a curl, both fine; a foreign one never is.\nexport function originAllowed(origin: string | undefined, port: number): boolean {\n if (origin === undefined) return true;\n return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;\n}\n\n// Compared in constant time so the token cannot be guessed one character at a time.\nexport function tokenMatches(given: string | null, expected: string): boolean {\n if (given === null) return false;\n const a = Buffer.from(given);\n const b = Buffer.from(expected);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nexport interface GuardVerdict {\n ok: boolean;\n status: number;\n reason: string;\n}\n\nconst PASS: GuardVerdict = { ok: true, status: 200, reason: '' };\n\nexport function guardRequest(\n headers: { host?: string; origin?: string },\n url: URL,\n { port, token }: GuardOptions,\n): GuardVerdict {\n if (!hostAllowed(headers.host, port)) {\n return { ok: false, status: 403, reason: '[verbaly] unexpected Host header' };\n }\n if (!originAllowed(headers.origin, port)) {\n return { ok: false, status: 403, reason: '[verbaly] cross-origin request' };\n }\n if (!tokenMatches(url.searchParams.get('t'), token)) {\n return { ok: false, status: 401, reason: '[verbaly] missing or wrong token, open the printed url' };\n }\n return PASS;\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\nimport type { ResolvedConfig } from '@verbaly/compiler';\nimport { approve, buildState, health, unapprove, writeMessage } from './api';\nimport { planTranslate, runExtract, startTranslate } from './actions';\nimport { read as readJob, running } from './jobs';\nimport { catalogHistory } from './history';\nimport { readAsset, uiBuilt } from './assets';\nimport { guardRequest, newToken } from './guard';\nimport { HttpError, badRequest, scrub } from './http';\n\nexport interface StudioServer {\n server: Server;\n port: number;\n token: string;\n url: string;\n close: () => Promise<void>;\n}\n\nexport interface StartOptions {\n port?: number;\n token?: string;\n}\n\nconst DEFAULT_PORT = 4747;\nconst MAX_BODY = 1_000_000;\n\nfunction send(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-store',\n });\n res.end(JSON.stringify(body));\n}\n\nasync function readJson(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of req) {\n size += (chunk as Buffer).length;\n if (size > MAX_BODY) throw new HttpError(413, 'request body too large');\n chunks.push(chunk as Buffer);\n }\n if (!chunks.length) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));\n } catch {\n throw badRequest('body is not valid JSON');\n }\n // null and an array both pass typeof 'object', and reading .text off them is a 500\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw badRequest('body must be a JSON object');\n }\n return parsed as Record<string, unknown>;\n}\n\nfunction segment(raw: string | undefined, what: string): string {\n let value: string;\n try {\n value = decodeURIComponent(raw ?? '');\n } catch {\n throw badRequest(`the ${what} in the url is not valid percent-encoding`);\n }\n if (!value) throw badRequest(`the url is missing a ${what}`);\n return value;\n}\n\n// One page, JSON on every route: a framework would only add a dependency to a local tool.\nexport function createStudioApp(cfg: ResolvedConfig, port: number, token: string) {\n return async function handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // The url is built inside the try: `GET //` throws, and out here that would kill the process.\n try {\n let url: URL;\n try {\n url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);\n } catch {\n throw badRequest('the request target is not a valid url');\n }\n\n const api = url.pathname.startsWith('/api/');\n const verdict = guardRequest({ host: req.headers.host, origin: req.headers.origin }, url, {\n port,\n token,\n });\n // the panel files are the published npm package: only the project data needs a token\n if (!verdict.ok && (api || verdict.status !== 401)) {\n send(res, verdict.status, { error: verdict.reason });\n return;\n }\n\n if (!api && req.method === 'GET') {\n const asset = readAsset(url.pathname);\n if (asset) {\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'no-store' });\n res.end(asset.body);\n return;\n }\n if (url.pathname === '/' && !uiBuilt()) {\n throw new HttpError(500, 'the panel is not in this install, so only /api/* answers here');\n }\n }\n\n if (req.method === 'GET' && url.pathname === '/api/state') {\n send(res, 200, await buildState(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/history') {\n send(res, 200, { commits: await catalogHistory(cfg) });\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/health') {\n send(res, 200, await health(cfg));\n return;\n }\n if (req.method === 'PUT' && url.pathname.startsWith('/api/message/')) {\n const rest = url.pathname.slice('/api/message/'.length).split('/');\n const locale = segment(rest[0], 'locale');\n const key = segment(rest.slice(1).join('/'), 'key');\n const body = await readJson(req);\n if (typeof body.text !== 'string') throw badRequest('body needs a \"text\" string');\n send(res, 200, writeMessage(cfg, locale, key, body.text));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/approve') {\n const body = await readJson(req);\n if (typeof body.locale !== 'string') throw badRequest('body needs a \"locale\" string');\n const keys = Array.isArray(body.keys)\n ? body.keys.filter((k): k is string => typeof k === 'string')\n : undefined;\n if (body.undo === true) {\n if (!keys?.length) throw badRequest('undoing needs the \"keys\" it should put back');\n send(res, 200, unapprove(cfg, body.locale, keys));\n return;\n }\n send(res, 200, approve(cfg, body.locale, keys));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/extract') {\n send(res, 200, await runExtract(cfg));\n return;\n }\n if (req.method === 'GET' && url.pathname === '/api/translate') {\n const locales = url.searchParams.getAll('locale');\n send(res, 200, await planTranslate(cfg, locales.length ? locales : undefined));\n return;\n }\n if (req.method === 'POST' && url.pathname === '/api/translate') {\n const body = await readJson(req);\n const locales = Array.isArray(body.locales)\n ? body.locales.filter((l): l is string => typeof l === 'string')\n : undefined;\n send(res, 200, await startTranslate(cfg, locales?.length ? locales : undefined));\n return;\n }\n // a reload loses the id, so the panel asks what is running rather than losing the bar\n if (req.method === 'GET' && url.pathname === '/api/job') {\n send(res, 200, running());\n return;\n }\n if (req.method === 'GET' && url.pathname.startsWith('/api/job/')) {\n send(res, 200, readJob(segment(url.pathname.slice('/api/job/'.length), 'job id')));\n return;\n }\n\n send(res, 404, { error: `[verbaly] no route for ${req.method} ${url.pathname}` });\n } catch (error) {\n const status = error instanceof HttpError ? error.status : 500;\n const message = error instanceof Error ? error.message : String(error);\n send(res, status, { error: scrub(message, cfg.root) });\n }\n };\n}\n\n// A busy port climbs instead of failing: this is a local tool, not a service on a fixed address.\nfunction listen(server: Server, port: number, attemptsLeft: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const onError = (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE' && attemptsLeft > 0) {\n server.removeListener('error', onError);\n resolve(listen(server, port + 1, attemptsLeft - 1));\n return;\n }\n reject(error);\n };\n server.once('error', onError);\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', onError);\n // port 0 asks the system to pick, so the bound address is the only place the answer is\n const bound = server.address() as AddressInfo | string | null;\n resolve(typeof bound === 'object' && bound !== null ? bound.port : port);\n });\n });\n}\n\nexport async function startStudio(\n cfg: ResolvedConfig,\n options: StartOptions = {},\n): Promise<StudioServer> {\n const token = options.token ?? newToken();\n const server = createServer();\n // The handler is attached before listen so no request can arrive without one.\n let port = options.port ?? DEFAULT_PORT;\n server.on('request', (req, res) => void createStudioApp(cfg, port, token)(req, res));\n port = await listen(server, port, 20);\n\n return {\n server,\n port,\n token,\n url: `http://127.0.0.1:${port}/?t=${token}`,\n close: () =>\n new Promise<void>((resolve, reject) =>\n server.close((error) => (error ? reject(error) : resolve())),\n ),\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible,d=()=>{};function f(e){for(var t=0;t<e.length;t++)e[t]()}function p(){var e,t;return{promise:new Promise((n,r)=>{e=n,t=r}),resolve:e,reject:t}}var m=1024,h=2048,g=4096,_=8192,v=16384,y=32768,b=1<<25,x=65536,S=1<<19,ee=1<<20,te=1<<25,C=65536,ne=1<<21,re=1<<22,ie=1<<23,w=Symbol(`$state`),ae=Symbol(`component`),oe=Symbol(``),se=Symbol(`attributes`),ce=Symbol(`class`),le=Symbol(`style`),ue=Symbol(`text`),de=Symbol(`form reset`),fe=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},pe=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),me={},T=Symbol(`uninitialized`),he=`http://www.w3.org/1999/xhtml`;function ge(){console.warn(`https://svelte.dev/e/derived_inert`)}function _e(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function ve(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function ye(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var E=!1;function be(e){E=e}var D;function O(e){if(e===null)throw _e(),me;return D=e}function xe(){return O($t(D))}function k(e){if(E){if($t(D)!==null)throw _e(),me;D=e}}function Se(e=1){if(E){for(var t=e,n=D;t--;)n=$t(n);D=n}}function Ce(e=!0){for(var t=0,n=D;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=$t(n);e&&n.remove(),n=i}}function we(e){if(!e||e.nodeType!==8)throw _e(),me;return e.data}function Te(e){return e===this.v}function Ee(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function De(e){return!Ee(e,this.v)}function Oe(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function ke(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function Ae(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function je(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function Me(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Ne(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function Pe(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Fe(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Ie(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Le(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function Re(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var A=null;function ze(e){A=e}function Be(e,t=!1,n){A={p:A,i:!1,c:null,e:null,s:e,x:null,r:U,l:null}}function Ve(e){var t=A,n=t.e;if(n!==null){t.e=null;for(var r of n)mn(r)}return e!==void 0&&(t.x=e),t.i=!0,A=t.p,He(e)}function He(e={}){return i(e,ae,{value:!0}),e}function Ue(){return!0}var We=[];function Ge(){var e=We;We=[],f(e)}function Ke(e){if(We.length===0&&!xt){var t=We;queueMicrotask(()=>{t===We&&Ge()})}We.push(e)}function qe(){for(;We.length>0;)Ge()}var Je=~(h|g|m);function j(e,t){e.f=e.f&Je|t}function Ye(e){e.f&512||e.deps===null?j(e,m):j(e,g)}function Xe(e){if(e!==null)for(let t of e)t.f&2&&t.f&65536&&(t.f^=C,Xe(t.deps))}function Ze(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),Xe(e.deps),j(e,m)}function Qe(e,t){if(t){let t=document.body;e.autofocus=!0,Ke(()=>{document.activeElement===t&&e.focus()})}}function $e(e){E&&Qt(e)!==null&&tn(e)}var et=!1;function tt(){et||(et=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[de]?.()})},{capture:!0}))}function nt(e){var t=H,n=U;In(null),Ln(null);try{return e()}finally{In(t),Ln(n)}}function rt(e,t,n,r=n){e.addEventListener(t,()=>nt(n));let i=e[de];e[de]=i?()=>{i(),r(!0)}:()=>r(!0),tt()}function it(e,t,n,r){let i=Ue()?ct:dt;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=U,c=at(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){sn(e,s)}ot()}}var d=st();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>ut(e))).then(u).catch(e=>sn(e,s)).finally(d)}l?l.then(()=>{c(),f(),ot()}):f()}function at(){var e=U,t=H,n=A,r=N;return function(i=!0){Ln(e),In(t),ze(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function ot(e=!0){Ln(null),In(null),ze(null),e&&N?.deactivate()}function st(){var e=U,t=e.b,n=N,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function ct(e){var t=2|h;return U!==null&&(U.f|=S),{ctx:A,deps:null,effects:null,equals:Te,f:t,fn:e,reactions:null,rv:0,v:T,wv:0,parent:U,ac:null}}var lt=Symbol(`obsolete`);function ut(e,t,n){let r=U;r===null&&ke();var i=void 0,a=Rt(T),o=!H,s=new Set;return _n(()=>{var t=U,n=p();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==fe&&n.reject(e)}).finally(ot)}catch(e){n.reject(e),ot()}var c=N;if(o){if(t.f&32768)var l=st();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(lt);else for(let e of s.values())e.reject(lt);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==lt&&(c.activate(),t?(a.f|=ie,Bt(a,t)):(a.f&8388608&&(a.f^=ie),Bt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),fn(()=>{for(let e of s)e.reject(lt)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function M(e){let t=ct(e);return zn(t),t}function dt(e){let t=ct(e);return t.equals=De,t}function ft(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n<t.length;n+=1)V(t[n])}}function pt(e){var t,n=U,r=e.parent;if(!Nn&&r!==null&&e.v!==T&&r.f&24576)return ge(),e.v;Ln(r);try{e.f&=~C,ft(e),t=Xn(e)}finally{Ln(n)}return t}function mt(e){var t=pt(e);if(!e.equals(t)&&(e.wv=qn(),(!N?.is_fork||e.deps===null)&&(N===null?e.v=t:(N.capture(e,t,!0),vt?.capture(e,t,!0)),e.deps===null))){j(e,m);return}Nn||(yt===null?Ye(e):(dn()||N?.is_fork)&&yt.set(e,t))}function ht(e){if(e.effects!==null)for(let t of e.effects)(t.teardown||t.ac)&&(t.teardown?.(),t.ac!==null&&nt(()=>{t.ac.abort(fe),t.ac=null}),t.fn!==null&&(t.teardown=d),$n(t,0),Sn(t))}function gt(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&er(t)}var _t=null,N=null,vt=null,yt=null,bt=null,xt=!1,St=!1,Ct=null,wt=null,Tt=0,Et=1,Dt=class e{id=Et++;#e=!1;linked=!0;#t=null;#n=null;async_deriveds=new Map;current=new Map;previous=new Map;#r=new Set;#i=new Set;#a=0;#o=new Map;#s=null;#c=[];#l=[];#u=new Set;#d=new Set;#f=new Map;#p=new Set;is_fork=!1;#m=!1;constructor(){_t===null?_t=this:(_t.#n=this,this.#t=_t),_t=this}#h(){if(this.is_fork)return!0;for(let n of this.#o.keys()){for(var e=n,t=!1;e.parent!==null;){if(this.#f.has(e)){t=!0;break}e=e.parent}if(!t)return!0}return!1}skip_effect(e){this.#f.has(e)||this.#f.set(e,{d:[],m:[]}),this.#p.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#f.get(e);if(n){this.#f.delete(e);for(var r of n.d)j(r,h),t(r);for(r of n.m)j(r,g),t(r)}this.#p.add(e)}#g(){this.#e=!0,Tt++>1e3&&(this.#x(),kt());for(let e of this.#u)this.#d.delete(e),j(e,h),this.schedule(e);for(let e of this.#d)j(e,g),this.schedule(e);let t=this.#c;this.#c=[],this.apply();var n=Ct=[],r=[],i=wt=[];for(let e of t)try{this.#_(e,n,r)}catch(t){throw Pt(e),this.#h()||this.discard(),t}if(N=null,i.length>0){var a=e.ensure();for(let e of i)a.schedule(e)}if(Ct=null,wt=null,this.#h()){this.#b(r),this.#b(n);for(let[e,t]of this.#f)Nt(e,t);i.length>0&&N.#g();return}let o=this.#v();if(o){this.#b(r),this.#b(n),o.#y(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),vt=this,jt(r),jt(n),vt=null,this.#s?.resolve();var s=N;if(this.#a===0&&(this.#c.length===0||s!==null)&&this.#x(),this.#c.length>0){if(s!==null){let e=s;e.#c.push(...this.#c.filter(t=>!e.#c.includes(t)))}else s=this}s!==null&&(It.clear(),s.#g())}#_(e,t,n){e.f^=m;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#f.has(r))&&r.fn!==null){a?r.f^=m:i&4?t.push(r):Jn(r)&&(i&16&&this.#d.add(r),er(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#v(){for(var e=this.#t;e!==null;){if(!e.is_fork){for(let[t,[,n]]of this.current)if(e.current.has(t)&&!n)return e}e=e.#t}return null}#y(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_effects(e.#u,e.#d);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#d.delete(i),j(i,h),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#x(),N=this,this.#g()}#b(e){for(var t=0;t<e.length;t+=1)Ze(e[t],this.#u,this.#d)}capture(e,t,n=!1){e.v!==T&&!this.previous.has(e)&&this.previous.set(e,e.v),e.f&8388608||(this.current.set(e,[t,n]),yt?.set(e,t)),this.is_fork||(e.v=t)}activate(){N=this}deactivate(){N=null,yt=null}flush(){try{St=!0,N=this,this.#g()}finally{Tt=0,bt=null,Ct=null,wt=null,St=!1,N=null,yt=null,It.clear()}}discard(){for(let e of this.#i)e(this);this.#i.clear();for(let e of this.async_deriveds.values())e.reject(lt);this.#x(),this.#s?.resolve()}register_created_effect(e){this.#l.push(e)}increment(e,t){if(this.#a+=1,e){let e=this.#o.get(t)??0;this.#o.set(t,e+1)}}decrement(e,t){if(--this.#a,e){let e=this.#o.get(t)??0;e===1?this.#o.delete(t):this.#o.set(t,e-1)}this.#m||(this.#m=!0,Ke(()=>{this.#m=!1,this.linked&&this.flush()}))}transfer_effects(e,t){for(let t of e)this.#u.add(t);for(let e of t)this.#d.add(e);e.clear(),t.clear()}oncommit(e){this.#r.add(e)}ondiscard(e){this.#i.add(e)}settled(){return(this.#s??=p()).promise}static ensure(){if(N===null){let t=N=new e;!St&&!xt&&Ke(()=>{t.#e||t.flush()})}return N}apply(){yt=null}schedule(e){if(bt=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}for(var t=e;t.parent!==null;){t=t.parent;var n=t.f;if(Ct!==null&&t===U&&(H===null||!(H.f&2)))return;if(n&96){if(!(n&1024))return;t.f^=m}}this.#c.push(t)}#x(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?_t=e:t.#t=e,this.linked=!1}}};function Ot(e){var t=xt;xt=!0;try{var n;for(e&&(N!==null&&!N.is_fork&&N.flush(),n=e());;){if(qe(),N===null)return n;N.flush()}}finally{xt=t}}function kt(){try{Pe()}catch(e){sn(e,bt)}}var At=null;function jt(e){var t=e.length;if(t!==0){for(var n=0;n<t;){var r=e[n++];if(!(r.f&24576)&&Jn(r)&&(At=new Set,er(r),r.deps===null&&r.first===null&&r.nodes===null&&r.teardown===null&&r.ac===null&&Tn(r),At?.size>0)){It.clear();for(let e of At){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)At.has(n)&&(At.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||er(n)}}At.clear()}}At=null}}function Mt(e){N.schedule(e)}function Nt(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),j(e,m);for(var n=e.first;n!==null;)Nt(n,t),n=n.next}}function Pt(e){j(e,m);for(var t=e.first;t!==null;)Pt(t),t=t.next}var Ft=new Set,It=new Map,Lt=!1;function Rt(e,t){return{f:0,v:e,reactions:null,equals:Te,rv:0,wv:0}}function P(e,t){let n=Rt(e,t);return zn(n),n}function zt(e,t=!1,n=!0){let r=Rt(e);return t||(r.equals=De),r}function F(e,t,n=!1){return H!==null&&(!Fn||H.f&131072)&&Ue()&&H.f&4325394&&(Rn===null||!Rn.has(e))&&Le(),Bt(e,n?Wt(t):t,wt)}function Bt(e,t,n=null){if(!e.equals(t)){Nn?It.set(e,t):It.has(e)||It.set(e,e.v);var r=Dt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&pt(t),yt===null&&Ye(t)}e.wv=qn(),Ut(e,h,n),Ue()&&U!==null&&U.f&1024&&!(U.f&96)&&(Vn===null?Hn([e]):Vn.push(e)),!r.is_fork&&Ft.size>0&&!Lt&&Vt()}return t}function Vt(){Lt=!1;for(let e of Ft){e.f&1024&&j(e,g);let t;try{t=Jn(e)}catch{t=!0}t&&er(e)}Ft.clear()}function Ht(e){F(e,e.v+1)}function Ut(e,t,n){var r=e.reactions;if(r!==null)for(var i=Ue(),a=r.length,o=0;o<a;o++){var s=r[o],c=s.f;if(i||s!==U){var l=(c&h)===0;if(l&&j(s,t),c&131072)Ft.add(s);else if(c&2){var u=s;yt?.delete(u),c&65536||(c&512&&(U===null||!(U.f&2097152))&&(s.f|=C),Ut(u,g,n))}else if(l){var d=s;c&16&&At!==null&&At.add(d),n===null?Mt(d):n.push(d)}}}}function Wt(t){if(typeof t!=`object`||!t||w in t||ae in t)return t;let n=l(t);if(n!==s&&n!==c)return t;var r=new Map,i=e(t),o=P(0),u=null,d=Gn,f=e=>{if(Gn===d)return e();var t=H,n=Gn;In(null),Kn(d);var r=e();return In(t),Kn(n),r};return i&&r.set(`length`,P(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&Fe();var i=r.get(t);return i===void 0?f(()=>{var e=P(n.value,u);return r.set(t,e),e}):F(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>P(T,u));r.set(t,e),Ht(o)}}else F(n,T),Ht(o);return!0},get(e,n,i){if(n===w)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>P(Wt(s?e[n]:T),u)),r.set(n,o)),o!==void 0){var c=G(o);return c===T?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){var n=Reflect.getOwnPropertyDescriptor(e,t);if(n&&`value`in n){var i=r.get(t);i&&(n.value=G(i))}else if(n===void 0){var a=r.get(t),o=a?.v;if(a!==void 0&&o!==T)return{enumerable:!0,configurable:!0,value:o,writable:!0}}return n},has(e,t){if(t===w)return!0;var n=r.get(t),i=n!==void 0&&n.v!==T||Reflect.has(e,t);return(n!==void 0||U!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>P(i?Wt(e[t]):T,u)),r.set(t,n)),G(n)===T)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;d<c.v;d+=1){var p=r.get(d+``);p===void 0?d in e&&(p=f(()=>P(T,u)),r.set(d+``,p)):F(p,T)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>P(void 0,u)),F(c,Wt(n)),r.set(t,c));else{l=c.v!==T;var m=f(()=>Wt(n));F(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&F(g,_+1)}Ht(o)}return!0},ownKeys(e){G(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==T});for(var[n,i]of r)i.v!==T&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Ie()}})}function Gt(e){try{if(typeof e==`object`&&e&&w in e)return e[w]}catch{}return e}function Kt(e,t){return Object.is(Gt(e),Gt(t))}var qt,Jt,Yt,Xt;function Zt(){if(qt===void 0){qt=window,Jt=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;Yt=a(t,`firstChild`).get,Xt=a(t,`nextSibling`).get,u(e)&&(e[ce]=void 0,e[se]=null,e[le]=void 0,e.__e=void 0),u(n)&&(n[ue]=void 0)}}function I(e=``){return document.createTextNode(e)}function Qt(e){return Yt.call(e)}function $t(e){return Xt.call(e)}function L(e,t){if(!E)return Qt(e);var n=Qt(D);if(n===null)n=D.appendChild(I());else if(t&&n.nodeType!==3){var r=I();return n?.before(r),O(r),r}return t&&an(n),O(n),n}function en(e,t=!1){if(!E){var n=Qt(e);return n instanceof Comment&&n.data===``?$t(n):n}if(t){if(D?.nodeType!==3){var r=I();return D?.before(r),O(r),r}an(D)}return D}function R(e,t=!1){if(!E)return Qt(e);var n=L(e,t);return k(e),n}function z(e,t=1,n=!1){let r=E?D:e;for(var i;t--;)i=r,r=$t(r);if(!E)return r;if(n){if(r?.nodeType!==3){var a=I();return r===null?i?.after(a):r.before(a),O(a),a}an(r)}return O(r),r}function tn(e){e.textContent=``}function nn(){return!1}function rn(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function an(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function on(e){var t=U;if(t===null)return H.f|=ie,e;if(!(t.f&32768)&&!(t.f&4))throw e;sn(e,t)}function sn(e,t){if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128&&!(t.f&33570816)){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}function cn(e){U===null&&(H===null&&Ne(e),Me()),Nn&&je(e)}function ln(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function un(e,t){var n=U;n!==null&&n.f&8192&&(e|=_);var r={ctx:A,deps:null,nodes:null,f:e|h|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};N?.register_created_effect(r);var i=r;if(e&4)Ct===null?Dt.ensure().schedule(r):Ct.push(r);else if(t!==null){try{er(r)}catch(e){throw V(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=x))}if(i!==null&&(i.parent=n,n!==null&&ln(i,n),H!==null&&H.f&2&&!(e&64))){var a=H;(a.effects??=[]).push(i)}return r}function dn(){return H!==null&&!Fn}function fn(e){let t=un(8,null);return j(t,m),t.teardown=e,t}function pn(e){cn(`$effect`);var t=U.f;if(!H&&t&32&&A!==null&&!A.i){var n=A;(n.e??=[]).push(e)}else return mn(e)}function mn(e){return un(4|ee,e)}function hn(e){Dt.ensure();let t=un(64|S,e);return(e={})=>new Promise(n=>{e.outro?En(t,()=>{V(t),n(void 0)}):(V(t),n(void 0))})}function gn(e){return un(4,e)}function _n(e){return un(re|S,e)}function vn(e,t=0){return un(8|t,e)}function B(e,t=[],n=[],r=[]){it(r,t,n,t=>{un(8,()=>{e(...t.map(G))})})}function yn(e,t=0){return un(16|t,e)}function bn(e){return un(32|S,e)}function xn(e){var t=e.teardown;if(t!==null){let n=Nn,r=H;Pn(!0),In(null);try{t.call(null)}catch(t){sn(t,e.parent)}finally{Pn(n),In(r)}}}function Sn(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&nt(()=>{e.abort(fe)});var r=n.next;n.f&64?n.parent=null:V(n,t),n=r}}function Cn(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||V(t),t=n}}function V(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(wn(e.nodes.start,e.nodes.end),n=!0),e.f|=b,Sn(e,t&&!n),$n(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();xn(e),e.f^=b,e.f|=v;var i=e.parent;i!==null&&i.first!==null&&Tn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function wn(e,t){for(;e!==null;){var n=e===t?null:$t(e);e.remove(),e=n}}function Tn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function En(e,t,n=!0){var r=[];e.f|=256,Dn(e,r,!0);var i=()=>{n&&V(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function Dn(e,t,n){if(!(e.f&8192)){e.f^=_;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);Dn(i,t,o?n:!1)}i=a}}}function On(e){e.f&=-257,kn(e,!0)}function kn(e,t){if(!(e.f&256)&&e.f&8192){e.f^=_,e.f&1024||(j(e,h),Dt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);kn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function An(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:$t(n);t.append(n),n=i}}var jn=null,Mn=!1,Nn=!1;function Pn(e){Nn=e}var H=null,Fn=!1;function In(e){H=e}var U=null;function Ln(e){U=e}var Rn=null;function zn(e){H!==null&&(Rn??=new Set).add(e)}var W=null,Bn=0,Vn=null;function Hn(e){Vn=e}var Un=1,Wn=0,Gn=Wn;function Kn(e){Gn=e}function qn(){return++Un}function Jn(e){var t=e.f;if(t&2048)return!0;if(t&2&&(e.f&=~C),t&4096){for(var n=e.deps,r=n.length,i=0;i<r;i++){var a=n[i];if(Jn(a)&&mt(a),a.wv>e.wv)return!0}t&512&&yt===null&&j(e,m)}return!1}function Yn(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Rn!==null&&Rn.has(e)))for(var i=0;i<r.length;i++){var a=r[i];a.f&2?Yn(a,t,!1):t===a&&(n?j(a,h):a.f&1024&&j(a,g),Mt(a))}}function Xn(e){var t=W,n=Bn,r=Vn,i=H,a=Rn,o=A,s=Fn,c=Gn,l=e.f;W=null,Bn=0,Vn=null,H=l&96?null:e,Rn=null,ze(e.ctx),Fn=!1,Gn=++Wn,e.ac!==null&&(nt(()=>{e.ac.abort(fe)}),e.ac=null);try{e.f|=ne;var u=e.fn,d=u();e.f|=y;var f=Zn(e);if(Ue()&&Vn!==null&&!Fn&&f!==null&&!(e.f&6146))for(var p=0;p<Vn.length;p++)Yn(Vn[p],e);if(i!==null&&i!==e){if(Wn++,i.deps!==null)for(let e=0;e<n;e+=1)i.deps[e].rv=Wn;if(t!==null)for(let e of t)e.rv=Wn;Vn!==null&&(r===null?r=Vn:r.push(...Vn))}return e.f&8388608&&(e.f^=ie),d}catch(t){return Zn(e),on(t)}finally{e.f^=ne,W=t,Bn=n,Vn=r,H=i,Rn=a,ze(o),Fn=s,Gn=c}}function Zn(e){var t=e.deps,n=N?.is_fork;if(W!==null){var r;if(n||$n(e,Bn),t!==null&&Bn>0)for(t.length=Bn+W.length,r=0;r<W.length;r++)t[Bn+r]=W[r];else e.deps=t=W;if(dn()&&e.f&512)for(r=Bn;r<t.length;r++)(t[r].reactions??=[]).push(e)}else!n&&t!==null&&Bn<t.length&&($n(e,Bn),t.length=Bn);return t}function Qn(e,r){let i=r.reactions;if(i!==null){var a=t.call(i,e);if(a!==-1){var o=i.length-1;o===0?i=r.reactions=null:(i[a]=i[o],i.pop())}}if(i===null&&r.f&2&&(W===null||!n.call(W,r))){var s=r;s.f&512&&(s.f^=512,s.f&=~C),s.v!==T&&Ye(s),s.ac!==null&&nt(()=>{s.ac.abort(fe),s.ac=null,j(s,h)}),ht(s),$n(s,0)}}function $n(e,t){var n=e.deps;if(n!==null)for(var r=t;r<n.length;r++)Qn(e,n[r])}function er(e){var t=e.f;if(!(t&16384)){j(e,m);var n=U,r=Mn;U=e,Mn=!(t&96);try{t&16777232?Cn(e):Sn(e),xn(e);var i=Xn(e);e.teardown=typeof i==`function`?i:null,e.wv=Un}finally{Mn=r,U=n}}}async function tr(){await Promise.resolve(),Ot()}function G(e){var t=!!(e.f&2);if(jn?.add(e),H!==null&&!Fn&&!(U!==null&&U.f&16384)&&(Rn===null||!Rn.has(e))){var r=H.deps;if(H.f&2097152)e.rv<Wn&&(e.rv=Wn,W===null&&r!==null&&r[Bn]===e?Bn++:W===null?W=[e]:W.push(e));else{H.deps??=[],n.call(H.deps,e)||H.deps.push(e);var i=e.reactions;i===null?e.reactions=[H]:n.call(i,H)||i.push(H)}}if(Nn&&It.has(e))return It.get(e);if(t){var a=e;if(Nn){var o=a.v;return(!(a.f&1024)&&a.reactions!==null||rr(a))&&(o=pt(a)),It.set(a,o),o}var s=!(a.f&512)&&!Fn&&H!==null&&(Mn||!!(H.f&512)),c=(a.f&y)===0;Jn(a)&&(s&&(a.f|=512),mt(a)),s&&!c&&(gt(a),nr(a))}if(yt?.has(e))return yt.get(e);if(e.f&8388608)throw e.v;return e.v}function nr(e){if(e.f|=512,e.deps!==null)for(let t of e.deps)(t.reactions??=[]).push(e),t.f&2&&!(t.f&512)&&(gt(t),nr(t))}function rr(e){if(e.v===T)return!0;if(e.deps===null)return!1;for(let t of e.deps)if(It.has(t)||t.f&2&&rr(t))return!0;return!1}function ir(e){var t=Fn;try{return Fn=!0,e()}finally{Fn=t}}[...`allowfullscreen.async.autofocus.autoplay.checked.controls.default.disabled.formnovalidate.indeterminate.inert.ismap.loop.multiple.muted.nomodule.novalidate.open.playsinline.readonly.required.reversed.seamless.selected.webkitdirectory.defer.disablepictureinpicture.disableremoteplayback`.split(`.`)];var ar=[`touchstart`,`touchmove`];function or(e){return ar.includes(e)}var sr=Symbol(`events`),cr=new Set,lr=new Set;function ur(e,t,n,r={}){function i(e){if(r.capture||hr.call(t,e),!e.cancelBubble)return nt(()=>n?.call(this,e))}return e.startsWith(`pointer`)||e.startsWith(`touch`)||e===`wheel`?Ke(()=>{t.addEventListener(e,i,r)}):t.addEventListener(e,i,r),i}function dr(e,t,n,r,i){var a={capture:r,passive:i},o=ur(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&fn(()=>{t.removeEventListener(e,o,a)})}function K(e,t,n){(t[sr]??={})[e]=n}function fr(e){for(var t=0;t<e.length;t++)cr.add(e[t]);for(var n of lr)n(e)}var pr=null,mr=!1;function hr(e){var t=this,n=t.ownerDocument,r=e.type,a=e.composedPath?.()||[],o=a[0]||e.target;pr=e,mr||(mr=!0,setTimeout(()=>{mr=!1,pr=null}));var s=0,c=pr===e&&e[sr];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[sr]=t;return}var u=a.indexOf(t);if(u===-1)return;l<=u&&(s=l)}if(o=a[s]||e.target,o!==t){i(e,`currentTarget`,{configurable:!0,get(){return o||n}});var d=H,f=U;In(null),Ln(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[sr]?.[r];h!=null&&(!o.disabled||e.target===o)&&h.call(o,e)}catch(e){p?m.push(e):p=e}if(e.cancelBubble)break;s++,o=s<a.length?a[s]:null}if(p){for(let e of m)queueMicrotask(()=>{throw e});throw p}}finally{e[sr]=t,delete e.currentTarget,In(d),Ln(f)}}}var gr=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function _r(e){return gr?.createHTML(e)??e}function vr(e){var t=rn(`template`);return t.innerHTML=_r(e.replaceAll(`<!>`,`<!---->`)),t.content}function yr(e,t){var n=U;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function q(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(`<!>`);return()=>{if(E)return yr(D,null),D;i===void 0&&(i=vr(a?e:`<!>`+e),n||(i=Qt(i)));var t=r||Jt?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=Qt(t),s=t.lastChild;yr(o,s)}else yr(t,t);return t}}function br(e,t,n=`svg`){var r=!e.startsWith(`<!>`),i=!!(t&1),a=`<${n}>${r?e:`<!>`+e}</${n}>`,o;return()=>{if(E)return yr(D,null),D;if(!o){var e=Qt(vr(a));if(i)for(o=document.createDocumentFragment();Qt(e);)o.appendChild(Qt(e));else o=Qt(e)}var t=o.cloneNode(!0);if(i){var n=Qt(t),r=t.lastChild;yr(n,r)}else yr(t,t);return t}}function xr(e,t){return br(e,t,`svg`)}function Sr(e=``){if(!E){var t=I(e+``);return yr(t,t),t}var n=D;return n.nodeType===3?an(n):(n.before(n=I()),O(n)),yr(n,n),n}function Cr(){if(E)return yr(D,null),D;var e=document.createDocumentFragment(),t=document.createComment(``),n=I();return e.append(t,n),yr(t,n),e}function J(e,t){if(E){var n=U;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=D),xe();return}e!==null&&e.before(t)}function wr(e){let t=0,n=Rt(0),r;return()=>{dn()&&(G(n),vn(()=>(t===0&&(r=ir(()=>e(()=>Ht(n)))),t+=1,()=>{Ke(()=>{--t,t===0&&(r?.(),r=void 0,Ht(n))})})))}}var Tr=x|S;function Er(e,t,n,r){new Dr(e,t,n,r)}var Dr=class{parent;is_pending=!1;transform_error;#e;#t=E?D:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Set;#p=new Set;#m=null;#h=wr(()=>(this.#m=Rt(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=U;t.b=this,t.f|=128,n(e)},this.parent=U.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=yn(()=>{if(E){let e=this.#t;xe();let t=e.data===`[!`;if(e.data.startsWith(`[?`)){let t=JSON.parse(e.data.slice(2));this.#_(t)}else t?this.#y():this.#g()}else this.#b()},Tr),E&&(this.#e=D)}#g(){try{this.#a=bn(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Ke(r),t&&(this.#s=bn(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){ye();return}t=!0,n&&Re(),this.#s!==null&&En(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})};return{reset:r,invoke_onerror:()=>{try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){sn(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=bn(()=>e(this.#e)),Ke(()=>{var e=this.#c=document.createDocumentFragment(),t=I(),n=!1;if(e.append(t),this.#a=this.#S(()=>{try{return bn(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){sn(e,this.#i.parent)}return null}}),this.#a===null){this.#c=null,n&&this.#x(N);return}this.#u===0&&(this.#e.before(e),this.#c=null,En(this.#o,()=>{this.#o=null}),this.#x(N))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=bn(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();An(this.#a,e);let t=this.#n.pending;this.#o=bn(()=>t(this.#e))}else this.#x(N)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){Ze(e,this.#f,this.#p)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=U,n=H,r=A;Ln(this.#i),In(this.#i),ze(this.#i.ctx);try{return Dt.ensure(),e()}finally{Ln(t),In(n),ze(r)}}#C(e,t){if(!this.has_pending_snippet()){this.parent&&this.parent.#C(e,t);return}this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&En(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!(!this.#m||this.#d)&&(this.#d=!0,Ke(()=>{this.#d=!1,this.#m&&Bt(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),G(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;N?.is_fork?(this.#a&&N.skip_effect(this.#a),this.#o&&N.skip_effect(this.#o),this.#s&&N.skip_effect(this.#s),N.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(V(this.#a),null),this.#o&&=(V(this.#o),null),this.#s&&=(V(this.#s),null),E&&(O(this.#t),Se(),O(Ce()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return bn(()=>{var r=U;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return sn(e,this.#i.parent),null}}))};Ke(()=>{var t;try{t=this.transform_error(e)}catch(e){sn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>sn(e,this.#i&&this.#i.parent)):n(t)})}};function Y(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[ue]??=e.nodeValue)&&(e[ue]=n,e.nodeValue=`${n}`)}function Or(e,t){return Ar(e,t)}var kr=new Map;function Ar(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){Zt();var l=void 0,u=hn(()=>{var s=n??t.appendChild(I());Er(s,{pending:()=>{}},t=>{Be({});var n=A;if(o&&(n.c=o),a&&(i.$$events=a),E&&yr(t,null),l=e(t,i)||He(),E&&(U.nodes.end=D,D===null||D.nodeType!==8||D.data!==`]`))throw _e(),me;Ve()},c);var u=new Set,d=e=>{for(var n=0;n<e.length;n++){var r=e[n];if(!u.has(r)){u.add(r);var i=or(r);for(let e of[t,document]){var a=kr.get(e);a===void 0&&(a=new Map,kr.set(e,a));var o=a.get(r);o===void 0?(e.addEventListener(r,hr,{passive:i}),a.set(r,1)):a.set(r,o+1)}}}};return d(r(cr)),lr.add(d),()=>{for(var e of u)for(let n of[t,document]){var r=kr.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,hr),r.delete(e),r.size===0&&kr.delete(n)):r.set(e,i)}lr.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return jr.set(l,u),l}var jr=new WeakMap,Mr=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)On(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(On(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(V(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();An(r,t),t.append(I()),this.#n.set(e,{effect:r,fragment:t})}else V(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),En(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(V(n.effect),this.#n.delete(e))};ensure(e,t){var n=N,r=nn();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=I();i.append(a),this.#n.set(e,{effect:bn(()=>t(a)),fragment:i})}else this.#t.set(e,bn(()=>t(this.anchor)))}if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else E&&(this.anchor=D),this.#a(n)}};function X(e,t,n=!1){var r;E&&(r=D,xe());var i=new Mr(e),a=n?x:0;function o(e,t){if(E){var n=we(r);if(e!==parseInt(n.substring(1))){var a=Ce();O(a),i.anchor=a,be(!1),i.ensure(e,t),be(!0);return}}i.ensure(e,t)}yn(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}function Nr(e,t){return t}function Pr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c<a;c++){let n=t[c];En(n,()=>{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;Fr(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null&&e.pending.size===0;if(l){var u=n,d=u.parentNode;tn(d),d.append(u),e.items.clear()}Fr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Fr(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i<t.length;i++){var a=t[i];r?.has(a)?(a.f|=te,An(a,document.createDocumentFragment())):V(t[i],n)}}var Ir;function Z(t,n,i,a,o,s=null){var c=t,l=new Map;if(n&4){var u=t;c=E?O(Qt(u)):u.appendChild(I())}E&&xe();var d=null,f=dt(()=>{var t=i();return e(t)?t:t==null?[]:r(t)}),p,m=new Map,h=!0;function g(e){v.effect.f&16384||(v.pending.delete(e),v.fallback=d,Rr(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=te,Br(d,null,c)):On(d):En(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:yn(()=>{p=G(f);var e=p.length;let t=!1;E&&we(c)===`[!`!=(e===0)&&(c=Ce(),O(c),be(!1),t=!0);for(var r=new Set,u=N,v=nn(),y=0;y<e;y+=1){E&&D.nodeType===8&&D.data===`]`&&(c=D,t=!0,be(!1));var b=p[y],x=a(b,y),S=h?null:l.get(x);S?(S.v&&Bt(S.v,b),S.i&&Bt(S.i,y),v&&u.unskip_effect(S.e)):(S=zr(l,h?c:Ir??=I(),b,x,y,o,n,i),h||(S.e.f|=te),l.set(x,S)),r.add(x)}if(e===0&&s&&!d&&(h?d=bn(()=>s(c)):(d=bn(()=>s(Ir??=I())),d.f|=te)),e>r.size&&Ae(``,``,``),E&&e>0&&O(Ce()),!h){if(m.set(u,r),v){for(let[e,t]of l)r.has(e)||u.skip_effect(t.e);u.oncommit(g),u.ondiscard(_)}else g(u)}t&&be(!0),G(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,E&&(c=D)}function Lr(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function Rr(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=Lr(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v<s;v+=1)h=t[v],g=a(h,v),_=c.get(g).e,_.f&33554432||(_.nodes?.a?.measure(),(f??=new Set).add(_));for(v=0;v<s;v+=1){if(h=t[v],g=a(h,v),_=c.get(g).e,e.outrogroups!==null)for(let t of e.outrogroups)t.pending.delete(_),t.done.delete(_);if(_.f&8192&&(On(_),o&&(_.nodes?.a?.unfix(),(f??=new Set).delete(_))),_.f&33554432){if(_.f^=te,_===l)Br(_,null,n);else{var y=d?d.next:l;_===e.effect.last&&(e.effect.last=_.prev),_.prev&&(_.prev.next=_.next),_.next&&(_.next.prev=_.prev),Vr(e,d,_),Vr(e,_,y),Br(_,y,n),d=_,p=[],m=[],l=Lr(d.next);continue}}if(_!==l){if(u!==void 0&&u.has(_)){if(p.length<m.length){var b=m[0],x;d=b.prev;var S=p[0],ee=p[p.length-1];for(x=0;x<p.length;x+=1)Br(p[x],b,n);for(x=0;x<m.length;x+=1)u.delete(m[x]);Vr(e,S.prev,ee.next),Vr(e,d,S),Vr(e,ee,b),l=b,d=ee,--v,p=[],m=[]}else u.delete(_),Br(_,l,n),Vr(e,_.prev,_.next),Vr(e,_,d===null?e.effect.first:d.next),Vr(e,d,_),d=_;continue}for(p=[],m=[];l!==null&&l!==_;)(u??=new Set).add(l),m.push(l),l=Lr(l.next);if(l===null)continue}_.f&33554432||p.push(_),d=_,l=Lr(_.next)}if(e.outrogroups!==null){for(let t of e.outrogroups)t.pending.size===0&&(Fr(e,r(t.done)),e.outrogroups?.delete(t));e.outrogroups.size===0&&(e.outrogroups=null)}if(l!==null||u!==void 0){var C=[];if(u!==void 0)for(_ of u)_.f&8192||C.push(_);for(;l!==null;)!(l.f&8192)&&l!==e.fallback&&C.push(l),l=Lr(l.next);var ne=C.length;if(ne>0){var re=i&4&&s===0?n:null;if(o){for(v=0;v<ne;v+=1)C[v].nodes?.a?.measure();for(v=0;v<ne;v+=1)C[v].nodes?.a?.fix()}Pr(e,C,re)}}o&&Ke(()=>{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function zr(e,t,n,r,i,a,o,s){var c=o&1?o&16?Rt(n):zt(n,!1,!1):null,l=o&2?Rt(i):null;return{v:c,i:l,e:bn(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function Br(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=$t(r);if(a.before(r),r===i)return;r=o}}function Vr(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function Hr(e,t,...n){var r=new Mr(e);yn(()=>{let e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},x)}var Ur=[...`
|
|
2
|
+
\r\f\xA0\v`];function Wr(e,t,n){var r=e==null?``:``+e;if(t&&(r=r?r+` `+t:t),n){for(var i of Object.keys(n))if(n[i])r=r?r+` `+i:i;else if(r.length)for(var a=i.length,o=0;(o=r.indexOf(i,o))>=0;){var s=o+a;(o===0||Ur.includes(r[o-1]))&&(s===r.length||Ur.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function Gr(e,t=!1){var n=t?` !important;`:`;`,r=``;for(var i of Object.keys(e)){var a=e[i];a!=null&&a!==``&&(r+=` `+i+`: `+a+n)}return r}function Kr(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function qr(e,t){if(t){var n=``,r,i;if(Array.isArray(t)?(r=t[0],i=t[1]):r=t,e){e=String(e).replaceAll(/\/\*.*?\*\//g,``).trim();var a=!1,o=0,s=!1,c=[];r&&c.push(...Object.keys(r).map(Kr)),i&&c.push(...Object.keys(i).map(Kr));var l=0,u=-1;let t=e.length;for(var d=0;d<t;d++){var f=e[d];if(s?f===`/`&&e[d-1]===`*`&&(s=!1):a?a===f&&(a=!1):f===`/`&&e[d+1]===`*`?s=!0:f===`"`||f===`'`?a=f:f===`(`?o++:f===`)`&&o--,!s&&a===!1&&o===0){if(f===`:`&&u===-1)u=d;else if(f===`;`||d===t-1){if(u!==-1){var p=Kr(e.substring(l,u).trim());if(!c.includes(p)){f!==`;`&&d++;var m=e.substring(l,d).trim();n+=` `+m+`;`}}l=d+1,u=-1}}}}return r&&(n+=Gr(r)),i&&(n+=Gr(i,!0)),n=n.trim(),n===``?null:n}return e==null?null:String(e)}function Jr(e,t,n,r,i,a){var o=e[ce];if(E||o!==n||o===void 0){var s=Wr(n,r,a);(!E||s!==e.getAttribute(`class`))&&(s==null?e.removeAttribute(`class`):t?e.className=s:e.setAttribute(`class`,s)),e[ce]=n}else if(a&&i!==a)for(var c in a){var l=!!a[c];(i==null||l!==!!i[c])&&e.classList.toggle(c,l)}return a}function Yr(e,t={},n,r){for(var i in n){var a=n[i];t[i]!==a&&(n[i]==null?e.style.removeProperty(i):e.style.setProperty(i,a,r))}}function Xr(e,t,n,r){var i=e[le];if(E||i!==t){var a=qr(t,r);(!E||a!==e.getAttribute(`style`))&&(a==null?e.removeAttribute(`style`):e.style.cssText=a),e[le]=t}else r&&(Array.isArray(r)?(Yr(e,n?.[0],r[0]),Yr(e,n?.[1],r[1],`important`)):Yr(e,n,r));return r}function Zr(e,t){t?e.hasAttribute(`selected`)||e.setAttribute(`selected`,``):e.removeAttribute(`selected`)}function Qr(t,n){var r=t.__defaultValue,i=t.multiple,a=i?r??[]:null;if(!i||e(a)){var o=t.selectedIndex,s=n&&i?new Set(t.selectedOptions):null;for(var c of t.options){var l=ti(c);Zr(c,i?a.includes(l):Kt(l,r))}if(n){if(s!==null)for(c of t.options){var u=s.has(c);c.selected!==u&&(c.selected=u)}else t.selectedIndex!==o&&(t.selectedIndex=o)}}}function $r(t,n,r=!1){if(t.multiple){if(n==null)return;if(!e(n))return ve();for(var i of t.options)i.selected=n.includes(ti(i));return}for(i of t.options)if(Kt(ti(i),n)){i.selected=!0;return}(!r||n!==void 0)&&(t.selectedIndex=-1)}function ei(e){var t=new MutationObserver(t=>{t.every(ni)||(`__defaultValue`in e&&Qr(e,!1),`__value`in e&&$r(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),fn(()=>{t.disconnect()})}function ti(e){return`__value`in e?e.__value:e.value}function ni(e){if(e.target.closest(`selectedcontent`)!==null)return!0;if(e.type===`childList`){var t=[...e.addedNodes,...e.removedNodes];return t.length>0&&t.every(e=>e.nodeName===`SELECTEDCONTENT`)}return!1}var ri=Symbol(`is custom element`),ii=Symbol(`is html`),ai=pe?`link`:`LINK`;function oi(e){if(E){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;Q(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;Q(e,`checked`,null),e.checked=r}}};e[de]=n,Ke(n),tt()}}function si(e,t){var n=ci(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=ci(e);E&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===ai)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[oe]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&ui(e).has(t)?e[t]=n:e.setAttribute(t,n))}function ci(e){return e[se]??={[ri]:e.nodeName.includes(`-`),[ii]:e.namespaceURI===he}}var li=new Map;function ui(e){var t=e.getAttribute(`is`)||e.nodeName,n=li.get(t);if(n)return n;li.set(t,n=new Set);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.add(s);i=l(i)}return n}function di(e,t,n=t){var r=new WeakSet;rt(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=fi(e)?pi(a):a,n(a),N!==null&&r.add(N),await tr(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(E&&e.defaultValue!==e.value||ir(t)==null&&e.value)&&(n(fi(e)?pi(e.value):e.value),N!==null&&r.add(N)),vn(()=>{var n=t();if(e===document.activeElement){var i=N;if(r.has(i))return}fi(e)&&n===pi(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}function fi(e){var t=e.type;return t===`number`||t===`range`}function pi(e){return e===``?null:+e}function mi(e,t){return e===t||e?.[w]===t}function hi(e=He(),t,n,r){var i=A.r,a=U;return gn(()=>{var o,s;return vn(()=>{o=s,s=r?.()||[],ir(()=>{mi(n(...s),e)||(t(e,...s),o&&mi(n(...o),e)&&t(null,...o))})}),()=>{let r=a;for(;r!==i&&r.parent!==null&&r.parent.f&33554432;)r=r.parent;let o=()=>{s&&mi(n(...s),e)&&t(null,...s)},c=r.teardown;r.teardown=()=>{o(),c?.()}}}),e}function gi(e){A===null&&Oe(`onMount`),pn(()=>{let t=ir(e);if(typeof t==`function`)return t})}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);var _i=xr(`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3.4 8.4 3 3 6.2-6.8"></path></svg>`),vi=xr(`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M8 4v5"></path><path d="M8 12h.01"></path></svg>`),yi=xr(`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"></path></svg>`),bi=q(`<span class="fix svelte-1grjtup"> </span>`),xi=q(`<li class="svelte-1grjtup"><span class="mark svelte-1grjtup" aria-hidden="true"><!></span> <span class="body svelte-1grjtup"><b class="svelte-1grjtup"> </b> <span class="msg svelte-1grjtup"> </span> <!></span> <span class="sr svelte-1grjtup"> </span></li>`),Si=q(`<section class="health svelte-1grjtup" aria-label="Health"><header class="svelte-1grjtup"><h2 class="svelte-1grjtup"> </h2> <p class="svelte-1grjtup">This is the same check <code>npx verbaly doctor</code> runs, read out loud. It looks at your
|
|
3
|
+
settings, your catalogs and the way your build is wired, and it never changes anything.</p> <button class="close svelte-1grjtup">Back to the messages</button></header> <ul class="svelte-1grjtup"></ul></section>`);function Ci(e,t){Be(t,!0);let n={config:`Your settings`,cli:`The verbaly command`,catalogs:`Your catalogs`,routing:`Where the language lives in your urls`,plugin:`The piece that wires your build`,types:`The generated types`,sources:`Reading your code`,orphans:`Keys nothing in your code uses`,bundle:`What the browser downloads`,translations:`The translations themselves`},r=M(()=>t.entries.filter(e=>e.level!==`ok`).length);var i=Si(),a=L(i),o=L(a),s=R(o,!0),c=z(o,4);k(a);var l=z(a,2);Z(l,21,()=>t.entries,Nr,(e,t)=>{var r=xi(),i=L(r),a=L(i),o=e=>{J(e,_i())},s=e=>{J(e,vi())},c=e=>{J(e,yi())};X(a,e=>{G(t).level===`ok`?e(o):G(t).level===`warn`?e(s,1):e(c,-1)}),k(i);var l=z(i,2),u=L(l),d=R(u,!0),f=z(u,2),p=R(f,!0),m=z(f,2),h=e=>{var n=bi(),r=R(n,!0);B(()=>Y(r,G(t).fix)),J(e,n)};X(m,e=>{G(t).fix&&e(h)}),k(l);var g=R(z(l,2),!0);k(r),B(()=>{Q(r,`data-level`,G(t).level),Y(d,n[G(t).check]??G(t).check),Y(p,G(t).message),Y(g,G(t).level)}),J(e,r)}),k(l),k(i),B(()=>Y(s,t.ok?`Nothing is broken`:`${G(r)} of ${t.entries.length} need you`)),K(`click`,c,function(...e){t.onClose?.apply(this,e)}),J(e,i),Ve()}fr([`click`]);var wi={done:{short:`ready`,long:`ready`},draft:{short:`unread`,long:`written by a machine, nobody has read it`},missing:{short:`missing`,long:`missing, so your visitor sees the source language`},broken:{short:`breaks`,long:`breaks your site`}},Ti={all:`everything`,missing:`missing`,draft:`unread`,broken:`breaks your site`,look:`worth a look`},Ei={divergent:`the source says this two ways`,collision:`came back as two translations`,echo:`still identical to the source`,digits:`the numbers moved`,url:`a link changed`,code:`a code span changed`},Di={cap:`Group`,all:`every group`,none:`Your keys have no groups yet.`,hint:`A key like nav.home belongs to nav.`},Oi=`Undo`,$={find:`Find new text`,findWhy:`Reads your code and adds what your catalogs do not have yet.`,translate:`Translate what is missing`,translateWhy:`Calls your provider, so it costs money and takes minutes.`,cancel:`Not now`,working:`Reading your code`,running:`Translating`,nothingNew:`Nothing new: your catalogs already have every message your code uses.`,nothingMissing:`Nothing missing in the languages you ticked.`,pickFirst:`Tick a language to translate it.`,onlyLocale:`This project has one language, so there is nothing to translate into.`,scanOff:`Source scanning is off in your config, so there is nothing to read.`},ki={noCatalogs:`No messages yet. Studio reads the catalogs in your project, and there are none here.`,oneLocale:`One language is all you have, so there is nothing to compare it against yet.`,oneLocaleFix:`Add another one to your config and it shows up in the rail.`,pickOne:`Tick a language in the rail to see its translations.`,noMatch:`Nothing matches. Every message here is in the state you asked for.`};function Ai(e){return`${e} ${e===1?`message`:`messages`}`}var ji={broken:{one:`translation breaks your site`,many:`translations break your site`},missing:{one:`message is missing`,many:`messages are missing`},draft:{one:`translation nobody has read`,many:`translations nobody has read`},undefined:{one:`key your code calls has no message`,many:`keys your code calls have no message`}},Mi={broken:`It lost a parameter or a tag, so the sentence would ship incomplete.`,missing:`Your visitor sees the source language until one is written.`,draft:`A machine wrote it and nobody has looked. It is already on your site.`,undefined:`Nothing defines it, so the build fails and the raw key would reach your page.`},Ni={here:`Overview`,clear:`Nothing is waiting for you.`,clearWhy:`Every language is complete and the build passes.`,project:`Project`,healthy:`Healthy`,problems:`Needs a look`,checks:`checks`,history:`Last changes to your catalogs`,noHistory:`No git history for your catalog directory.`,countMessages:`Messages`,countLocales:`Languages`,open:`Open`},Pi={label:`Search your messages`,scope:`Searches your text in every language, never the key.`,none:`Nothing has that text, in any language.`,oneHit:`1 message`,hits:e=>`${e} messages`,moveKeys:`move`,openKeys:`open`,closeKeys:`close`,close:`Close`,placeholder:`Search the text, not the key`},Fi=q(`<span> </span>`),Ii=q(`<li><button><span> </span> <!></button></li>`),Li=q(`<button class="read svelte-l3e5c7"> <span class="n svelte-l3e5c7"> </span></button>`),Ri=q(`<li><label><input type="checkbox" class="svelte-l3e5c7"/> <span class="meta svelte-l3e5c7"><span class="name svelte-l3e5c7"> </span> <span class="state svelte-l3e5c7"> </span></span></label> <!></li>`),zi=q(`<p class="undo svelte-l3e5c7"><span> </span> <button class="svelte-l3e5c7"> </button></p>`),Bi=q(`<option> </option>`),Vi=q(`<h2 class="cap svelte-l3e5c7"> </h2> <select class="groups svelte-l3e5c7"><option> </option><!></select>`,1),Hi=q(`<li><button type="button"><span> </span> <span class="count svelte-l3e5c7"> </span></button></li>`),Ui=q(`<nav class="rail svelte-l3e5c7" aria-label="Languages and filters"><ul class="views svelte-l3e5c7"></ul> <!> <h2 class="cap svelte-l3e5c7">Languages</h2> <ul class="langs svelte-l3e5c7"></ul> <!> <!> <h2 class="cap svelte-l3e5c7">Show</h2> <ul class="filters svelte-l3e5c7"></ul></nav>`);function Wi(e,t){Be(t,!0);let n=[{id:`overview`,label:`Overview`},{id:`messages`,label:`Messages`},{id:`health`,label:`Health`}],r=[`all`,`look`,`missing`,`draft`,`broken`];function i(e){return e.source?`the one you write`:e.broken?`${e.broken} breaks your site`:e.missing?`${e.missing} missing`:e.draft?`${e.draft} nobody has read`:`all read`}function a(e){return e.source?`done`:e.broken?`broken`:e.missing?`missing`:e.draft?`draft`:`done`}var o=Ui(),s=L(o);Z(s,21,()=>n,e=>e.id,(e,n)=>{var r=Ii(),i=L(r);let a;var o=L(i),s=R(o,!0),c=z(o,2),l=e=>{var n=Fi();let r;var i=R(n,!0);B(()=>{r=Jr(n,1,`bad svelte-l3e5c7`,null,r,{clean:!t.checks.bad}),Y(i,t.checks.bad||`ok`)}),J(e,n)};X(c,e=>{G(n).id===`health`&&t.checks&&e(l)}),k(i),k(r),B(()=>{a=Jr(i,1,`nav svelte-l3e5c7`,null,a,{on:t.view===G(n).id}),Q(i,`aria-current`,t.view===G(n).id?`page`:void 0),Y(s,G(n).label)}),K(`click`,i,()=>t.onView(G(n).id)),J(e,r)}),k(s);var c=z(s,2);Hr(c,()=>t.actions);var l=z(c,4);Z(l,21,()=>t.health,e=>e.locale,(e,n)=>{var r=Ri(),o=L(r);let s;var c=L(o);oi(c);var l=z(c,2),u=L(l),d=R(u,!0),f=z(u,2),p=R(f,!0);k(l),k(o);var m=z(o,2),h=e=>{var r=Li(),i=L(r),a=R(z(i),!0);k(r),B(()=>{Y(i,`Mark as read `),Y(a,G(n).draft)}),K(`click`,r,()=>t.onRead(G(n).locale)),J(e,r)};X(m,e=>{!G(n).source&&G(n).draft>0&&e(h)}),k(r),B((e,t,r)=>{s=Jr(o,1,`lang svelte-l3e5c7`,null,s,{source:G(n).source}),si(c,e),c.disabled=G(n).source,Y(d,G(n).locale),Q(f,`data-state`,t),Y(p,r)},[()=>t.shown.includes(G(n).locale),()=>a(G(n)),()=>i(G(n))]),K(`change`,c,()=>t.onToggle(G(n).locale)),J(e,r)}),k(l);var u=z(l,2),d=e=>{var n=zi(),r=L(n),i=R(r),a=z(r,2),o=R(a,!0);k(n),B(()=>{Y(i,`${t.pending.keys.length??``} in ${t.pending.locale??``} marked as read`),Y(o,Oi)}),K(`click`,a,function(...e){t.onUndo?.apply(this,e)}),J(e,n)};X(u,e=>{t.pending&&e(d)});var f=z(u,2),p=e=>{var n=Vi(),r=en(n),i=R(r,!0),a=z(r,2),o=L(a),s=R(o,!0);o.value=o.__value=``,Z(z(o),17,()=>t.groups,e=>e.name,(e,t)=>{var n=Bi(),r=R(n),i={};B(()=>{Y(r,`${G(t).name??``} (${G(t).total??``})${G(t).broken+G(t).missing+G(t).draft>0?` · ${G(t).broken+G(t).missing+G(t).draft} to do`:``}`),i!==(i=G(t).name)&&(n.value=(n.__value=i)??``)}),J(e,n)}),k(a);var c;ei(a),B(()=>{Y(i,Di.cap),Q(a,`aria-label`,Di.cap),Y(s,Di.all),c!==(c=t.group??``)&&(a.value=(a.__value=c)??``,$r(a,c))}),K(`change`,a,e=>t.onGroup(e.currentTarget.value||null)),J(e,n)};X(f,e=>{t.groups.length&&e(p)});var m=z(f,4);Z(m,20,()=>r,e=>e,(e,n)=>{var r=Hi(),i=L(r);let a;var o=L(i),s=R(o,!0),c=R(z(o,2),!0);k(i),k(r),B(()=>{a=Jr(i,1,`svelte-l3e5c7`,null,a,{on:t.state===n}),Y(s,Ti[n]),Y(c,t.counts[n]??0)}),K(`click`,i,()=>t.onState(n)),J(e,r)}),k(m),k(o),J(e,o),Ve()}fr([`click`,`change`]);var Gi=xr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true"><path d="M5 11h12" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></svg>`),Ki=xr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true" fill="none"><path d="M6 12.5 11 7l5 5.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11 8v7" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"></path></svg>`),qi=xr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true" fill="none"><path d="M4.5 12.5c1.6-2.2 3.2-2.2 4.8 0s3.2 2.2 4.8 0 3.2-2.2 4.8 0" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"></path></svg>`),Ji=xr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true"><path d="M11 6v6.4" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path><circle cx="11" cy="16" r="1.2" fill="currentColor"></circle></svg>`),Yi=q(`<!> <span class="sr svelte-1fu82r1"> </span>`,1);function Xi(e,t){let n={done:`translated`,draft:`written by a machine`,missing:`not translated, shows in your source language`,broken:`breaks your site`};var r=Yi(),i=en(r),a=e=>{J(e,Gi())},o=e=>{J(e,Ki())},s=e=>{J(e,qi())},c=e=>{J(e,Ji())};X(i,e=>{t.state===`done`?e(a):t.state===`missing`?e(o,1):t.state===`draft`?e(s,2):e(c,-1)});var l=R(z(i,2),!0);B(()=>Y(l,n[t.state])),J(e,r)}var Zi=new Set;function Qi(e){Zi.has(e)||(Zi.add(e),console.warn(`[verbaly] ${e}`))}var $i=/\{\s*[a-zA-Z0-9_]+\s*,\s*(?:plural|selectordinal|select|number|date|time)\b/;function ea(e){return $i.test(e)}function ta(e){let t=0,n=()=>e.charAt(t),r=()=>{for(;t<e.length&&/\s/.test(n());)t++},i=()=>{let r=``;for(;t<e.length&&/[a-zA-Z0-9_]/.test(n());)r+=e[t++];return r};function a(r){let i=[],a=``,c=()=>{a&&i.push({kind:`text`,value:a}),a=``};for(;t<e.length;){let e=n();if(e===`}`)break;e===`{`?(c(),i.push(s())):e===`#`&&r?(c(),i.push({kind:`hash`}),t++):e===`'`?a+=o():(a+=e,t++)}return c(),i}function o(){if(t++,n()===`'`)return t++,`'`;let r=n();if(r!==`{`&&r!==`}`&&r!==`#`)return`'`;let i=``;for(;t<e.length;){if(n()===`'`){if(e.charAt(t+1)===`'`){i+=`'`,t+=2;continue}return t++,i}i+=e[t++]}return i}function s(){t++,r();let o=i();if(r(),n()===`}`)return t++,{kind:`param`,name:o};n()===`,`&&t++,r();let s=i(),u={kind:`param`,name:o};if(s===`number`||s===`date`||s===`time`){r();let i=``;if(n()===`,`){for(t++,r();t<e.length&&n()!==`}`&&n()!==`,`;)i+=e[t++];i=i.trim()}return s===`number`?u.format=i===`integer`||i===`percent`||i===`currency`?i:`number`:(u.format=s,i&&(u.arg=i)),l(),u}if(s===`plural`||s===`selectordinal`||s===`select`){s===`selectordinal`&&(u.ordinal=!0);let i=[];if(r(),n()===`,`&&t++,r(),s!==`select`&&e.startsWith(`offset:`,t)){for(t+=7,r();t<e.length&&/[0-9]/.test(n());)t++;r()}for(;t<e.length&&n()!==`}`;){let e=c();if(r(),n()!==`{`)break;t++;let o=a(s!==`select`);n()===`}`&&t++,i.push([e,o]),r()}return n()===`}`&&t++,u.variants=i,u}return l(),u}function c(){if(n()===`=`){let r=`=`;for(t++;t<e.length&&/[0-9]/.test(n());)r+=e[t++];return r}let r=``;for(;t<e.length&&!/[\s{]/.test(n());)r+=e[t++];return r}function l(){for(;t<e.length&&n()!==`}`;)t++;n()===`}`&&t++}return a(!1)}var na=new Map,ra=5e3;function ia(e,t){let n=na.get(e);if(!n){if(ea(e)){if(!t)return aa(e);n=t(e)}else n=oa(e,!1);na.size>=ra&&na.delete(na.keys().next().value),na.set(e,n)}return n}function aa(e){return Qi(`a message uses ICU syntax but no ICU parser is loaded: pass icu to createVerbaly (the compiler wires it when a catalog needs it, so this means it arrived after the build)`),[{kind:`text`,value:e}]}function oa(e,t){let n=[],r=``,i=0,a=()=>{r&&n.push({kind:`text`,value:r}),r=``};for(;i<e.length;){let o=e[i];if(o===`{`){if(e[i+1]===`{`){r+=`{`,i+=2;continue}let t=sa(e,i);if(t<0){r+=e.slice(i);break}a(),n.push(ca(e.slice(i+1,t))),i=t+1}else o===`}`&&e[i+1]===`}`?(r+=`}`,i+=2):t&&o===`#`?e[i+1]===`#`?(r+=`#`,i+=2):(a(),n.push({kind:`hash`}),i+=1):(r+=o,i+=1)}return a(),n}function sa(e,t){let n=0,r=t;for(;r<e.length;){let t=e[r];if(t===`{`){if(e[r+1]===`{`){r+=2;continue}n+=1}else if(t===`}`){if(e[r+1]===`}`){r+=2;continue}if(--n,n===0)return r}r+=1}return-1}function ca(e){let t=la(e),n=(t[0]??``).trim();if(!n)return{kind:`text`,value:`{${e}}`};let r=n.indexOf(`:`),i=(r<0?n:n.slice(0,r)).trim();if(!i)return{kind:`text`,value:`{${e}}`};let a={kind:`param`,name:i};if(r>=0){let e=n.slice(r+1).trim(),t=e.indexOf(`/`);a.format=(t<0?e:e.slice(0,t)).trim(),t>=0&&(a.arg=e.slice(t+1).trim())}if(t.length>1){a.variants=[];for(let e of t.slice(1)){let t=e.indexOf(`:`);if(t<0)continue;let n=e.slice(0,t).trim(),r=e.slice(t+1).trim();n&&a.variants.push([n,oa(r,!0)])}}return a}function la(e){let t=[],n=``,r=0,i=0;for(;i<e.length;){let a=e[i];if(a===`{`){if(e[i+1]===`{`){n+=`{{`,i+=2;continue}r+=1,n+=a}else if(a===`}`){if(e[i+1]===`}`){n+=`}}`,i+=2;continue}--r,n+=a}else if(a===`|`&&r===0){if(e[i+1]===`|`){n+=`|`,i+=2;continue}t.push(n),n=``}else n+=a;i+=1}return t.push(n),t}var ua=/<(\/?)([a-zA-Z][\w-]*)(\/?)>/g,da=/&(?:(lt|gt|amp)|#(\d+)|#[xX]([0-9a-fA-F]+));/g,fa={lt:`<`,gt:`>`,amp:`&`},pa=e=>e.replace(da,(e,t,n,r)=>{if(t)return fa[t];let i=n?parseInt(n,10):parseInt(r,16);return i<=1114111?String.fromCodePoint(i):e});function ma(e){ua.lastIndex=0;let t=[],n=[],r=()=>n.length?n[n.length-1].children:t,i=e=>{e&&r().push(pa(e))},a=0,o;for(;(o=ua.exec(e))!==null;){let[t,s,c,l]=o;if(i(e.slice(a,o.index)),a=o.index+t.length,l)r().push({name:c,children:[]});else if(s){if(n.length&&n[n.length-1].name===c){let e=n.pop();r().push(e)}else i(t)}else n.push({name:c,children:[]})}for(i(e.slice(a));n.length;){let e=n.pop();r().push(...e.children)}return t}function ha(e,t){for(let n of e)if(n.kind===`param`&&n.name){t.has(n.name)||t.set(n.name,new Set);for(let[e,r]of n.variants??[])t.get(n.name).add(e),ha(r,t)}}function ga(e){let t=new Map;try{ha(ia(e,ta),t)}catch{}return t}function _a(e,t){for(let n of e)typeof n!=`string`&&(t.push(n.name),_a(n.children,t))}function va(e){let t=[];try{_a(ma(e),t)}catch{return t}return t}function ya(e){let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);return t}var ba=e=>e.length===1?e[0]:`${e.slice(0,-1).join(`, `)} and ${e.at(-1)}`;function xa(e,t){let n=ga(e),r=ga(t),i=[...new Set([...n.keys(),...r.keys()])].sort().map(e=>({name:e,inSource:n.has(e),inTarget:r.has(e)})),a=[],o=i.filter(e=>e.inSource&&!e.inTarget).map(e=>`{${e.name}}`),s=i.filter(e=>!e.inSource&&e.inTarget).map(e=>`{${e.name}}`);o.length&&a.push(`${ba(o)} is missing, so its value never reaches the text`),s.length&&a.push(`${ba(s)} is not in the source, so it renders as literal text`);for(let[e,t]of r)t.size&&!t.has(`other`)&&a.push(`the block for {${e}} has no "other" case, so some counts render empty`);let c=ya(va(e)),l=ya(va(t));for(let[e,t]of c)(l.get(e)??0)<t&&a.push(`<${e}> is missing from the translation`);for(let[e,t]of l)(c.get(e)??0)<t&&a.push(`<${e}> is not in the source message`);return{params:i,problems:a}}var Sa=q(`<span> </span>`),Ca=q(`<span class="vmsg svelte-2clsr"> </span>`),wa=q(`<span class="tl edit svelte-2clsr"><span class="disc svelte-2clsr"> </span> <textarea class="tf svelte-2clsr" rows="2"></textarea></span> <span class="editbar svelte-2clsr"><!> <!> <!> <button class="btn sm svelte-2clsr"> </button> <button class="btn sm quiet svelte-2clsr">Cancel</button> <span class="keys svelte-2clsr">Enter saves · Esc closes</span></span>`,1),Ta=q(`<button class="tv svelte-2clsr"> </button>`),Ea=q(`<button class="tv none svelte-2clsr"> </button>`),Da=q(`<span class="sig svelte-2clsr"> </span>`),Oa=q(`<span class="tl svelte-2clsr"><span class="disc svelte-2clsr"> </span> <!> <!></span>`),ka=q(`<article><span class="tile svelte-2clsr"><!></span> <span class="row-t svelte-2clsr"><span class="src svelte-2clsr"> </span> <!></span></article>`);function Aa(e,t){Be(t,!0);let n=M(()=>t.row.cells.filter(e=>t.shown.includes(e.locale))),r=M(()=>[`broken`,`missing`,`draft`,`done`].find(e=>G(n).some(t=>t.state===e))??`done`),i=P(``),a=P(!1),o=P(null),s=M(()=>xa(t.row.source,G(i))),c=e=>`${e.locale} ${t.row.key}`;function l(e){F(i,e.text,!0),F(o,null),t.onEdit(c(e))}async function u(e){G(a)||(F(a,!0),F(o,await t.onSave(e.locale,t.row.key,G(i)),!0),F(a,!1),G(o)||t.onEdit(null))}function d(e,n){e.key===`Escape`&&t.onEdit(null),e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),u(n))}var f=ka();let p;var m=L(f);Xi(L(m),{get state(){return G(r)}}),k(m);var h=z(m,2),g=L(h),_=R(g,!0);Z(z(g,2),17,()=>G(n),e=>e.locale,(e,n)=>{var r=Cr(),f=en(r),p=e=>{var r=wa(),c=en(r),l=L(c),f=R(l,!0),p=z(l,2);$e(p),Qe(p,!0),k(c);var m=z(c,2),h=L(m);Z(h,17,()=>G(s).params,e=>e.name,(e,t)=>{var n=Sa();let r;var i=R(n);B(()=>{r=Jr(n,1,`pm svelte-2clsr`,null,r,{gone:G(t).inSource&&!G(t).inTarget}),Y(i,`${G(t).inSource&&!G(t).inTarget?`+`:``}{${G(t).name??``}}`)}),J(e,n)});var g=z(h,2);Z(g,16,()=>G(s).problems,e=>e,(e,t)=>{var n=Ca(),r=R(n,!0);B(()=>Y(r,t)),J(e,n)});var _=z(g,2),v=e=>{var t=Ca(),n=R(t,!0);B(()=>Y(n,G(o))),J(e,t)};X(_,e=>{G(o)&&!G(s).problems.length&&e(v)});var y=z(_,2),b=R(y,!0),x=z(y,2);Se(2),k(m),B(()=>{Q(l,`data-state`,G(n).state),Y(f,G(n).locale),Q(p,`aria-label`,`Translation for ${G(n).locale??``}`),y.disabled=G(a),Y(b,G(a)?`Saving`:`Save`)}),K(`keydown`,p,e=>d(e,G(n))),di(p,()=>G(i),e=>F(i,e)),K(`click`,y,()=>u(G(n))),K(`click`,x,()=>t.onEdit(null)),J(e,r)},m=M(()=>t.editing===c(G(n))),h=e=>{var t=Oa(),r=L(t),i=R(r,!0),a=z(r,2),o=e=>{var t=Ta(),r=R(t,!0);B(()=>{Q(t,`title`,G(n).text),Y(r,G(n).text)}),K(`click`,t,()=>l(G(n))),J(e,t)},s=e=>{var t=Ea(),r=R(t,!0);B(()=>Y(r,wi.missing.long)),K(`click`,t,()=>l(G(n))),J(e,t)};X(a,e=>{G(n).text?e(o):e(s,-1)}),Z(z(a,2),16,()=>G(n).signals,e=>e,(e,t)=>{var n=Da(),r=R(n,!0);B(()=>{Q(n,`title`,Ei[t]??t),Y(r,Ei[t]??t)}),J(e,n)}),k(t),B(()=>{Q(r,`data-state`,G(n).state),Y(i,G(n).locale)}),J(e,t)};X(f,e=>{G(m)?e(p):e(h,-1)}),J(e,r)}),k(h),k(f),B(e=>{p=Jr(f,1,`row svelte-2clsr`,null,p,{open:e}),Q(f,`data-worst`,G(r)),Q(f,`data-key`,t.row.key),Q(m,`data-state`,G(r)),Y(_,t.row.source)},[()=>G(n).some(e=>t.editing===c(e))]),J(e,f),Ve()}fr([`keydown`,`click`]);function ja(e,t=``,n={}){for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;typeof i==`string`?n[e]=i:i&&typeof i==`object`&&!Array.isArray(i)&&ja(i,e,n)}return n}function Ma(e){let t={};for(let n of e.locales)t[n]=ja(e.catalogs[n]??{});let n=new Map;for(let t of e.check.broken)t.severity===`error`&&n.set(`${t.locale}\u0000${t.key}`,t.issue);let r=new Map;for(let[t,n]of Object.entries(e.drafts))r.set(t,new Set(n));let i=t[e.sourceLocale]??{},a=e.locales.filter(t=>t!==e.sourceLocale),o=Object.keys(i).map(o=>({key:o,source:i[o]??``,origins:e.origins[o]??[],cells:a.map(i=>{let a=t[i]?.[o]??``,s=n.get(`${i}\u0000${o}`);return{locale:i,text:a,state:s?`broken`:a?r.get(i)?.has(o)?`draft`:`done`:`missing`,issue:s,signals:(e.triage?.[i]?.[o]??[]).map(e=>e.signal)}})}));return{root:e.root,scanning:e.scanning,sourceLocale:e.sourceLocale,locales:e.locales,rows:o,undefined:e.check.unknown??[],problems:e.problems}}function Na(e){return e.locales.map(t=>{let n=e.rows.length;if(t===e.sourceLocale)return{locale:t,source:!0,total:n,done:n,draft:0,missing:0,broken:0};let r={done:0,draft:0,missing:0,broken:0};for(let n of e.rows){let e=n.cells.find(e=>e.locale===t);e&&r[e.state]++}return{locale:t,source:!1,total:n,...r}})}function Pa(e,t){Object.assign(e,Ma(t))}function Fa(e,t,n){return e.rows.length?e.locales.length<2?`oneLocale`:t.length?n.length?null:`noMatch`:`pickOne`:`noCatalogs`}function Ia(e){let t=e.indexOf(`.`);return t>0?e.slice(0,t):null}function La(e,t){let n=new Set(t),r=new Map;for(let t of e){let e=Ia(t.key);if(e===null)continue;let i=r.get(e)??{name:e,total:0,broken:0,missing:0,draft:0};i.total+=1;for(let e of t.cells)n.has(e.locale)&&e.state!==`done`&&(i[e.state]+=1);r.set(e,i)}return[...r.values()].sort((e,t)=>e.name<t.name?-1:1)}function Ra(e,t){let n=t.text.trim().toLowerCase(),r=new Set(t.locales);return e.filter(e=>{let i=e.cells.filter(e=>r.has(e.locale));return t.state===`look`&&!i.some(e=>e.signals.length)||t.state!==`all`&&t.state!==`look`&&!i.some(e=>e.state===t.state)||t.group&&Ia(e.key)!==t.group?!1:!n||e.source.toLowerCase().includes(n)?!0:i.some(e=>e.text.toLowerCase().includes(n))})}var za=[`broken`,`missing`,`draft`,`done`];function Ba(e){for(let t of za)if(e.cells.some(e=>e.state===t))return t;return`done`}function Va(e,t,n=40){let r=t.trim().toLowerCase();if(!r)return[];let i=[];for(let t of e.rows){let a=[];t.source.toLowerCase().includes(r)&&a.push(e.sourceLocale);for(let e of t.cells)e.text.toLowerCase().includes(r)&&a.push(e.locale);if(!a.length)continue;let o=a[0],s=o===e.sourceLocale?t.source:t.cells.find(e=>e.locale===o)?.text??``;if(i.push({key:t.key,group:Ia(t.key),source:t.source,locales:a,text:s,state:Ba(t)}),i.length===n)break}return i}function Ha(e,t){let n=t.trim(),r=e.toLowerCase().indexOf(n.toLowerCase());return r<0?[e,``,``]:[e.slice(0,r),e.slice(r,r+n.length),e.slice(r+n.length)]}var Ua=q(`<div class="bill svelte-a18sfu"><p class="lede svelte-a18sfu"> </p> <p class="why svelte-a18sfu"> </p> <div class="pair svelte-a18sfu"><button class="go svelte-a18sfu"> </button> <button class="plain svelte-a18sfu"> </button></div></div>`),Wa=q(`<div class="bill svelte-a18sfu"><p class="lede svelte-a18sfu"> </p> <div class="track svelte-a18sfu"><span class="fill svelte-a18sfu"></span></div> <p class="why svelte-a18sfu"> </p></div>`),Ga=q(`<button class="act svelte-a18sfu"><span class="name svelte-a18sfu"> </span> <span class="why svelte-a18sfu"> </span></button> <button class="act svelte-a18sfu"><span class="name svelte-a18sfu"> </span> <span class="why svelte-a18sfu"> </span></button>`,1),Ka=q(`<p> </p>`),qa=q(`<section class="acts svelte-a18sfu" aria-label="Commands"><h2 class="cap svelte-a18sfu">Commands</h2> <!> <!></section>`);function Ja(e,t){Be(t,!0);let n=P(Wt({at:`idle`})),r=M(()=>G(n).at===`finding`||G(n).at===`planning`||G(n).at===`running`);function i(e,t=!1){F(n,{at:`said`,text:e,bad:t},!0)}async function a(){F(n,{at:`finding`},!0);let e=await t.api.extract();if(e.error||!e.value)return i(e.error??`no answer`,!0);let{found:r}=e.value;if(!r)return i($.nothingNew);let a=`${Ai(r)} your code uses and your catalogs did not have`;await t.onDone(a),i(a)}async function o(){F(n,{at:`planning`},!0);let e=await t.api.plan(t.shown);if(e.error||!e.value)return i(e.error??`no answer`,!0);if(!e.value.total)return i($.nothingMissing);F(n,{at:`plan`,plan:e.value},!0)}async function s(e){let r=await t.api.job(e);if(r.error||!r.value)return i(r.error??`no answer`,!0);let a=r.value;if(a.state===`running`){F(n,{at:`running`,job:a},!0);return}let o=`${Ai(a.done)} translated, unread until you read them`;await t.onDone(o),i(a.state===`failed`?a.message??`the run failed`:o,a.state===`failed`)}async function c(){let e=await t.api.translate(t.shown);if(e.error||!e.value)return i(e.error??`no answer`,!0);F(n,{at:`running`,job:e.value},!0)}gi(()=>{t.api.job().then(e=>{e.value&&G(n).at===`idle`&&F(n,{at:`running`,job:e.value},!0)})}),pn(()=>{if(G(n).at!==`running`)return;let e=G(n).job.id,t=setInterval(()=>void s(e),1e3);return()=>clearInterval(t)});let l=M(()=>t.targets?t.shown.length?$.translateWhy:$.pickFirst:$.onlyLocale),u=M(()=>G(n).at===`running`&&G(n).job.total?G(n).job.done/G(n).job.total:0);var d=qa(),f=z(L(d),2),p=e=>{var t=Ua(),r=L(t),i=R(r),a=z(r,2),o=R(a,!0),s=z(a,2),l=L(s),u=R(l,!0),d=z(l,2),f=R(d,!0);k(s),k(t),B((e,t)=>{Y(i,`${e??``} in ${t??``}`),Y(o,$.translateWhy),Y(u,$.translate),Y(f,$.cancel)},[()=>Ai(G(n).plan.total),()=>Object.keys(G(n).plan.pending).join(`, `)]),K(`click`,l,c),K(`click`,d,()=>F(n,{at:`idle`},!0)),J(e,t)},m=e=>{var t=Wa(),r=L(t),i=R(r),a=z(r,2),o=R(a),s=R(z(a,2));k(t),B(e=>{Y(i,`${$.running??``} ${G(n).job.locale??``??``}`),Xr(o,`width: ${e??``}%`),Y(s,`${G(n).job.done??``} of ${G(n).job.total??``}`)},[()=>Math.round(G(u)*100)]),J(e,t)},h=e=>{var i=Ga(),s=en(i),c=L(s),u=R(c,!0),d=R(z(c,2),!0);k(s);var f=z(s,2),p=L(f),m=R(p,!0),h=R(z(p,2),!0);k(f),B(()=>{s.disabled=G(r)||!t.scanning,Y(u,G(n).at===`finding`?$.working:$.find),Y(d,t.scanning?$.findWhy:$.scanOff),f.disabled=G(r)||!t.shown.length,Y(m,$.translate),Y(h,G(l))}),K(`click`,s,a),K(`click`,f,o),J(e,i)};X(f,e=>{G(n).at===`plan`?e(p):G(n).at===`running`?e(m,1):e(h,-1)});var g=z(f,2),_=e=>{var t=Ka();let r;var i=R(t,!0);B(()=>{r=Jr(t,1,`said svelte-a18sfu`,null,r,{bad:G(n).bad}),Y(i,G(n).text)}),J(e,t)};X(g,e=>{G(n).at===`said`&&e(_)}),k(d),J(e,d),Ve()}fr([`click`]);var Ya=q(`<h2 class="svelte-1qmtve8"> </h2>`),Xa=q(`<h2 class="svelte-1qmtve8"> </h2> <p class="svelte-1qmtve8"> </p>`,1),Za=q(`<code class="keys svelte-1qmtve8"> </code>`),Qa=q(`<button class="svelte-1qmtve8"> </button>`),$a=q(`<div class="job svelte-1qmtve8"><span class="tile svelte-1qmtve8"><!></span> <span class="what svelte-1qmtve8"><b class="svelte-1qmtve8"> </b> <span class="svelte-1qmtve8"> </span> <!></span> <!></div>`),eo=q(`<p class="empty svelte-1qmtve8">…</p>`),to=q(`<p class="empty svelte-1qmtve8"> </p>`),no=q(`<p class="commit svelte-1qmtve8"><code class="svelte-1qmtve8"> </code> <span class="svelte-1qmtve8"><b class="svelte-1qmtve8"> </b><span class="svelte-1qmtve8"> </span></span></p>`),ro=q(`<main class="overview svelte-1qmtve8"><header class="svelte-1qmtve8"><span class="chip svelte-1qmtve8"> </span> <!></header> <div class="cols svelte-1qmtve8"><section class="jobs svelte-1qmtve8" aria-label="What needs you"></section> <aside class="side svelte-1qmtve8"><div class="card svelte-1qmtve8"><button class="ring svelte-1qmtve8"><b class="svelte-1qmtve8"> </b> <strong class="svelte-1qmtve8"> </strong> <span class="svelte-1qmtve8"> </span></button> <p class="kv svelte-1qmtve8"><b class="svelte-1qmtve8"> </b><strong class="svelte-1qmtve8"> </strong></p> <p class="kv svelte-1qmtve8"><b class="svelte-1qmtve8"> </b><strong class="svelte-1qmtve8"> </strong></p></div> <div class="card svelte-1qmtve8"><p class="head svelte-1qmtve8"> </p> <!></div></aside></div></main>`);function io(e,t){Be(t,!0);let n=M(()=>t.health.filter(e=>!e.source)),r=M(()=>{let e=e=>G(n).reduce((t,n)=>t+e(n),0);return[{id:`broken`,n:e(e=>e.broken)},{id:`missing`,n:e(e=>e.missing)},{id:`draft`,n:e(e=>e.draft)},{id:`undefined`,n:t.undefinedKeys.length}].filter(e=>e.n>0)}),i=M(()=>G(r).reduce((e,t)=>e+t.n,0)),a=new Intl.RelativeTimeFormat(void 0,{numeric:`auto`});function o(e){let t=Math.round((Date.parse(e)-Date.now())/864e5);return t>-1?a.format(0,`day`):t>-31?a.format(t,`day`):a.format(Math.round(t/30),`month`)}var s=ro(),c=L(s),l=L(c),u=R(l,!0),d=z(l,2),f=e=>{var t=Ya(),n=R(t);B(()=>Y(n,`${G(i)??``} ${G(i)===1?`thing is`:`things are`} waiting for you.`)),J(e,t)},p=e=>{var t=Xa(),n=en(t),r=R(n,!0),i=R(z(n,2),!0);B(()=>{Y(r,Ni.clear),Y(i,Ni.clearWhy)}),J(e,t)};X(d,e=>{G(i)>0?e(f):e(p,-1)}),k(c);var m=z(c,2),h=L(m);Z(h,21,()=>G(r),e=>e.id,(e,n)=>{var r=$a(),i=L(r),a=L(i);{let e=M(()=>G(n).id===`undefined`?`broken`:G(n).id);Xi(a,{get state(){return G(e)}})}k(i);var o=z(i,2),s=L(o),c=R(s),l=z(s,2),u=R(l,!0),d=z(l,2),f=e=>{var n=Za(),r=R(n,!0);B(e=>Y(r,e),[()=>t.undefinedKeys.slice(0,3).map(e=>e.key).join(` · `)]),J(e,n)};X(d,e=>{G(n).id===`undefined`&&e(f)}),k(o);var p=z(o,2),m=e=>{var r=Qa(),i=R(r,!0);B(()=>Y(i,Ni.open)),K(`click`,r,()=>t.onFilter(G(n).id)),J(e,r)};X(p,e=>{G(n).id!==`undefined`&&e(m)}),k(r),B(()=>{Q(i,`data-state`,G(n).id===`undefined`?`broken`:G(n).id),Y(c,`${G(n).n??``} ${(G(n).n===1?ji[G(n).id].one:ji[G(n).id].many)??``}`),Y(u,Mi[G(n).id])}),J(e,r)}),k(h);var g=z(h,2),_=L(g),v=L(_),y=L(v),b=R(y,!0),x=z(y,2),S=R(x,!0),ee=R(z(x,2),!0);k(v);var te=z(v,2),C=L(te),ne=R(C,!0),re=R(z(C),!0);k(te);var ie=z(te,2),w=L(ie),ae=R(w,!0),oe=R(z(w),!0);k(ie),k(_);var se=z(_,2),ce=L(se),le=R(ce,!0),ue=z(ce,2),de=e=>{J(e,eo())},fe=e=>{var t=to(),n=R(t,!0);B(()=>Y(n,Ni.noHistory)),J(e,t)},pe=e=>{var n=Cr();Z(en(n),17,()=>t.commits,e=>e.sha,(e,t)=>{var n=no(),r=L(n),i=R(r,!0),a=z(r,2),s=L(a),c=R(s,!0),l=R(z(s));k(a),k(n),B(e=>{Y(i,G(t).sha),Y(c,G(t).subject),Y(l,`${G(t).author??``} · ${e??``}`)},[()=>o(G(t).date)]),J(e,n)}),J(e,n)};X(ue,e=>{t.commits===null?e(de):t.commits.length===0?e(fe,1):e(pe,-1)}),k(se),k(g),k(m),k(s),B(()=>{Y(u,Ni.here),v.disabled=!t.checks,Y(b,Ni.project),Y(S,t.checks&&t.checks.ok===t.checks.total?Ni.healthy:Ni.problems),Y(ee,t.checks?`${t.checks.ok} of ${t.checks.total} ${Ni.checks}`:`…`),Y(ne,Ni.countMessages),Y(re,t.total),Y(ae,Ni.countLocales),Y(oe,t.locales.length),Y(le,Ni.history)}),K(`click`,v,function(...e){t.onHealth?.apply(this,e)}),J(e,s),Ve()}fr([`click`]);var ao=q(`<p class="none svelte-1xn1b0j"> </p>`),oo=q(`<span class="group svelte-1xn1b0j"> </span>`),so=q(`<span class="src svelte-1xn1b0j"> </span>`),co=q(`<b class="disc svelte-1xn1b0j"> </b>`),lo=q(`<li><button><span class="tile svelte-1xn1b0j"><!></span> <span class="what svelte-1xn1b0j"><span class="found svelte-1xn1b0j"> <mark class="svelte-1xn1b0j"> </mark> </span> <!> <!></span> <span class="where svelte-1xn1b0j"></span></button></li>`),uo=q(`<ul class="svelte-1xn1b0j"></ul>`),fo=q(`<div class="sheet svelte-1xn1b0j" role="dialog"><p class="head svelte-1xn1b0j"><span> </span> <b class="svelte-1xn1b0j"> </b></p> <!> <p class="keys svelte-1xn1b0j"><kbd class="svelte-1xn1b0j">↑</kbd><kbd class="svelte-1xn1b0j">↓</kbd> <kbd class="svelte-1xn1b0j">enter</kbd> <kbd class="svelte-1xn1b0j">esc</kbd> <button class="close svelte-1xn1b0j"> </button></p></div>`);function po(e,t){Be(t,!0);let n=P(0);pn(()=>{t.query,F(n,0)});function r(e){t.hits.length&&F(n,(G(n)+e+t.hits.length)%t.hits.length)}function i(){let e=t.hits[G(n)];e&&t.onPick(e.key)}var a={move:r,choose:i},o=fo(),s=L(o),c=L(s),l=R(c,!0),u=R(z(c,2),!0);k(s);var d=z(s,2),f=e=>{var t=ao(),n=R(t,!0);B(()=>Y(n,Pi.none)),J(e,t)},p=e=>{var r=uo();Z(r,23,()=>t.hits,e=>e.key,(e,r,i)=>{let a=M(()=>Ha(G(r).text,t.query));var o=lo(),s=L(o);let c;var l=L(s);Xi(L(l),{get state(){return G(r).state}}),k(l);var u=z(l,2),d=L(u),f=L(d,!0),p=z(f),m=R(p,!0),h=z(p,1,!0);k(d);var g=z(d,2),_=e=>{var t=oo(),n=R(t,!0);B(()=>Y(n,G(r).group)),J(e,t)};X(g,e=>{G(r).group&&e(_)});var v=z(g,2),y=e=>{var t=so(),n=R(t,!0);B(()=>Y(n,G(r).source)),J(e,t)},b=M(()=>!G(r).locales.includes(t.sourceLocale));X(v,e=>{G(b)&&e(y)}),k(u);var x=z(u,2);Z(x,20,()=>G(r).locales,e=>e,(e,t)=>{var n=co(),r=R(n,!0);B(()=>Y(r,t)),J(e,n)}),k(x),k(s),k(o),B(()=>{c=Jr(s,1,`hit svelte-1xn1b0j`,null,c,{on:G(i)===G(n)}),Q(l,`data-state`,G(r).state),Y(f,G(a)[0]),Y(m,G(a)[1]),Y(h,G(a)[2])}),K(`click`,s,()=>t.onPick(G(r).key)),J(e,o)}),k(r),J(e,r)};X(d,e=>{t.hits.length===0?e(f):e(p,-1)});var m=z(d,2),h=z(L(m),2),g=z(h,2),_=z(g,2),v=z(_),y=R(v,!0);return k(m),k(o),B(e=>{Q(o,`aria-label`,Pi.label),Y(l,Pi.scope),Y(u,e),Y(h,`${Pi.moveKeys??``} `),Y(g,`${Pi.openKeys??``} `),Y(_,`${Pi.closeKeys??``} `),Y(y,Pi.close)},[()=>t.hits.length===1?Pi.oneHit:Pi.hits(t.hits.length)]),K(`click`,v,function(...e){t.onClose?.apply(this,e)}),J(e,o),Ve(a)}fr([`click`]);var mo=q(`<li><code> </code> </li>`),ho=q(`<ul class="problems svelte-1xn7ig5"></ul>`),go=q(`<p class="note svelte-1xn7ig5"> </p>`),_o=q(`<!> <!>`,1),vo=q(`<main class="table svelte-1xn7ig5"><!></main>`),yo=q(`Saved in <code> </code>`,1),bo=q(`<p class="snack svelte-1xn7ig5" role="status"><svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="svelte-1xn7ig5"><path d="m3.4 8.4 3 3 6.2-6.8"></path></svg> <!> <button class="svelte-1xn7ig5">Dismiss</button></p>`),xo=q(`<div class="shell svelte-1xn7ig5"><header class="bar svelte-1xn7ig5"><span class="brand svelte-1xn7ig5">verbaly <b class="svelte-1xn7ig5">studio</b></span> <input class="search svelte-1xn7ig5" type="search"/> <span class="root svelte-1xn7ig5"> </span></header> <!> <!> <div class="body svelte-1xn7ig5"><!> <!></div> <!></div>`);function So(e,t){Be(t,!0);let n=P(null),r=P(null),i=P(null),a=P(`overview`),o=P(null),s=P(null);function c(e){e===`health`?l():F(a,e,!0)}async function l(){F(a,`health`);let e=await t.api.health();if(e.error){F(r,{text:e.error,file:``},!0);return}e.value&&F(o,e.value,!0)}pn(()=>{t.api.health().then(e=>{e.value&&F(o,e.value,!0)}),t.api.history().then(e=>{F(s,e.value?.commits??[],!0)})});function u(e){F(g,G(v),!0),F(m,e,!0),F(a,`messages`)}async function d(e){let a=await t.api.state();if(a.error||!a.value){F(r,{text:a.error??`[verbaly] the server sent no state`,file:``},!0);return}F(n,null),F(i,null),Pa(t.panel,a.value),F(r,{text:e,file:``},!0);let s=await t.api.health();s.value&&F(o,s.value,!0)}async function f(e,n,a){let o=await t.api.setRead(e,n,a);if(o.error){F(r,{text:o.error,file:``},!0);return}let s=new Set(o.value?.keys??[]);for(let n of t.panel.rows){if(!s.has(n.key))continue;let t=n.cells.find(t=>t.locale===e);t?.text&&(t.state=a?`draft`:`done`)}F(i,a?null:{locale:e,keys:o.value?.keys??[]},!0)}async function p(e,n,i){let a=await t.api.save(e,n,i);if(a.error)return a.error;let o=t.panel.rows.find(e=>e.key===n)?.cells.find(t=>t.locale===e);return o&&(o.text=i,o.state=i?`done`:`missing`,o.issue=void 0),F(r,{text:i,file:`${e}.json`},!0),null}let m=P(`all`),h=P(``),g=P(null),_=P(null),v=M(()=>t.panel.locales.filter(e=>e!==t.panel.sourceLocale)),y=M(()=>G(g)??G(v).slice(0,1)),b=M(()=>Na(t.panel)),x=M(()=>Va(t.panel,G(h))),S=P(void 0),ee=P(void 0),te=P(null),C=M(()=>La(t.panel.rows,G(y))),ne=M(()=>Ra(t.panel.rows,{text:``,state:G(m),locales:G(y),group:G(_)})),re=M(()=>Fa(t.panel,G(y),G(ne))),ie=M(()=>{let e={all:0,look:0,missing:0,draft:0,broken:0};for(let n of[`all`,`look`,`missing`,`draft`,`broken`])e[n]=Ra(t.panel.rows,{text:``,state:n,locales:G(y),group:G(_)}).length;return e}),w=P(60);pn(()=>{G(m),G(y),G(_),F(w,60)});function ae(e){F(h,``),F(m,`all`),F(_,null),F(g,G(v),!0),F(a,`messages`),F(te,e,!0)}pn(()=>{if(!G(te))return;let e=G(te),t=G(ne).findIndex(t=>t.key===e);if(t<0){F(te,null);return}if(t+1>G(w)){F(w,t+1);return}F(te,null),tr().then(()=>{document.querySelector(`[data-key="${CSS.escape(e)}"]`)?.scrollIntoView({block:`center`})})});function oe(e){if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`){e.preventDefault(),G(ee)?.focus(),G(ee)?.select();return}G(h)&&(e.key===`Escape`?(F(h,``),G(ee)?.blur()):e.key===`ArrowDown`?(e.preventDefault(),G(S)?.move(1)):e.key===`ArrowUp`?(e.preventDefault(),G(S)?.move(-1)):e.key===`Enter`&&(e.preventDefault(),G(S)?.choose()))}function se(e){let t=e.currentTarget;t.scrollTop+t.clientHeight>t.scrollHeight-600&&G(w)<G(ne).length&&F(w,G(w)+60)}function ce(e){F(g,G(y).includes(e)?G(y).filter(t=>t!==e):[...G(y),e],!0)}var le=xo();dr(`keydown`,qt,oe);var ue=L(le),de=z(L(ue),2);oi(de),hi(de,e=>F(ee,e),()=>G(ee));var fe=z(de,2),pe=R(fe,!0);k(ue);var me=z(ue,2),T=e=>{var n=ho();Z(n,21,()=>t.panel.problems,e=>e.scope+e.message,(e,t)=>{var n=mo(),r=L(n),i=R(r,!0),a=z(r);k(n),B(()=>{Y(i,G(t).scope),Y(a,` ${G(t).message??``}`)}),J(e,n)}),k(n),J(e,n)};X(me,e=>{t.panel.problems.length&&e(T)});var he=z(me,2),ge=e=>{hi(po(e,{get query(){return G(h)},get hits(){return G(x)},get sourceLocale(){return t.panel.sourceLocale},onPick:ae,onClose:()=>F(h,``)}),e=>F(S,e,!0),()=>G(S))};X(he,e=>{G(h)&&e(ge)});var _e=z(he,2),ve=L(_e);{let e=e=>{Ja(e,{get api(){return t.api},get scanning(){return t.panel.scanning},get targets(){return G(v).length},get shown(){return G(y)},onDone:d})},n=M(()=>G(o)?{bad:G(o).entries.filter(e=>e.level!==`ok`).length}:null);Wi(ve,{get health(){return G(b)},get shown(){return G(y)},get state(){return G(m)},get counts(){return G(ie)},get pending(){return G(i)},get checks(){return G(n)},onToggle:ce,onState:e=>F(m,e,!0),onRead:e=>f(e,void 0,!1),onUndo:()=>G(i)&&f(G(i).locale,G(i).keys,!0),get view(){return G(a)},onView:c,get groups(){return G(C)},get group(){return G(_)},onGroup:e=>F(_,e,!0),actions:e,$$slots:{actions:!0}})}var ye=z(ve,2),E=e=>{{let n=M(()=>G(o)?{ok:G(o).entries.filter(e=>e.level===`ok`).length,total:G(o).entries.length}:null);io(e,{get health(){return G(b)},get undefinedKeys(){return t.panel.undefined},get locales(){return t.panel.locales},get total(){return t.panel.rows.length},get checks(){return G(n)},get commits(){return G(s)},onFilter:u,onHealth:l})}},be=e=>{{let t=M(()=>G(o)?.entries??[]),n=M(()=>G(o)?.ok??!0);Ci(e,{get entries(){return G(t)},get ok(){return G(n)},onClose:()=>F(a,`overview`)})}},D=e=>{var t=vo(),r=L(t),i=e=>{var t=go(),n=R(t);B(()=>Y(n,`${ki[G(re)]??``}${G(re)===`oneLocale`?` ${ki.oneLocaleFix}`:``}`)),J(e,t)},a=e=>{var t=_o(),r=en(t);Z(r,17,()=>G(ne).slice(0,G(w)),e=>e.key,(e,t)=>{Aa(e,{get row(){return G(t)},get shown(){return G(y)},get editing(){return G(n)},onEdit:e=>F(n,e,!0),onSave:p})});var i=z(r,2),a=e=>{var t=go(),n=R(t);B(()=>Y(n,`${G(ne).length-G(w)} more below`)),J(e,t)};X(i,e=>{G(w)<G(ne).length&&e(a)}),J(e,t)};X(r,e=>{G(re)?e(i):e(a,-1)}),k(t),dr(`scroll`,t,se),J(e,t)};X(ye,e=>{G(a)===`overview`?e(E):G(a)===`health`?e(be,1):e(D,-1)}),k(_e);var O=z(_e,2),xe=e=>{var t=bo(),n=z(L(t),2),i=e=>{var t=yo(),n=R(z(en(t)),!0);B(()=>Y(n,G(r).file)),J(e,t)},a=e=>{var t=Sr();B(()=>Y(t,G(r).text)),J(e,t)};X(n,e=>{G(r).file?e(i):e(a,-1)});var o=z(n,2);k(t),K(`click`,o,()=>F(r,null)),J(e,t)};X(O,e=>{G(r)&&e(xe)}),k(le),B(()=>{Q(de,`placeholder`,Pi.placeholder),Q(de,`aria-label`,Pi.placeholder),Q(fe,`title`,t.panel.root),Y(pe,t.panel.root)}),di(de,()=>G(h),e=>F(h,e)),J(e,le),Ve()}fr([`click`]);async function Co(e,t,n){let r=t.includes(`?`)?`&`:`?`,i;try{i=await fetch(`${t}${r}t=${encodeURIComponent(e)}`,{...n,headers:n?.body===void 0?void 0:{"content-type":`application/json`},body:n?.body===void 0?void 0:JSON.stringify(n.body)})}catch{return{error:`[verbaly] the studio server is not answering, is it still running?`}}let a=await i.json().catch(()=>({}));return i.ok?{value:a}:{error:a.error??`[verbaly] the server answered ${i.status}`}}function wo(e){return{state:()=>Co(e,`/api/state`),health:()=>Co(e,`/api/health`),history:()=>Co(e,`/api/history`),save:(t,n,r)=>Co(e,`/api/message/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,{method:`PUT`,body:{text:r}}),setRead:(t,n,r)=>Co(e,`/api/approve`,{method:`POST`,body:{locale:t,keys:n,undo:r}}),extract:()=>Co(e,`/api/extract`,{method:`POST`}),plan:t=>{let n=t.map(e=>`locale=${encodeURIComponent(e)}`).join(`&`);return Co(e,`/api/translate${n?`?${n}`:``}`)},translate:t=>Co(e,`/api/translate`,{method:`POST`,body:{locales:t}}),job:t=>Co(e,t?`/api/job/${encodeURIComponent(t)}`:`/api/job`)}}function To(e){return Wt(Ma(e))}var Eo=new URLSearchParams(location.search).get(`t`)??``;async function Do(){let e=document.getElementById(`app`),t=wo(Eo),n=await t.state();if(n.error||!n.value){e.textContent=n.error??`[verbaly] the server sent no state`;return}Or(So,{target:e,props:{panel:To(n.value),api:t}})}Do();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.health.svelte-1grjtup{background:var(--paper);flex:1;min-width:0;overflow-y:auto}header.svelte-1grjtup{border-bottom:1px solid var(--rule);padding:28px 24px 20px}h2.svelte-1grjtup{letter-spacing:-.014em;color:var(--ink);margin:0;font-size:21px;font-weight:500}header.svelte-1grjtup p:where(.svelte-1grjtup){max-width:64ch;color:var(--muted);margin:8px 0 0;font-size:13px}.close.svelte-1grjtup{border:1px solid var(--rule-strong);border-radius:var(--radius);background:var(--paper);color:var(--body);font:inherit;cursor:pointer;margin-top:16px;padding:5px 12px;font-size:12.5px}.close.svelte-1grjtup:hover{background:var(--ground)}ul.svelte-1grjtup{margin:0;padding:0;list-style:none}li.svelte-1grjtup{border-bottom:1px solid var(--rule);align-items:flex-start;gap:12px;padding:14px 24px;display:flex}.mark.svelte-1grjtup{background:var(--done-tint);width:20px;height:20px;color:var(--done);border-radius:50%;flex:none;justify-content:center;align-items:center;margin-top:1px;display:inline-flex}[data-level=warn].svelte-1grjtup .mark:where(.svelte-1grjtup){background:var(--missing-tint);color:var(--missing)}[data-level=error].svelte-1grjtup .mark:where(.svelte-1grjtup){background:var(--broken-tint);color:var(--broken)}.body.svelte-1grjtup{flex-direction:column;gap:2px;min-width:0;display:flex}b.svelte-1grjtup{color:var(--ink);font-size:13.5px;font-weight:500}.msg.svelte-1grjtup{color:var(--body);font-size:13px}.fix.svelte-1grjtup{font-family:var(--mono);color:var(--draft);margin-top:4px;font-size:12px}.sr.svelte-1grjtup{clip-path:inset(50%);width:1px;height:1px;position:absolute;overflow:hidden}.rail.svelte-l3e5c7{width:var(--rail);border-right:1px solid var(--rule);background:var(--ground);flex:none;padding:18px 14px;overflow-y:auto}.views.svelte-l3e5c7{margin:0 0 18px;padding:0;list-style:none}.nav.svelte-l3e5c7{border-radius:var(--radius);width:100%;font:inherit;color:var(--body);cursor:pointer;text-align:left;background:0 0;border:0;align-items:center;gap:8px;padding:7px 8px;font-size:13px;display:flex}.nav.svelte-l3e5c7:hover{background:var(--hollow)}.nav.on.svelte-l3e5c7{background:var(--done-tint);color:var(--done);box-shadow:inset 2px 0 0 var(--done);font-weight:500}.bad.svelte-l3e5c7{background:var(--broken-tint);color:var(--broken);font-family:var(--mono);border-radius:999px;margin-left:auto;padding:0 7px;font-size:11px}.bad.clean.svelte-l3e5c7{background:var(--done-tint);color:var(--done)}.groups.svelte-l3e5c7{border:1px solid var(--rule);border-radius:var(--radius);background:var(--paper);width:100%;color:var(--body);font:inherit;margin-bottom:18px;padding:7px 8px;font-size:13px}.cap.svelte-l3e5c7{letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 8px;padding:0 6px;font-size:11px;font-weight:600}ul.svelte-l3e5c7{margin:0 0 22px;padding:0;list-style:none}.lang.svelte-l3e5c7{border-radius:var(--radius);cursor:pointer;align-items:flex-start;gap:10px;padding:7px 6px;display:flex}.lang.svelte-l3e5c7:hover{background:var(--hollow)}.lang.source.svelte-l3e5c7{cursor:default}.lang.svelte-l3e5c7 input:where(.svelte-l3e5c7){accent-color:var(--done);margin:4px 0 0}.meta.svelte-l3e5c7{flex-direction:column;min-width:0;display:flex}.name.svelte-l3e5c7{font-family:var(--mono);color:var(--ink);font-size:13px;font-weight:600}.state.svelte-l3e5c7{color:var(--muted);font-size:11.5px}.state[data-state=broken].svelte-l3e5c7{color:var(--broken)}.state[data-state=missing].svelte-l3e5c7{color:var(--missing)}.state[data-state=draft].svelte-l3e5c7{color:var(--draft)}.read.svelte-l3e5c7{border:1px solid var(--draft);background:var(--draft-tint);color:var(--draft);font:inherit;cursor:pointer;border-radius:999px;align-items:center;gap:6px;margin:2px 0 6px 30px;padding:3px 9px;font-size:11.5px;display:flex}.read.svelte-l3e5c7 .n:where(.svelte-l3e5c7){font-family:var(--mono);opacity:.8}.undo.svelte-l3e5c7{border-radius:var(--radius);background:var(--hollow);color:var(--body);align-items:center;gap:8px;margin:-14px 0 22px;padding:8px 10px;font-size:11.5px;display:flex}.undo.svelte-l3e5c7 button:where(.svelte-l3e5c7){border:1px solid var(--rule-strong);border-radius:var(--radius);background:var(--paper);color:var(--ink);font:inherit;cursor:pointer;margin-left:auto;padding:3px 10px;font-size:11.5px}.filters.svelte-l3e5c7 button:where(.svelte-l3e5c7){border-radius:var(--radius);width:100%;font:inherit;color:var(--body);cursor:pointer;text-align:left;background:0 0;border:0;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.filters.svelte-l3e5c7 button:where(.svelte-l3e5c7):hover{background:var(--hollow)}.filters.svelte-l3e5c7 button.on:where(.svelte-l3e5c7){background:var(--hollow);color:var(--ink);font-weight:600}.count.svelte-l3e5c7{font-family:var(--mono);color:var(--muted);font-size:12px}.sr.svelte-1fu82r1{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.row.svelte-2clsr{border-bottom:1px solid var(--rule);align-items:flex-start;gap:16px;min-height:64px;padding:12px 20px;display:flex}.row.svelte-2clsr:hover{background:var(--ground)}.row.open.svelte-2clsr{background:var(--paper);box-shadow:inset 3px 0 0 var(--done);outline:1px solid var(--rule);outline-offset:-1px}.tile.svelte-2clsr{border-radius:var(--radius);flex:none;justify-content:center;align-items:center;width:26px;height:26px;margin-top:2px;display:inline-flex}.tile[data-state=done].svelte-2clsr{color:var(--rule-strong)}.tile[data-state=draft].svelte-2clsr{background:var(--draft-tint);color:var(--draft)}.tile[data-state=missing].svelte-2clsr{background:var(--missing-tint);color:var(--missing)}.tile[data-state=broken].svelte-2clsr{background:var(--broken);color:var(--paper)}.row-t.svelte-2clsr{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.src.svelte-2clsr{color:var(--muted);text-overflow:ellipsis;white-space:nowrap;font-size:13.5px;line-height:1.3;overflow:hidden}.tl.svelte-2clsr{align-items:baseline;gap:8px;min-width:0;display:flex}.tl.edit.svelte-2clsr{align-items:flex-start}.disc.svelte-2clsr{background:var(--hollow);width:20px;height:20px;color:var(--body);font-family:var(--mono);letter-spacing:-.02em;border-radius:50%;flex:none;justify-content:center;align-items:center;font-size:9px;display:inline-flex;transform:translateY(3px)}.disc[data-state=done].svelte-2clsr{background:var(--done-tint);color:var(--done)}.disc[data-state=draft].svelte-2clsr{background:var(--draft-tint);color:var(--draft)}.disc[data-state=missing].svelte-2clsr{background:var(--missing-tint);color:var(--missing)}.disc[data-state=broken].svelte-2clsr{background:var(--broken-tint);color:var(--broken)}.tv.svelte-2clsr{text-align:left;min-width:0;font-family:var(--serif);color:var(--ink);text-overflow:ellipsis;white-space:nowrap;cursor:text;background:0 0;border:0;flex:1;padding:0;font-size:17px;line-height:1.35;overflow:hidden}.sig.svelte-2clsr{color:var(--draft);background:var(--draft-tint);white-space:nowrap;border-radius:4px;flex:none;padding:1px 6px;font-size:11px}.tv.none.svelte-2clsr{font-family:var(--sans);color:var(--missing);font-size:13px;font-style:italic}.tf.svelte-2clsr{min-width:0;font-family:var(--serif);color:var(--ink);background:var(--paper);border:1px solid var(--done);border-radius:var(--radius);resize:vertical;flex:1;padding:6px 10px;font-size:17px;line-height:1.45}.tf.svelte-2clsr:focus-visible{outline:2px solid color-mix(in oklab, var(--done) 26%, transparent);outline-offset:1px}.editbar.svelte-2clsr{flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px;display:flex}.pm.svelte-2clsr{font-family:var(--mono);color:var(--body);background:var(--hollow);border-radius:4px;padding:1px 5px;font-size:12.5px}.pm.gone.svelte-2clsr{background:var(--broken-tint);border:1px dashed var(--broken);color:var(--broken)}.vmsg.svelte-2clsr{color:var(--broken);background:var(--broken-tint);border-radius:var(--radius);align-items:center;gap:6px;padding:4px 9px;font-size:12.5px;display:inline-flex}.btn.svelte-2clsr{border:1px solid var(--done);border-radius:var(--radius);background:var(--done);height:30px;color:var(--paper);font:inherit;cursor:pointer;padding:0 12px;font-size:12.5px;font-weight:500}.btn.quiet.svelte-2clsr{background:var(--paper);color:var(--body);border-color:var(--rule-strong);font-weight:400}.btn.svelte-2clsr:disabled{opacity:.6;cursor:default}.keys.svelte-2clsr{font-family:var(--mono);color:var(--muted);font-size:11px}.acts.svelte-a18sfu{margin-bottom:22px}.cap.svelte-a18sfu{letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 8px;padding:0 6px;font-size:11px;font-weight:600}.act.svelte-a18sfu{border-radius:var(--radius);width:100%;font:inherit;color:var(--body);cursor:pointer;text-align:left;background:0 0;border:0;flex-direction:column;gap:1px;margin-bottom:4px;padding:7px 8px;display:flex}.act.svelte-a18sfu:hover:not(:disabled){background:var(--hollow)}.act.svelte-a18sfu:disabled{cursor:default}.act.svelte-a18sfu:disabled .name:where(.svelte-a18sfu){opacity:.55}.name.svelte-a18sfu{color:var(--ink);font-size:13px}.why.svelte-a18sfu{color:var(--muted);margin:0;font-size:11.5px;line-height:1.35}.bill.svelte-a18sfu{border:1px solid var(--rule);border-radius:var(--radius);background:var(--paper);padding:10px}.lede.svelte-a18sfu{color:var(--ink);margin:0 0 4px;font-size:13px}.pair.svelte-a18sfu{gap:6px;margin-top:10px;display:flex}.go.svelte-a18sfu{border-radius:var(--radius);background:var(--done);color:var(--paper);font:inherit;cursor:pointer;border:0;flex:1;padding:5px 10px;font-size:12px}.plain.svelte-a18sfu{border:1px solid var(--rule-strong);border-radius:var(--radius);color:var(--body);font:inherit;cursor:pointer;background:0 0;padding:5px 10px;font-size:12px}.track.svelte-a18sfu{background:var(--hollow);border-radius:999px;height:4px;margin:8px 0 6px;overflow:hidden}.fill.svelte-a18sfu{background:var(--done);height:100%;transition:width .3s linear;display:block}.said.svelte-a18sfu{color:var(--muted);margin:6px 0 0;padding:0 8px;font-size:11.5px}.said.bad.svelte-a18sfu{color:var(--broken)}.overview.svelte-1qmtve8{background:var(--ground);flex:1;min-width:0;overflow-y:auto}header.svelte-1qmtve8{padding:28px 24px 20px}.chip.svelte-1qmtve8{background:var(--done-tint);color:var(--done);border-radius:999px;padding:3px 12px;font-size:12px;font-weight:500;display:inline-block}h2.svelte-1qmtve8{letter-spacing:-.024em;max-width:24ch;color:var(--ink);margin:14px 0 0;font-size:30px;font-weight:500;line-height:1.16}header.svelte-1qmtve8 p:where(.svelte-1qmtve8){color:var(--muted);margin:10px 0 0;font-size:14px}.cols.svelte-1qmtve8{grid-template-columns:minmax(0,1fr) 320px;align-items:start;gap:20px;padding:0 24px 28px;display:grid}.card.svelte-1qmtve8,.jobs.svelte-1qmtve8{background:var(--paper);border:1px solid var(--rule);border-radius:14px;overflow:hidden}.side.svelte-1qmtve8{flex-direction:column;gap:16px;min-width:0;display:flex}.job.svelte-1qmtve8{border-top:1px solid var(--rule);align-items:center;gap:16px;padding:16px 20px;display:flex}.job.svelte-1qmtve8:first-child{border-top:0}.tile.svelte-1qmtve8{border-radius:var(--radius);flex:none;justify-content:center;align-items:center;width:26px;height:26px;display:inline-flex}.tile[data-state=broken].svelte-1qmtve8{background:var(--broken);color:var(--paper)}.tile[data-state=missing].svelte-1qmtve8{background:var(--missing-tint);color:var(--missing)}.tile[data-state=draft].svelte-1qmtve8{background:var(--draft-tint);color:var(--draft)}.what.svelte-1qmtve8{flex:1;min-width:0}.what.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--ink);font-size:15px;font-weight:500;display:block}.what.svelte-1qmtve8>span:where(.svelte-1qmtve8){color:var(--muted);font-size:13px;display:block}.keys.svelte-1qmtve8{font-family:var(--mono);color:var(--muted);text-overflow:ellipsis;white-space:nowrap;margin-top:4px;font-size:11px;display:block;overflow:hidden}button.svelte-1qmtve8{border:1px solid var(--rule-strong);border-radius:var(--radius);background:var(--paper);height:32px;color:var(--body);cursor:pointer;flex:none;padding:0 14px;font-family:inherit;font-size:13px}button.svelte-1qmtve8:hover{background:var(--ground)}.ring.svelte-1qmtve8{text-align:left;border:0;border-radius:0;width:100%;height:auto;padding:18px 20px;display:block}.ring.svelte-1qmtve8:disabled{cursor:default}.ring.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--muted);font-size:12px;font-weight:400;display:block}.ring.svelte-1qmtve8 strong:where(.svelte-1qmtve8){color:var(--ink);margin-top:2px;font-size:17px;font-weight:500;display:block}.ring.svelte-1qmtve8 span:where(.svelte-1qmtve8){color:var(--muted);margin-top:4px;font-size:12px;display:block}.kv.svelte-1qmtve8{border-top:1px solid var(--rule);align-items:center;gap:12px;height:44px;margin:0;padding:0 20px;display:flex}.kv.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--body);flex:1;font-size:13px;font-weight:400}.kv.svelte-1qmtve8 strong:where(.svelte-1qmtve8){color:var(--ink);font-variant-numeric:tabular-nums;font-size:15px;font-weight:500}.head.svelte-1qmtve8{border-bottom:1px solid var(--rule);color:var(--ink);margin:0;padding:16px 20px;font-size:15px;font-weight:500}.empty.svelte-1qmtve8{color:var(--muted);margin:0;padding:16px 20px;font-size:13px}.commit.svelte-1qmtve8{align-items:flex-start;gap:12px;margin:0;padding:10px 20px;display:flex}.commit.svelte-1qmtve8 code:where(.svelte-1qmtve8){font-family:var(--mono);color:var(--muted);flex:none;margin-top:2px;font-size:11px}.commit.svelte-1qmtve8>span:where(.svelte-1qmtve8){flex:1;min-width:0}.commit.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--body);font-size:12px;font-weight:400;line-height:1.45;display:block}.commit.svelte-1qmtve8 span:where(.svelte-1qmtve8) span:where(.svelte-1qmtve8){color:var(--muted);margin-top:2px;font-size:11px;display:block}@media (max-width:900px){.cols.svelte-1qmtve8{grid-template-columns:minmax(0,1fr)}}.sheet.svelte-1xn1b0j{z-index:6;background:var(--paper);border:1px solid var(--rule);border-radius:0 0 14px 14px;flex-direction:column;width:660px;max-width:calc(100% - 32px);max-height:70%;display:flex;position:absolute;top:46px;left:50%;overflow:hidden;transform:translate(-50%);box-shadow:0 24px 60px -24px #00000073}.head.svelte-1xn1b0j{border-bottom:1px solid var(--rule);color:var(--muted);align-items:center;gap:12px;margin:0;padding:10px 18px;font-size:12px;display:flex}.head.svelte-1xn1b0j b:where(.svelte-1xn1b0j){background:var(--draft-tint);color:var(--draft);white-space:nowrap;border-radius:999px;margin-left:auto;padding:2px 9px;font-weight:500}.none.svelte-1xn1b0j{color:var(--muted);margin:0;padding:18px;font-size:13px}ul.svelte-1xn1b0j{margin:0;padding:0;list-style:none;overflow-y:auto}.hit.svelte-1xn1b0j{border:0;border-bottom:1px solid var(--rule);width:100%;font:inherit;text-align:left;cursor:pointer;background:0 0;align-items:center;gap:12px;padding:10px 18px;display:flex}.hit.svelte-1xn1b0j:hover,.hit.on.svelte-1xn1b0j{background:var(--ground)}.hit.on.svelte-1xn1b0j{box-shadow:inset 3px 0 0 var(--done)}.tile.svelte-1xn1b0j{border-radius:var(--radius);flex:none;justify-content:center;align-items:center;width:22px;height:22px;display:inline-flex}.tile[data-state=done].svelte-1xn1b0j{color:var(--rule-strong)}.tile[data-state=broken].svelte-1xn1b0j{background:var(--broken);color:var(--paper)}.tile[data-state=missing].svelte-1xn1b0j{background:var(--missing-tint);color:var(--missing)}.tile[data-state=draft].svelte-1xn1b0j{background:var(--draft-tint);color:var(--draft)}.what.svelte-1xn1b0j{flex:1;min-width:0}.found.svelte-1xn1b0j{font-family:var(--serif);color:var(--ink);text-overflow:ellipsis;white-space:nowrap;font-size:15px;display:block;overflow:hidden}mark.svelte-1xn1b0j{background:var(--draft-tint);color:inherit;border-radius:3px;padding:0 2px}.group.svelte-1xn1b0j{background:var(--hollow);color:var(--muted);font-family:var(--mono);border-radius:999px;margin-right:6px;padding:0 6px;font-size:10px;display:inline-block}.src.svelte-1xn1b0j{color:var(--muted);text-overflow:ellipsis;white-space:nowrap;font-size:12px;display:block;overflow:hidden}.where.svelte-1xn1b0j{flex:none;gap:4px;display:flex}.disc.svelte-1xn1b0j{background:var(--hollow);width:20px;height:20px;color:var(--body);font-family:var(--mono);text-transform:uppercase;border-radius:50%;justify-content:center;align-items:center;font-size:9px;font-weight:400;display:inline-flex}.keys.svelte-1xn1b0j{border-top:1px solid var(--rule);color:var(--muted);align-items:center;gap:6px;margin:0;padding:8px 18px;font-size:11px;display:flex}kbd.svelte-1xn1b0j{font-family:var(--mono);border:1px solid var(--rule);border-radius:3px;padding:0 4px;font-size:10px}.close.svelte-1xn1b0j{font:inherit;color:var(--muted);cursor:pointer;background:0 0;border:0;margin-left:auto;font-size:11px;text-decoration:underline}.shell.svelte-1xn7ig5{flex-direction:column;height:100%;display:flex;position:relative}.bar.svelte-1xn7ig5{background:var(--bar);height:48px;color:var(--on-bar);flex:none;align-items:center;gap:16px;padding:0 16px;display:flex;box-shadow:inset 0 -1px #ffffff1f}.brand.svelte-1xn7ig5{letter-spacing:.02em;opacity:.75;white-space:nowrap;font-size:13px}.brand.svelte-1xn7ig5 b:where(.svelte-1xn7ig5){opacity:1;font-weight:600}.search.svelte-1xn7ig5{border-radius:var(--radius);max-width:520px;color:var(--on-bar);font:inherit;background:#ffffff0f;border:1px solid #ffffff29;flex:1;padding:6px 12px;font-size:13px}.search.svelte-1xn7ig5::placeholder{color:#ffffff73}.search.svelte-1xn7ig5:focus-visible{outline:2px solid var(--done);outline-offset:1px}.root.svelte-1xn7ig5{font-family:var(--mono);opacity:.55;text-overflow:ellipsis;white-space:nowrap;max-width:30ch;margin-left:auto;font-size:11.5px;overflow:hidden}.problems.svelte-1xn7ig5{background:var(--broken-tint);color:var(--broken);border-bottom:1px solid var(--rule);margin:0;padding:8px 16px;font-size:12.5px;list-style:none}.body.svelte-1xn7ig5{flex:1;min-height:0;display:flex}.table.svelte-1xn7ig5{background:var(--paper);flex:1;min-width:0;overflow-y:auto}.note.svelte-1xn7ig5{color:var(--muted);margin:0;padding:24px 20px;font-size:13px}.snack.svelte-1xn7ig5{background:var(--bar);height:44px;color:var(--on-bar);border-radius:var(--radius);white-space:nowrap;align-items:center;gap:12px;margin:0;padding:0 12px 0 20px;font-size:13px;display:flex;position:absolute;bottom:24px;left:50%;transform:translate(-50%);box-shadow:0 2px 6px #0610052e,0 34px 64px -28px #06100566}.snack.svelte-1xn7ig5 svg:where(.svelte-1xn7ig5){color:#8ed67f}.snack.svelte-1xn7ig5 button:where(.svelte-1xn7ig5){height:30px;color:inherit;font:inherit;cursor:pointer;background:#ffffff24;border:0;border-radius:4px;padding:0 12px;font-size:12.5px}.verbaly-studio{--paper:#f8fbf7;--ground:#eff4ee;--hollow:#e5ede4;--rule:#d7dfd5;--rule-strong:#828d80;--muted:#636c61;--body:#374036;--ink:#061005;--bar:#131e12;--on-bar:#f8fbf7;--broken:#b43931;--broken-tint:#eee0db;--missing:#8e5a04;--missing-tint:#e9e4d5;--draft:#2267ad;--draft-tint:#dae6ed;--done:#2e7428;--done-tint:#dce8da;--sans:"Schibsted Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--serif:"Newsreader", ui-serif, Georgia, "Times New Roman", serif;--mono:"JetBrains Mono", ui-monospace, "Cascadia Code", "SF Mono", monospace;--rail:232px;--radius:6px}@media (prefers-color-scheme:dark){.verbaly-studio:not([data-theme=light]){--paper:#10170f;--ground:#161e15;--hollow:#1d271c;--rule:#2a352a;--rule-strong:#6f7a6d;--muted:#9aa598;--body:#d3dbd1;--ink:#f2f7f1;--broken:#f08a82;--broken-tint:#3a211f;--missing:#dcae4e;--missing-tint:#352c16;--draft:#7db6e8;--draft-tint:#172a3a;--done:#79c46f;--done-tint:#182c16}}.verbaly-studio[data-theme=dark]{--paper:#10170f;--ground:#161e15;--hollow:#1d271c;--rule:#2a352a;--rule-strong:#6f7a6d;--muted:#9aa598;--body:#d3dbd1;--ink:#f2f7f1;--broken:#f08a82;--broken-tint:#3a211f;--missing:#dcae4e;--missing-tint:#352c16;--draft:#7db6e8;--draft-tint:#172a3a;--done:#79c46f;--done-tint:#182c16}.verbaly-studio,.verbaly-studio *,.verbaly-studio :before,.verbaly-studio :after{box-sizing:border-box}.verbaly-studio{background:var(--ground);color:var(--body);font-family:var(--sans);-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5}.verbaly-studio code,.verbaly-studio kbd{font-family:var(--mono);font-size:.92em}@media (prefers-reduced-motion:reduce){.verbaly-studio,.verbaly-studio *,.verbaly-studio :before,.verbaly-studio :after{transition-duration:.01ms!important;animation-duration:.01ms!important}}html,body{height:100%}body{background:var(--ground);margin:0}#app{height:100%}
|
package/dist/ui/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>Verbaly Studio</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-BWCfMFep.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BYjBNask.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="app"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verbaly/studio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
4
4
|
"description": "Local review server for Verbaly: read, edit and approve translations over the JSON files already in your repo. No account, no database.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@verbaly/compiler": "^0.
|
|
46
|
+
"@verbaly/compiler": "^0.61.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"svelte": "^5.57.0",
|
|
52
52
|
"svelte-check": "^4.7.6",
|
|
53
53
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
54
|
-
"verbaly": "^0.
|
|
54
|
+
"verbaly": "^0.61.0",
|
|
55
55
|
"vite": "^8.3.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.health.svelte-1grjtup{background:var(--paper);flex:1;min-width:0;overflow-y:auto}header.svelte-1grjtup{border-bottom:1px solid var(--rule);padding:28px 24px 20px}h2.svelte-1grjtup{letter-spacing:-.014em;color:var(--ink);margin:0;font-size:21px;font-weight:500}header.svelte-1grjtup p:where(.svelte-1grjtup){max-width:64ch;color:var(--muted);margin:8px 0 0;font-size:13px}.close.svelte-1grjtup{border:1px solid var(--rule-strong);border-radius:var(--radius);background:var(--paper);color:var(--body);font:inherit;cursor:pointer;margin-top:16px;padding:5px 12px;font-size:12.5px}.close.svelte-1grjtup:hover{background:var(--ground)}ul.svelte-1grjtup{margin:0;padding:0;list-style:none}li.svelte-1grjtup{border-bottom:1px solid var(--rule);align-items:flex-start;gap:12px;padding:14px 24px;display:flex}.mark.svelte-1grjtup{background:var(--done-tint);width:20px;height:20px;color:var(--done);border-radius:50%;flex:none;justify-content:center;align-items:center;margin-top:1px;display:inline-flex}[data-level=warn].svelte-1grjtup .mark:where(.svelte-1grjtup){background:var(--missing-tint);color:var(--missing)}[data-level=error].svelte-1grjtup .mark:where(.svelte-1grjtup){background:var(--broken-tint);color:var(--broken)}.body.svelte-1grjtup{flex-direction:column;gap:2px;min-width:0;display:flex}b.svelte-1grjtup{color:var(--ink);font-size:13.5px;font-weight:500}.msg.svelte-1grjtup{color:var(--body);font-size:13px}.fix.svelte-1grjtup{font-family:var(--mono);color:var(--draft);margin-top:4px;font-size:12px}.sr.svelte-1grjtup{clip-path:inset(50%);width:1px;height:1px;position:absolute;overflow:hidden}.rail.svelte-l3e5c7{width:var(--rail);border-right:1px solid var(--rule);background:var(--ground);flex:none;padding:18px 14px;overflow-y:auto}.views.svelte-l3e5c7{margin:0 0 18px;padding:0;list-style:none}.nav.svelte-l3e5c7{border-radius:var(--radius);width:100%;font:inherit;color:var(--body);cursor:pointer;text-align:left;background:0 0;border:0;align-items:center;gap:8px;padding:7px 8px;font-size:13px;display:flex}.nav.svelte-l3e5c7:hover{background:var(--hollow)}.nav.on.svelte-l3e5c7{background:var(--done-tint);color:var(--done);box-shadow:inset 2px 0 0 var(--done);font-weight:500}.bad.svelte-l3e5c7{background:var(--broken-tint);color:var(--broken);font-family:var(--mono);border-radius:999px;margin-left:auto;padding:0 7px;font-size:11px}.bad.clean.svelte-l3e5c7{background:var(--done-tint);color:var(--done)}.cap.svelte-l3e5c7{letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 8px;padding:0 6px;font-size:11px;font-weight:600}ul.svelte-l3e5c7{margin:0 0 22px;padding:0;list-style:none}.lang.svelte-l3e5c7{border-radius:var(--radius);cursor:pointer;align-items:flex-start;gap:10px;padding:7px 6px;display:flex}.lang.svelte-l3e5c7:hover{background:var(--hollow)}.lang.source.svelte-l3e5c7{cursor:default}.lang.svelte-l3e5c7 input:where(.svelte-l3e5c7){accent-color:var(--done);margin:4px 0 0}.meta.svelte-l3e5c7{flex-direction:column;min-width:0;display:flex}.name.svelte-l3e5c7{font-family:var(--mono);color:var(--ink);font-size:13px;font-weight:600}.state.svelte-l3e5c7{color:var(--muted);font-size:11.5px}.state[data-state=broken].svelte-l3e5c7{color:var(--broken)}.state[data-state=missing].svelte-l3e5c7{color:var(--missing)}.state[data-state=draft].svelte-l3e5c7{color:var(--draft)}.read.svelte-l3e5c7{border:1px solid var(--draft);background:var(--draft-tint);color:var(--draft);font:inherit;cursor:pointer;border-radius:999px;align-items:center;gap:6px;margin:2px 0 6px 30px;padding:3px 9px;font-size:11.5px;display:flex}.read.svelte-l3e5c7 .n:where(.svelte-l3e5c7){font-family:var(--mono);opacity:.8}.undo.svelte-l3e5c7{border-radius:var(--radius);background:var(--hollow);color:var(--body);align-items:center;gap:8px;margin:-14px 0 22px;padding:8px 10px;font-size:11.5px;display:flex}.undo.svelte-l3e5c7 button:where(.svelte-l3e5c7){border:1px solid var(--rule-strong);border-radius:var(--radius);background:var(--paper);color:var(--ink);font:inherit;cursor:pointer;margin-left:auto;padding:3px 10px;font-size:11.5px}.filters.svelte-l3e5c7 button:where(.svelte-l3e5c7){border-radius:var(--radius);width:100%;font:inherit;color:var(--body);cursor:pointer;text-align:left;background:0 0;border:0;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.filters.svelte-l3e5c7 button:where(.svelte-l3e5c7):hover{background:var(--hollow)}.filters.svelte-l3e5c7 button.on:where(.svelte-l3e5c7){background:var(--hollow);color:var(--ink);font-weight:600}.count.svelte-l3e5c7{font-family:var(--mono);color:var(--muted);font-size:12px}.sr.svelte-1fu82r1{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.row.svelte-2clsr{border-bottom:1px solid var(--rule);align-items:flex-start;gap:16px;min-height:64px;padding:12px 20px;display:flex}.row.svelte-2clsr:hover{background:var(--ground)}.row.open.svelte-2clsr{background:var(--paper);box-shadow:inset 3px 0 0 var(--done);outline:1px solid var(--rule);outline-offset:-1px}.tile.svelte-2clsr{border-radius:var(--radius);flex:none;justify-content:center;align-items:center;width:26px;height:26px;margin-top:2px;display:inline-flex}.tile[data-state=done].svelte-2clsr{color:var(--rule-strong)}.tile[data-state=draft].svelte-2clsr{background:var(--draft-tint);color:var(--draft)}.tile[data-state=missing].svelte-2clsr{background:var(--missing-tint);color:var(--missing)}.tile[data-state=broken].svelte-2clsr{background:var(--broken);color:var(--paper)}.row-t.svelte-2clsr{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.src.svelte-2clsr{color:var(--muted);text-overflow:ellipsis;white-space:nowrap;font-size:13.5px;line-height:1.3;overflow:hidden}.tl.svelte-2clsr{align-items:baseline;gap:8px;min-width:0;display:flex}.tl.edit.svelte-2clsr{align-items:flex-start}.disc.svelte-2clsr{background:var(--hollow);width:20px;height:20px;color:var(--body);font-family:var(--mono);letter-spacing:-.02em;border-radius:50%;flex:none;justify-content:center;align-items:center;font-size:9px;display:inline-flex;transform:translateY(3px)}.disc[data-state=done].svelte-2clsr{background:var(--done-tint);color:var(--done)}.disc[data-state=draft].svelte-2clsr{background:var(--draft-tint);color:var(--draft)}.disc[data-state=missing].svelte-2clsr{background:var(--missing-tint);color:var(--missing)}.disc[data-state=broken].svelte-2clsr{background:var(--broken-tint);color:var(--broken)}.tv.svelte-2clsr{text-align:left;min-width:0;font-family:var(--serif);color:var(--ink);text-overflow:ellipsis;white-space:nowrap;cursor:text;background:0 0;border:0;flex:1;padding:0;font-size:17px;line-height:1.35;overflow:hidden}.sig.svelte-2clsr{color:var(--draft);background:var(--draft-tint);white-space:nowrap;border-radius:4px;flex:none;padding:1px 6px;font-size:11px}.tv.none.svelte-2clsr{font-family:var(--sans);color:var(--missing);font-size:13px;font-style:italic}.tf.svelte-2clsr{min-width:0;font-family:var(--serif);color:var(--ink);background:var(--paper);border:1px solid var(--done);border-radius:var(--radius);resize:vertical;flex:1;padding:6px 10px;font-size:17px;line-height:1.45}.tf.svelte-2clsr:focus-visible{outline:2px solid color-mix(in oklab, var(--done) 26%, transparent);outline-offset:1px}.editbar.svelte-2clsr{flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px;display:flex}.pm.svelte-2clsr{font-family:var(--mono);color:var(--body);background:var(--hollow);border-radius:4px;padding:1px 5px;font-size:12.5px}.pm.gone.svelte-2clsr{background:var(--broken-tint);border:1px dashed var(--broken);color:var(--broken)}.vmsg.svelte-2clsr{color:var(--broken);background:var(--broken-tint);border-radius:var(--radius);align-items:center;gap:6px;padding:4px 9px;font-size:12.5px;display:inline-flex}.btn.svelte-2clsr{border:1px solid var(--done);border-radius:var(--radius);background:var(--done);height:30px;color:var(--paper);font:inherit;cursor:pointer;padding:0 12px;font-size:12.5px;font-weight:500}.btn.quiet.svelte-2clsr{background:var(--paper);color:var(--body);border-color:var(--rule-strong);font-weight:400}.btn.svelte-2clsr:disabled{opacity:.6;cursor:default}.keys.svelte-2clsr{font-family:var(--mono);color:var(--muted);font-size:11px}.acts.svelte-a18sfu{margin-bottom:22px}.cap.svelte-a18sfu{letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0 0 8px;padding:0 6px;font-size:11px;font-weight:600}.act.svelte-a18sfu{border-radius:var(--radius);width:100%;font:inherit;color:var(--body);cursor:pointer;text-align:left;background:0 0;border:0;flex-direction:column;gap:1px;margin-bottom:4px;padding:7px 8px;display:flex}.act.svelte-a18sfu:hover:not(:disabled){background:var(--hollow)}.act.svelte-a18sfu:disabled{cursor:default}.act.svelte-a18sfu:disabled .name:where(.svelte-a18sfu){opacity:.55}.name.svelte-a18sfu{color:var(--ink);font-size:13px}.why.svelte-a18sfu{color:var(--muted);margin:0;font-size:11.5px;line-height:1.35}.bill.svelte-a18sfu{border:1px solid var(--rule);border-radius:var(--radius);background:var(--paper);padding:10px}.lede.svelte-a18sfu{color:var(--ink);margin:0 0 4px;font-size:13px}.pair.svelte-a18sfu{gap:6px;margin-top:10px;display:flex}.go.svelte-a18sfu{border-radius:var(--radius);background:var(--done);color:var(--paper);font:inherit;cursor:pointer;border:0;flex:1;padding:5px 10px;font-size:12px}.plain.svelte-a18sfu{border:1px solid var(--rule-strong);border-radius:var(--radius);color:var(--body);font:inherit;cursor:pointer;background:0 0;padding:5px 10px;font-size:12px}.track.svelte-a18sfu{background:var(--hollow);border-radius:999px;height:4px;margin:8px 0 6px;overflow:hidden}.fill.svelte-a18sfu{background:var(--done);height:100%;transition:width .3s linear;display:block}.said.svelte-a18sfu{color:var(--muted);margin:6px 0 0;padding:0 8px;font-size:11.5px}.said.bad.svelte-a18sfu{color:var(--broken)}.overview.svelte-1qmtve8{background:var(--ground);flex:1;min-width:0;overflow-y:auto}header.svelte-1qmtve8{padding:28px 24px 20px}.chip.svelte-1qmtve8{background:var(--done-tint);color:var(--done);border-radius:999px;padding:3px 12px;font-size:12px;font-weight:500;display:inline-block}h2.svelte-1qmtve8{letter-spacing:-.024em;max-width:24ch;color:var(--ink);margin:14px 0 0;font-size:30px;font-weight:500;line-height:1.16}header.svelte-1qmtve8 p:where(.svelte-1qmtve8){color:var(--muted);margin:10px 0 0;font-size:14px}.cols.svelte-1qmtve8{grid-template-columns:minmax(0,1fr) 320px;align-items:start;gap:20px;padding:0 24px 28px;display:grid}.card.svelte-1qmtve8,.jobs.svelte-1qmtve8{background:var(--paper);border:1px solid var(--rule);border-radius:14px;overflow:hidden}.side.svelte-1qmtve8{flex-direction:column;gap:16px;min-width:0;display:flex}.job.svelte-1qmtve8{border-top:1px solid var(--rule);align-items:center;gap:16px;padding:16px 20px;display:flex}.job.svelte-1qmtve8:first-child{border-top:0}.tile.svelte-1qmtve8{border-radius:var(--radius);flex:none;justify-content:center;align-items:center;width:26px;height:26px;display:inline-flex}.tile[data-state=broken].svelte-1qmtve8{background:var(--broken);color:var(--paper)}.tile[data-state=missing].svelte-1qmtve8{background:var(--missing-tint);color:var(--missing)}.tile[data-state=draft].svelte-1qmtve8{background:var(--draft-tint);color:var(--draft)}.what.svelte-1qmtve8{flex:1;min-width:0}.what.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--ink);font-size:15px;font-weight:500;display:block}.what.svelte-1qmtve8>span:where(.svelte-1qmtve8){color:var(--muted);font-size:13px;display:block}.keys.svelte-1qmtve8{font-family:var(--mono);color:var(--muted);text-overflow:ellipsis;white-space:nowrap;margin-top:4px;font-size:11px;display:block;overflow:hidden}button.svelte-1qmtve8{border:1px solid var(--rule-strong);border-radius:var(--radius);background:var(--paper);height:32px;color:var(--body);cursor:pointer;flex:none;padding:0 14px;font-family:inherit;font-size:13px}button.svelte-1qmtve8:hover{background:var(--ground)}.ring.svelte-1qmtve8{text-align:left;border:0;border-radius:0;width:100%;height:auto;padding:18px 20px;display:block}.ring.svelte-1qmtve8:disabled{cursor:default}.ring.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--muted);font-size:12px;font-weight:400;display:block}.ring.svelte-1qmtve8 strong:where(.svelte-1qmtve8){color:var(--ink);margin-top:2px;font-size:17px;font-weight:500;display:block}.ring.svelte-1qmtve8 span:where(.svelte-1qmtve8){color:var(--muted);margin-top:4px;font-size:12px;display:block}.kv.svelte-1qmtve8{border-top:1px solid var(--rule);align-items:center;gap:12px;height:44px;margin:0;padding:0 20px;display:flex}.kv.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--body);flex:1;font-size:13px;font-weight:400}.kv.svelte-1qmtve8 strong:where(.svelte-1qmtve8){color:var(--ink);font-variant-numeric:tabular-nums;font-size:15px;font-weight:500}.head.svelte-1qmtve8{border-bottom:1px solid var(--rule);color:var(--ink);margin:0;padding:16px 20px;font-size:15px;font-weight:500}.empty.svelte-1qmtve8{color:var(--muted);margin:0;padding:16px 20px;font-size:13px}.commit.svelte-1qmtve8{align-items:flex-start;gap:12px;margin:0;padding:10px 20px;display:flex}.commit.svelte-1qmtve8 code:where(.svelte-1qmtve8){font-family:var(--mono);color:var(--muted);flex:none;margin-top:2px;font-size:11px}.commit.svelte-1qmtve8>span:where(.svelte-1qmtve8){flex:1;min-width:0}.commit.svelte-1qmtve8 b:where(.svelte-1qmtve8){color:var(--body);font-size:12px;font-weight:400;line-height:1.45;display:block}.commit.svelte-1qmtve8 span:where(.svelte-1qmtve8) span:where(.svelte-1qmtve8){color:var(--muted);margin-top:2px;font-size:11px;display:block}@media (max-width:900px){.cols.svelte-1qmtve8{grid-template-columns:minmax(0,1fr)}}.shell.svelte-1xn7ig5{flex-direction:column;height:100%;display:flex;position:relative}.bar.svelte-1xn7ig5{background:var(--bar);height:48px;color:var(--on-bar);flex:none;align-items:center;gap:16px;padding:0 16px;display:flex;box-shadow:inset 0 -1px #ffffff1f}.brand.svelte-1xn7ig5{letter-spacing:.02em;opacity:.75;white-space:nowrap;font-size:13px}.brand.svelte-1xn7ig5 b:where(.svelte-1xn7ig5){opacity:1;font-weight:600}.search.svelte-1xn7ig5{border-radius:var(--radius);max-width:520px;color:var(--on-bar);font:inherit;background:#ffffff0f;border:1px solid #ffffff29;flex:1;padding:6px 12px;font-size:13px}.search.svelte-1xn7ig5::placeholder{color:#ffffff73}.search.svelte-1xn7ig5:focus-visible{outline:2px solid var(--done);outline-offset:1px}.root.svelte-1xn7ig5{font-family:var(--mono);opacity:.55;text-overflow:ellipsis;white-space:nowrap;max-width:30ch;margin-left:auto;font-size:11.5px;overflow:hidden}.problems.svelte-1xn7ig5{background:var(--broken-tint);color:var(--broken);border-bottom:1px solid var(--rule);margin:0;padding:8px 16px;font-size:12.5px;list-style:none}.body.svelte-1xn7ig5{flex:1;min-height:0;display:flex}.table.svelte-1xn7ig5{background:var(--paper);flex:1;min-width:0;overflow-y:auto}.note.svelte-1xn7ig5{color:var(--muted);margin:0;padding:24px 20px;font-size:13px}.snack.svelte-1xn7ig5{background:var(--bar);height:44px;color:var(--on-bar);border-radius:var(--radius);white-space:nowrap;align-items:center;gap:12px;margin:0;padding:0 12px 0 20px;font-size:13px;display:flex;position:absolute;bottom:24px;left:50%;transform:translate(-50%);box-shadow:0 2px 6px #0610052e,0 34px 64px -28px #06100566}.snack.svelte-1xn7ig5 svg:where(.svelte-1xn7ig5){color:#8ed67f}.snack.svelte-1xn7ig5 button:where(.svelte-1xn7ig5){height:30px;color:inherit;font:inherit;cursor:pointer;background:#ffffff24;border:0;border-radius:4px;padding:0 12px;font-size:12.5px}.verbaly-studio{--paper:#f8fbf7;--ground:#eff4ee;--hollow:#e5ede4;--rule:#d7dfd5;--rule-strong:#828d80;--muted:#636c61;--body:#374036;--ink:#061005;--bar:#131e12;--on-bar:#f8fbf7;--broken:#b43931;--broken-tint:#eee0db;--missing:#8e5a04;--missing-tint:#e9e4d5;--draft:#2267ad;--draft-tint:#dae6ed;--done:#2e7428;--done-tint:#dce8da;--sans:"Schibsted Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--serif:"Newsreader", ui-serif, Georgia, "Times New Roman", serif;--mono:"JetBrains Mono", ui-monospace, "Cascadia Code", "SF Mono", monospace;--rail:232px;--radius:6px}@media (prefers-color-scheme:dark){.verbaly-studio:not([data-theme=light]){--paper:#10170f;--ground:#161e15;--hollow:#1d271c;--rule:#2a352a;--rule-strong:#6f7a6d;--muted:#9aa598;--body:#d3dbd1;--ink:#f2f7f1;--broken:#f08a82;--broken-tint:#3a211f;--missing:#dcae4e;--missing-tint:#352c16;--draft:#7db6e8;--draft-tint:#172a3a;--done:#79c46f;--done-tint:#182c16}}.verbaly-studio[data-theme=dark]{--paper:#10170f;--ground:#161e15;--hollow:#1d271c;--rule:#2a352a;--rule-strong:#6f7a6d;--muted:#9aa598;--body:#d3dbd1;--ink:#f2f7f1;--broken:#f08a82;--broken-tint:#3a211f;--missing:#dcae4e;--missing-tint:#352c16;--draft:#7db6e8;--draft-tint:#172a3a;--done:#79c46f;--done-tint:#182c16}.verbaly-studio,.verbaly-studio *,.verbaly-studio :before,.verbaly-studio :after{box-sizing:border-box}.verbaly-studio{background:var(--ground);color:var(--body);font-family:var(--sans);-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5}.verbaly-studio code,.verbaly-studio kbd{font-family:var(--mono);font-size:.92em}@media (prefers-reduced-motion:reduce){.verbaly-studio,.verbaly-studio *,.verbaly-studio :before,.verbaly-studio :after{transition-duration:.01ms!important;animation-duration:.01ms!important}}html,body{height:100%}body{background:var(--ground);margin:0}#app{height:100%}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible,d=()=>{};function f(e){for(var t=0;t<e.length;t++)e[t]()}function p(){var e,t;return{promise:new Promise((n,r)=>{e=n,t=r}),resolve:e,reject:t}}var m=1024,h=2048,g=4096,_=8192,v=16384,y=32768,b=1<<25,x=65536,S=1<<19,ee=1<<20,te=1<<25,C=65536,ne=1<<21,re=1<<22,ie=1<<23,ae=Symbol(`$state`),oe=Symbol(`component`),se=Symbol(``),ce=Symbol(`attributes`),le=Symbol(`class`),ue=Symbol(`style`),de=Symbol(`text`),fe=Symbol(`form reset`),pe=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},me=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),he={},w=Symbol(`uninitialized`),ge=`http://www.w3.org/1999/xhtml`;function _e(){console.warn(`https://svelte.dev/e/derived_inert`)}function ve(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function ye(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var T=!1;function be(e){T=e}var E;function D(e){if(e===null)throw ve(),he;return E=e}function xe(){return D(Xt(E))}function O(e){if(T){if(Xt(E)!==null)throw ve(),he;E=e}}function Se(e=1){if(T){for(var t=e,n=E;t--;)n=Xt(n);E=n}}function Ce(e=!0){for(var t=0,n=E;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=Xt(n);e&&n.remove(),n=i}}function we(e){if(!e||e.nodeType!==8)throw ve(),he;return e.data}function Te(e){return e===this.v}function Ee(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function De(e){return!Ee(e,this.v)}function Oe(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function ke(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function Ae(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function je(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function Me(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Ne(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function Pe(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Fe(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Ie(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Le(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function Re(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var k=null;function ze(e){k=e}function Be(e,t=!1,n){k={p:k,i:!1,c:null,e:null,s:e,x:null,r:U,l:null}}function Ve(e){var t=k,n=t.e;if(n!==null){t.e=null;for(var r of n)dn(r)}return e!==void 0&&(t.x=e),t.i=!0,k=t.p,He(e)}function He(e={}){return i(e,oe,{value:!0}),e}function Ue(){return!0}var We=[];function Ge(){var e=We;We=[],f(e)}function Ke(e){if(We.length===0&&!xt){var t=We;queueMicrotask(()=>{t===We&&Ge()})}We.push(e)}function qe(){for(;We.length>0;)Ge()}var Je=~(h|g|m);function A(e,t){e.f=e.f&Je|t}function Ye(e){e.f&512||e.deps===null?A(e,m):A(e,g)}function Xe(e){if(e!==null)for(let t of e)t.f&2&&t.f&65536&&(t.f^=C,Xe(t.deps))}function Ze(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),Xe(e.deps),A(e,m)}function Qe(e,t){if(t){let t=document.body;e.autofocus=!0,Ke(()=>{document.activeElement===t&&e.focus()})}}function $e(e){T&&I(e)!==null&&Qt(e)}var et=!1;function tt(){et||(et=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[fe]?.()})},{capture:!0}))}function nt(e){var t=H,n=U;Mn(null),Nn(null);try{return e()}finally{Mn(t),Nn(n)}}function rt(e,t,n,r=n){e.addEventListener(t,()=>nt(n));let i=e[fe];e[fe]=i?()=>{i(),r(!0)}:()=>r(!0),tt()}function it(e,t,n,r){let i=Ue()?ct:dt;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=U,c=at(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){rn(e,s)}ot()}}var d=st();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>ut(e))).then(u).catch(e=>rn(e,s)).finally(d)}l?l.then(()=>{c(),f(),ot()}):f()}function at(){var e=U,t=H,n=k,r=M;return function(i=!0){Nn(e),Mn(t),ze(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function ot(e=!0){Nn(null),Mn(null),ze(null),e&&M?.deactivate()}function st(){var e=U,t=e.b,n=M,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function ct(e){var t=2|h;return U!==null&&(U.f|=S),{ctx:k,deps:null,effects:null,equals:Te,f:t,fn:e,reactions:null,rv:0,v:w,wv:0,parent:U,ac:null}}var lt=Symbol(`obsolete`);function ut(e,t,n){let r=U;r===null&&ke();var i=void 0,a=Rt(w),o=!H,s=new Set;return pn(()=>{var t=U,n=p();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==pe&&n.reject(e)}).finally(ot)}catch(e){n.reject(e),ot()}var c=M;if(o){if(t.f&32768)var l=st();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(lt);else for(let e of s.values())e.reject(lt);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==lt&&(c.activate(),t?(a.f|=ie,Bt(a,t)):(a.f&8388608&&(a.f^=ie),Bt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),ln(()=>{for(let e of s)e.reject(lt)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function j(e){let t=ct(e);return Fn(t),t}function dt(e){let t=ct(e);return t.equals=De,t}function ft(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n<t.length;n+=1)V(t[n])}}function pt(e){var t,n=U,r=e.parent;if(!kn&&r!==null&&e.v!==w&&r.f&24576)return _e(),e.v;Nn(r);try{e.f&=~C,ft(e),t=Gn(e)}finally{Nn(n)}return t}function mt(e){var t=pt(e);if(!e.equals(t)&&(e.wv=Hn(),(!M?.is_fork||e.deps===null)&&(M===null?e.v=t:(M.capture(e,t,!0),vt?.capture(e,t,!0)),e.deps===null))){A(e,m);return}kn||(yt===null?Ye(e):(cn()||M?.is_fork)&&yt.set(e,t))}function ht(e){if(e.effects!==null)for(let t of e.effects)(t.teardown||t.ac)&&(t.teardown?.(),t.ac!==null&&nt(()=>{t.ac.abort(pe),t.ac=null}),t.fn!==null&&(t.teardown=d),Jn(t,0),vn(t))}function gt(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&Yn(t)}var _t=null,M=null,vt=null,yt=null,bt=null,xt=!1,St=!1,Ct=null,wt=null,Tt=0,Et=1,Dt=class e{id=Et++;#e=!1;linked=!0;#t=null;#n=null;async_deriveds=new Map;current=new Map;previous=new Map;#r=new Set;#i=new Set;#a=0;#o=new Map;#s=null;#c=[];#l=[];#u=new Set;#d=new Set;#f=new Map;#p=new Set;is_fork=!1;#m=!1;constructor(){_t===null?_t=this:(_t.#n=this,this.#t=_t),_t=this}#h(){if(this.is_fork)return!0;for(let n of this.#o.keys()){for(var e=n,t=!1;e.parent!==null;){if(this.#f.has(e)){t=!0;break}e=e.parent}if(!t)return!0}return!1}skip_effect(e){this.#f.has(e)||this.#f.set(e,{d:[],m:[]}),this.#p.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#f.get(e);if(n){this.#f.delete(e);for(var r of n.d)A(r,h),t(r);for(r of n.m)A(r,g),t(r)}this.#p.add(e)}#g(){this.#e=!0,Tt++>1e3&&(this.#x(),kt());for(let e of this.#u)this.#d.delete(e),A(e,h),this.schedule(e);for(let e of this.#d)A(e,g),this.schedule(e);let t=this.#c;this.#c=[],this.apply();var n=Ct=[],r=[],i=wt=[];for(let e of t)try{this.#_(e,n,r)}catch(t){throw Pt(e),this.#h()||this.discard(),t}if(M=null,i.length>0){var a=e.ensure();for(let e of i)a.schedule(e)}if(Ct=null,wt=null,this.#h()){this.#b(r),this.#b(n);for(let[e,t]of this.#f)Nt(e,t);i.length>0&&M.#g();return}let o=this.#v();if(o){this.#b(r),this.#b(n),o.#y(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),vt=this,jt(r),jt(n),vt=null,this.#s?.resolve();var s=M;if(this.#a===0&&(this.#c.length===0||s!==null)&&this.#x(),this.#c.length>0){if(s!==null){let e=s;e.#c.push(...this.#c.filter(t=>!e.#c.includes(t)))}else s=this}s!==null&&(It.clear(),s.#g())}#_(e,t,n){e.f^=m;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#f.has(r))&&r.fn!==null){a?r.f^=m:i&4?t.push(r):Un(r)&&(i&16&&this.#d.add(r),Yn(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#v(){for(var e=this.#t;e!==null;){if(!e.is_fork){for(let[t,[,n]]of this.current)if(e.current.has(t)&&!n)return e}e=e.#t}return null}#y(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_effects(e.#u,e.#d);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#d.delete(i),A(i,h),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#x(),M=this,this.#g()}#b(e){for(var t=0;t<e.length;t+=1)Ze(e[t],this.#u,this.#d)}capture(e,t,n=!1){e.v!==w&&!this.previous.has(e)&&this.previous.set(e,e.v),e.f&8388608||(this.current.set(e,[t,n]),yt?.set(e,t)),this.is_fork||(e.v=t)}activate(){M=this}deactivate(){M=null,yt=null}flush(){try{St=!0,M=this,this.#g()}finally{Tt=0,bt=null,Ct=null,wt=null,St=!1,M=null,yt=null,It.clear()}}discard(){for(let e of this.#i)e(this);this.#i.clear();for(let e of this.async_deriveds.values())e.reject(lt);this.#x(),this.#s?.resolve()}register_created_effect(e){this.#l.push(e)}increment(e,t){if(this.#a+=1,e){let e=this.#o.get(t)??0;this.#o.set(t,e+1)}}decrement(e,t){if(--this.#a,e){let e=this.#o.get(t)??0;e===1?this.#o.delete(t):this.#o.set(t,e-1)}this.#m||(this.#m=!0,Ke(()=>{this.#m=!1,this.linked&&this.flush()}))}transfer_effects(e,t){for(let t of e)this.#u.add(t);for(let e of t)this.#d.add(e);e.clear(),t.clear()}oncommit(e){this.#r.add(e)}ondiscard(e){this.#i.add(e)}settled(){return(this.#s??=p()).promise}static ensure(){if(M===null){let t=M=new e;!St&&!xt&&Ke(()=>{t.#e||t.flush()})}return M}apply(){yt=null}schedule(e){if(bt=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}for(var t=e;t.parent!==null;){t=t.parent;var n=t.f;if(Ct!==null&&t===U&&(H===null||!(H.f&2)))return;if(n&96){if(!(n&1024))return;t.f^=m}}this.#c.push(t)}#x(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?_t=e:t.#t=e,this.linked=!1}}};function Ot(e){var t=xt;xt=!0;try{var n;for(e&&(M!==null&&!M.is_fork&&M.flush(),n=e());;){if(qe(),M===null)return n;M.flush()}}finally{xt=t}}function kt(){try{Pe()}catch(e){rn(e,bt)}}var At=null;function jt(e){var t=e.length;if(t!==0){for(var n=0;n<t;){var r=e[n++];if(!(r.f&24576)&&Un(r)&&(At=new Set,Yn(r),r.deps===null&&r.first===null&&r.nodes===null&&r.teardown===null&&r.ac===null&&xn(r),At?.size>0)){It.clear();for(let e of At){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)At.has(n)&&(At.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||Yn(n)}}At.clear()}}At=null}}function Mt(e){M.schedule(e)}function Nt(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),A(e,m);for(var n=e.first;n!==null;)Nt(n,t),n=n.next}}function Pt(e){A(e,m);for(var t=e.first;t!==null;)Pt(t),t=t.next}var Ft=new Set,It=new Map,Lt=!1;function Rt(e,t){return{f:0,v:e,reactions:null,equals:Te,rv:0,wv:0}}function N(e,t){let n=Rt(e,t);return Fn(n),n}function zt(e,t=!1,n=!0){let r=Rt(e);return t||(r.equals=De),r}function P(e,t,n=!1){return H!==null&&(!jn||H.f&131072)&&Ue()&&H.f&4325394&&(Pn===null||!Pn.has(e))&&Le(),Bt(e,n?Wt(t):t,wt)}function Bt(e,t,n=null){if(!e.equals(t)){kn?It.set(e,t):It.has(e)||It.set(e,e.v);var r=Dt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&pt(t),yt===null&&Ye(t)}e.wv=Hn(),Ut(e,h,n),Ue()&&U!==null&&U.f&1024&&!(U.f&96)&&(In===null?Ln([e]):In.push(e)),!r.is_fork&&Ft.size>0&&!Lt&&Vt()}return t}function Vt(){Lt=!1;for(let e of Ft){e.f&1024&&A(e,g);let t;try{t=Un(e)}catch{t=!0}t&&Yn(e)}Ft.clear()}function Ht(e){P(e,e.v+1)}function Ut(e,t,n){var r=e.reactions;if(r!==null)for(var i=Ue(),a=r.length,o=0;o<a;o++){var s=r[o],c=s.f;if(i||s!==U){var l=(c&h)===0;if(l&&A(s,t),c&131072)Ft.add(s);else if(c&2){var u=s;yt?.delete(u),c&65536||(c&512&&(U===null||!(U.f&2097152))&&(s.f|=C),Ut(u,g,n))}else if(l){var d=s;c&16&&At!==null&&At.add(d),n===null?Mt(d):n.push(d)}}}}function Wt(t){if(typeof t!=`object`||!t||ae in t||oe in t)return t;let n=l(t);if(n!==s&&n!==c)return t;var r=new Map,i=e(t),o=N(0),u=null,d=Bn,f=e=>{if(Bn===d)return e();var t=H,n=Bn;Mn(null),Vn(d);var r=e();return Mn(t),Vn(n),r};return i&&r.set(`length`,N(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&Fe();var i=r.get(t);return i===void 0?f(()=>{var e=N(n.value,u);return r.set(t,e),e}):P(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>N(w,u));r.set(t,e),Ht(o)}}else P(n,w),Ht(o);return!0},get(e,n,i){if(n===ae)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>N(Wt(s?e[n]:w),u)),r.set(n,o)),o!==void 0){var c=K(o);return c===w?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){var n=Reflect.getOwnPropertyDescriptor(e,t);if(n&&`value`in n){var i=r.get(t);i&&(n.value=K(i))}else if(n===void 0){var a=r.get(t),o=a?.v;if(a!==void 0&&o!==w)return{enumerable:!0,configurable:!0,value:o,writable:!0}}return n},has(e,t){if(t===ae)return!0;var n=r.get(t),i=n!==void 0&&n.v!==w||Reflect.has(e,t);return(n!==void 0||U!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>N(i?Wt(e[t]):w,u)),r.set(t,n)),K(n)===w)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;d<c.v;d+=1){var p=r.get(d+``);p===void 0?d in e&&(p=f(()=>N(w,u)),r.set(d+``,p)):P(p,w)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>N(void 0,u)),P(c,Wt(n)),r.set(t,c));else{l=c.v!==w;var m=f(()=>Wt(n));P(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&P(g,_+1)}Ht(o)}return!0},ownKeys(e){K(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==w});for(var[n,i]of r)i.v!==w&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Ie()}})}var Gt,Kt,qt,Jt;function Yt(){if(Gt===void 0){Gt=window,Kt=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;qt=a(t,`firstChild`).get,Jt=a(t,`nextSibling`).get,u(e)&&(e[le]=void 0,e[ce]=null,e[ue]=void 0,e.__e=void 0),u(n)&&(n[de]=void 0)}}function F(e=``){return document.createTextNode(e)}function I(e){return qt.call(e)}function Xt(e){return Jt.call(e)}function L(e,t){if(!T)return I(e);var n=I(E);if(n===null)n=E.appendChild(F());else if(t&&n.nodeType!==3){var r=F();return n?.before(r),D(r),r}return t&&tn(n),D(n),n}function Zt(e,t=!1){if(!T){var n=I(e);return n instanceof Comment&&n.data===``?Xt(n):n}if(t){if(E?.nodeType!==3){var r=F();return E?.before(r),D(r),r}tn(E)}return E}function R(e,t=!1){if(!T)return I(e);var n=L(e,t);return O(e),n}function z(e,t=1,n=!1){let r=T?E:e;for(var i;t--;)i=r,r=Xt(r);if(!T)return r;if(n){if(r?.nodeType!==3){var a=F();return r===null?i?.after(a):r.before(a),D(a),a}tn(r)}return D(r),r}function Qt(e){e.textContent=``}function $t(){return!1}function en(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function tn(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function nn(e){var t=U;if(t===null)return H.f|=ie,e;if(!(t.f&32768)&&!(t.f&4))throw e;rn(e,t)}function rn(e,t){if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128&&!(t.f&33570816)){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}function an(e){U===null&&(H===null&&Ne(e),Me()),kn&&je(e)}function on(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function sn(e,t){var n=U;n!==null&&n.f&8192&&(e|=_);var r={ctx:k,deps:null,nodes:null,f:e|h|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};M?.register_created_effect(r);var i=r;if(e&4)Ct===null?Dt.ensure().schedule(r):Ct.push(r);else if(t!==null){try{Yn(r)}catch(e){throw V(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=x))}if(i!==null&&(i.parent=n,n!==null&&on(i,n),H!==null&&H.f&2&&!(e&64))){var a=H;(a.effects??=[]).push(i)}return r}function cn(){return H!==null&&!jn}function ln(e){let t=sn(8,null);return A(t,m),t.teardown=e,t}function un(e){an(`$effect`);var t=U.f;if(!H&&t&32&&k!==null&&!k.i){var n=k;(n.e??=[]).push(e)}else return dn(e)}function dn(e){return sn(4|ee,e)}function fn(e){Dt.ensure();let t=sn(64|S,e);return(e={})=>new Promise(n=>{e.outro?Sn(t,()=>{V(t),n(void 0)}):(V(t),n(void 0))})}function pn(e){return sn(re|S,e)}function mn(e,t=0){return sn(8|t,e)}function B(e,t=[],n=[],r=[]){it(r,t,n,t=>{sn(8,()=>{e(...t.map(K))})})}function hn(e,t=0){return sn(16|t,e)}function gn(e){return sn(32|S,e)}function _n(e){var t=e.teardown;if(t!==null){let n=kn,r=H;An(!0),Mn(null);try{t.call(null)}catch(t){rn(t,e.parent)}finally{An(n),Mn(r)}}}function vn(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&nt(()=>{e.abort(pe)});var r=n.next;n.f&64?n.parent=null:V(n,t),n=r}}function yn(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||V(t),t=n}}function V(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(bn(e.nodes.start,e.nodes.end),n=!0),e.f|=b,vn(e,t&&!n),Jn(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();_n(e),e.f^=b,e.f|=v;var i=e.parent;i!==null&&i.first!==null&&xn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function bn(e,t){for(;e!==null;){var n=e===t?null:Xt(e);e.remove(),e=n}}function xn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function Sn(e,t,n=!0){var r=[];e.f|=256,Cn(e,r,!0);var i=()=>{n&&V(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function Cn(e,t,n){if(!(e.f&8192)){e.f^=_;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);Cn(i,t,o?n:!1)}i=a}}}function wn(e){e.f&=-257,Tn(e,!0)}function Tn(e,t){if(!(e.f&256)&&e.f&8192){e.f^=_,e.f&1024||(A(e,h),Dt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Tn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function En(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:Xt(n);t.append(n),n=i}}var Dn=null,On=!1,kn=!1;function An(e){kn=e}var H=null,jn=!1;function Mn(e){H=e}var U=null;function Nn(e){U=e}var Pn=null;function Fn(e){H!==null&&(Pn??=new Set).add(e)}var W=null,G=0,In=null;function Ln(e){In=e}var Rn=1,zn=0,Bn=zn;function Vn(e){Bn=e}function Hn(){return++Rn}function Un(e){var t=e.f;if(t&2048)return!0;if(t&2&&(e.f&=~C),t&4096){for(var n=e.deps,r=n.length,i=0;i<r;i++){var a=n[i];if(Un(a)&&mt(a),a.wv>e.wv)return!0}t&512&&yt===null&&A(e,m)}return!1}function Wn(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Pn!==null&&Pn.has(e)))for(var i=0;i<r.length;i++){var a=r[i];a.f&2?Wn(a,t,!1):t===a&&(n?A(a,h):a.f&1024&&A(a,g),Mt(a))}}function Gn(e){var t=W,n=G,r=In,i=H,a=Pn,o=k,s=jn,c=Bn,l=e.f;W=null,G=0,In=null,H=l&96?null:e,Pn=null,ze(e.ctx),jn=!1,Bn=++zn,e.ac!==null&&(nt(()=>{e.ac.abort(pe)}),e.ac=null);try{e.f|=ne;var u=e.fn,d=u();e.f|=y;var f=Kn(e);if(Ue()&&In!==null&&!jn&&f!==null&&!(e.f&6146))for(var p=0;p<In.length;p++)Wn(In[p],e);if(i!==null&&i!==e){if(zn++,i.deps!==null)for(let e=0;e<n;e+=1)i.deps[e].rv=zn;if(t!==null)for(let e of t)e.rv=zn;In!==null&&(r===null?r=In:r.push(...In))}return e.f&8388608&&(e.f^=ie),d}catch(t){return Kn(e),nn(t)}finally{e.f^=ne,W=t,G=n,In=r,H=i,Pn=a,ze(o),jn=s,Bn=c}}function Kn(e){var t=e.deps,n=M?.is_fork;if(W!==null){var r;if(n||Jn(e,G),t!==null&&G>0)for(t.length=G+W.length,r=0;r<W.length;r++)t[G+r]=W[r];else e.deps=t=W;if(cn()&&e.f&512)for(r=G;r<t.length;r++)(t[r].reactions??=[]).push(e)}else!n&&t!==null&&G<t.length&&(Jn(e,G),t.length=G);return t}function qn(e,r){let i=r.reactions;if(i!==null){var a=t.call(i,e);if(a!==-1){var o=i.length-1;o===0?i=r.reactions=null:(i[a]=i[o],i.pop())}}if(i===null&&r.f&2&&(W===null||!n.call(W,r))){var s=r;s.f&512&&(s.f^=512,s.f&=~C),s.v!==w&&Ye(s),s.ac!==null&&nt(()=>{s.ac.abort(pe),s.ac=null,A(s,h)}),ht(s),Jn(s,0)}}function Jn(e,t){var n=e.deps;if(n!==null)for(var r=t;r<n.length;r++)qn(e,n[r])}function Yn(e){var t=e.f;if(!(t&16384)){A(e,m);var n=U,r=On;U=e,On=!(t&96);try{t&16777232?yn(e):vn(e),_n(e);var i=Gn(e);e.teardown=typeof i==`function`?i:null,e.wv=Rn}finally{On=r,U=n}}}async function Xn(){await Promise.resolve(),Ot()}function K(e){var t=!!(e.f&2);if(Dn?.add(e),H!==null&&!jn&&!(U!==null&&U.f&16384)&&(Pn===null||!Pn.has(e))){var r=H.deps;if(H.f&2097152)e.rv<zn&&(e.rv=zn,W===null&&r!==null&&r[G]===e?G++:W===null?W=[e]:W.push(e));else{H.deps??=[],n.call(H.deps,e)||H.deps.push(e);var i=e.reactions;i===null?e.reactions=[H]:n.call(i,H)||i.push(H)}}if(kn&&It.has(e))return It.get(e);if(t){var a=e;if(kn){var o=a.v;return(!(a.f&1024)&&a.reactions!==null||Qn(a))&&(o=pt(a)),It.set(a,o),o}var s=!(a.f&512)&&!jn&&H!==null&&(On||!!(H.f&512)),c=(a.f&y)===0;Un(a)&&(s&&(a.f|=512),mt(a)),s&&!c&&(gt(a),Zn(a))}if(yt?.has(e))return yt.get(e);if(e.f&8388608)throw e.v;return e.v}function Zn(e){if(e.f|=512,e.deps!==null)for(let t of e.deps)(t.reactions??=[]).push(e),t.f&2&&!(t.f&512)&&(gt(t),Zn(t))}function Qn(e){if(e.v===w)return!0;if(e.deps===null)return!1;for(let t of e.deps)if(It.has(t)||t.f&2&&Qn(t))return!0;return!1}function $n(e){var t=jn;try{return jn=!0,e()}finally{jn=t}}[...`allowfullscreen.async.autofocus.autoplay.checked.controls.default.disabled.formnovalidate.indeterminate.inert.ismap.loop.multiple.muted.nomodule.novalidate.open.playsinline.readonly.required.reversed.seamless.selected.webkitdirectory.defer.disablepictureinpicture.disableremoteplayback`.split(`.`)];var er=[`touchstart`,`touchmove`];function tr(e){return er.includes(e)}var nr=Symbol(`events`),rr=new Set,ir=new Set;function ar(e,t,n,r={}){function i(e){if(r.capture||ur.call(t,e),!e.cancelBubble)return nt(()=>n?.call(this,e))}return e.startsWith(`pointer`)||e.startsWith(`touch`)||e===`wheel`?Ke(()=>{t.addEventListener(e,i,r)}):t.addEventListener(e,i,r),i}function or(e,t,n,r,i){var a={capture:r,passive:i},o=ar(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&ln(()=>{t.removeEventListener(e,o,a)})}function q(e,t,n){(t[nr]??={})[e]=n}function sr(e){for(var t=0;t<e.length;t++)rr.add(e[t]);for(var n of ir)n(e)}var cr=null,lr=!1;function ur(e){var t=this,n=t.ownerDocument,r=e.type,a=e.composedPath?.()||[],o=a[0]||e.target;cr=e,lr||(lr=!0,setTimeout(()=>{lr=!1,cr=null}));var s=0,c=cr===e&&e[nr];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[nr]=t;return}var u=a.indexOf(t);if(u===-1)return;l<=u&&(s=l)}if(o=a[s]||e.target,o!==t){i(e,`currentTarget`,{configurable:!0,get(){return o||n}});var d=H,f=U;Mn(null),Nn(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[nr]?.[r];h!=null&&(!o.disabled||e.target===o)&&h.call(o,e)}catch(e){p?m.push(e):p=e}if(e.cancelBubble)break;s++,o=s<a.length?a[s]:null}if(p){for(let e of m)queueMicrotask(()=>{throw e});throw p}}finally{e[nr]=t,delete e.currentTarget,Mn(d),Nn(f)}}}var dr=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function fr(e){return dr?.createHTML(e)??e}function pr(e){var t=en(`template`);return t.innerHTML=fr(e.replaceAll(`<!>`,`<!---->`)),t.content}function mr(e,t){var n=U;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function J(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(`<!>`);return()=>{if(T)return mr(E,null),E;i===void 0&&(i=pr(a?e:`<!>`+e),n||(i=I(i)));var t=r||Kt?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=I(t),s=t.lastChild;mr(o,s)}else mr(t,t);return t}}function hr(e,t,n=`svg`){var r=!e.startsWith(`<!>`),i=!!(t&1),a=`<${n}>${r?e:`<!>`+e}</${n}>`,o;return()=>{if(T)return mr(E,null),E;if(!o){var e=I(pr(a));if(i)for(o=document.createDocumentFragment();I(e);)o.appendChild(I(e));else o=I(e)}var t=o.cloneNode(!0);if(i){var n=I(t),r=t.lastChild;mr(n,r)}else mr(t,t);return t}}function gr(e,t){return hr(e,t,`svg`)}function _r(e=``){if(!T){var t=F(e+``);return mr(t,t),t}var n=E;return n.nodeType===3?tn(n):(n.before(n=F()),D(n)),mr(n,n),n}function vr(){if(T)return mr(E,null),E;var e=document.createDocumentFragment(),t=document.createComment(``),n=F();return e.append(t,n),mr(t,n),e}function Y(e,t){if(T){var n=U;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=E),xe();return}e!==null&&e.before(t)}function yr(e){let t=0,n=Rt(0),r;return()=>{cn()&&(K(n),mn(()=>(t===0&&(r=$n(()=>e(()=>Ht(n)))),t+=1,()=>{Ke(()=>{--t,t===0&&(r?.(),r=void 0,Ht(n))})})))}}var br=x|S;function xr(e,t,n,r){new Sr(e,t,n,r)}var Sr=class{parent;is_pending=!1;transform_error;#e;#t=T?E:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Set;#p=new Set;#m=null;#h=yr(()=>(this.#m=Rt(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=U;t.b=this,t.f|=128,n(e)},this.parent=U.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=hn(()=>{if(T){let e=this.#t;xe();let t=e.data===`[!`;if(e.data.startsWith(`[?`)){let t=JSON.parse(e.data.slice(2));this.#_(t)}else t?this.#y():this.#g()}else this.#b()},br),T&&(this.#e=E)}#g(){try{this.#a=gn(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Ke(r),t&&(this.#s=gn(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){ye();return}t=!0,n&&Re(),this.#s!==null&&Sn(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})};return{reset:r,invoke_onerror:()=>{try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){rn(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=gn(()=>e(this.#e)),Ke(()=>{var e=this.#c=document.createDocumentFragment(),t=F(),n=!1;if(e.append(t),this.#a=this.#S(()=>{try{return gn(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){rn(e,this.#i.parent)}return null}}),this.#a===null){this.#c=null,n&&this.#x(M);return}this.#u===0&&(this.#e.before(e),this.#c=null,Sn(this.#o,()=>{this.#o=null}),this.#x(M))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=gn(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();En(this.#a,e);let t=this.#n.pending;this.#o=gn(()=>t(this.#e))}else this.#x(M)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){Ze(e,this.#f,this.#p)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=U,n=H,r=k;Nn(this.#i),Mn(this.#i),ze(this.#i.ctx);try{return Dt.ensure(),e()}finally{Nn(t),Mn(n),ze(r)}}#C(e,t){if(!this.has_pending_snippet()){this.parent&&this.parent.#C(e,t);return}this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&Sn(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!(!this.#m||this.#d)&&(this.#d=!0,Ke(()=>{this.#d=!1,this.#m&&Bt(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),K(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;M?.is_fork?(this.#a&&M.skip_effect(this.#a),this.#o&&M.skip_effect(this.#o),this.#s&&M.skip_effect(this.#s),M.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(V(this.#a),null),this.#o&&=(V(this.#o),null),this.#s&&=(V(this.#s),null),T&&(D(this.#t),Se(),D(Ce()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return gn(()=>{var r=U;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return rn(e,this.#i.parent),null}}))};Ke(()=>{var t;try{t=this.transform_error(e)}catch(e){rn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>rn(e,this.#i&&this.#i.parent)):n(t)})}};function X(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[de]??=e.nodeValue)&&(e[de]=n,e.nodeValue=`${n}`)}function Cr(e,t){return Tr(e,t)}var wr=new Map;function Tr(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){Yt();var l=void 0,u=fn(()=>{var s=n??t.appendChild(F());xr(s,{pending:()=>{}},t=>{Be({});var n=k;if(o&&(n.c=o),a&&(i.$$events=a),T&&mr(t,null),l=e(t,i)||He(),T&&(U.nodes.end=E,E===null||E.nodeType!==8||E.data!==`]`))throw ve(),he;Ve()},c);var u=new Set,d=e=>{for(var n=0;n<e.length;n++){var r=e[n];if(!u.has(r)){u.add(r);var i=tr(r);for(let e of[t,document]){var a=wr.get(e);a===void 0&&(a=new Map,wr.set(e,a));var o=a.get(r);o===void 0?(e.addEventListener(r,ur,{passive:i}),a.set(r,1)):a.set(r,o+1)}}}};return d(r(rr)),ir.add(d),()=>{for(var e of u)for(let n of[t,document]){var r=wr.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,ur),r.delete(e),r.size===0&&wr.delete(n)):r.set(e,i)}ir.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return Er.set(l,u),l}var Er=new WeakMap,Dr=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)wn(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(wn(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(V(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();En(r,t),t.append(F()),this.#n.set(e,{effect:r,fragment:t})}else V(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),Sn(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(V(n.effect),this.#n.delete(e))};ensure(e,t){var n=M,r=$t();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=F();i.append(a),this.#n.set(e,{effect:gn(()=>t(a)),fragment:i})}else this.#t.set(e,gn(()=>t(this.anchor)))}if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else T&&(this.anchor=E),this.#a(n)}};function Z(e,t,n=!1){var r;T&&(r=E,xe());var i=new Dr(e),a=n?x:0;function o(e,t){if(T){var n=we(r);if(e!==parseInt(n.substring(1))){var a=Ce();D(a),i.anchor=a,be(!1),i.ensure(e,t),be(!0);return}}i.ensure(e,t)}hn(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}function Or(e,t){return t}function kr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c<a;c++){let n=t[c];Sn(n,()=>{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;Ar(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null&&e.pending.size===0;if(l){var u=n,d=u.parentNode;Qt(d),d.append(u),e.items.clear()}Ar(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Ar(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i<t.length;i++){var a=t[i];r?.has(a)?(a.f|=te,En(a,document.createDocumentFragment())):V(t[i],n)}}var jr;function Mr(t,n,i,a,o,s=null){var c=t,l=new Map;if(n&4){var u=t;c=T?D(I(u)):u.appendChild(F())}T&&xe();var d=null,f=dt(()=>{var t=i();return e(t)?t:t==null?[]:r(t)}),p,m=new Map,h=!0;function g(e){v.effect.f&16384||(v.pending.delete(e),v.fallback=d,Pr(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=te,Ir(d,null,c)):wn(d):Sn(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:hn(()=>{p=K(f);var e=p.length;let t=!1;T&&we(c)===`[!`!=(e===0)&&(c=Ce(),D(c),be(!1),t=!0);for(var r=new Set,u=M,v=$t(),y=0;y<e;y+=1){T&&E.nodeType===8&&E.data===`]`&&(c=E,t=!0,be(!1));var b=p[y],x=a(b,y),S=h?null:l.get(x);S?(S.v&&Bt(S.v,b),S.i&&Bt(S.i,y),v&&u.unskip_effect(S.e)):(S=Fr(l,h?c:jr??=F(),b,x,y,o,n,i),h||(S.e.f|=te),l.set(x,S)),r.add(x)}if(e===0&&s&&!d&&(h?d=gn(()=>s(c)):(d=gn(()=>s(jr??=F())),d.f|=te)),e>r.size&&Ae(``,``,``),T&&e>0&&D(Ce()),!h){if(m.set(u,r),v){for(let[e,t]of l)r.has(e)||u.skip_effect(t.e);u.oncommit(g),u.ondiscard(_)}else g(u)}t&&be(!0),K(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,T&&(c=E)}function Nr(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function Pr(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=Nr(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v<s;v+=1)h=t[v],g=a(h,v),_=c.get(g).e,_.f&33554432||(_.nodes?.a?.measure(),(f??=new Set).add(_));for(v=0;v<s;v+=1){if(h=t[v],g=a(h,v),_=c.get(g).e,e.outrogroups!==null)for(let t of e.outrogroups)t.pending.delete(_),t.done.delete(_);if(_.f&8192&&(wn(_),o&&(_.nodes?.a?.unfix(),(f??=new Set).delete(_))),_.f&33554432){if(_.f^=te,_===l)Ir(_,null,n);else{var y=d?d.next:l;_===e.effect.last&&(e.effect.last=_.prev),_.prev&&(_.prev.next=_.next),_.next&&(_.next.prev=_.prev),Lr(e,d,_),Lr(e,_,y),Ir(_,y,n),d=_,p=[],m=[],l=Nr(d.next);continue}}if(_!==l){if(u!==void 0&&u.has(_)){if(p.length<m.length){var b=m[0],x;d=b.prev;var S=p[0],ee=p[p.length-1];for(x=0;x<p.length;x+=1)Ir(p[x],b,n);for(x=0;x<m.length;x+=1)u.delete(m[x]);Lr(e,S.prev,ee.next),Lr(e,d,S),Lr(e,ee,b),l=b,d=ee,--v,p=[],m=[]}else u.delete(_),Ir(_,l,n),Lr(e,_.prev,_.next),Lr(e,_,d===null?e.effect.first:d.next),Lr(e,d,_),d=_;continue}for(p=[],m=[];l!==null&&l!==_;)(u??=new Set).add(l),m.push(l),l=Nr(l.next);if(l===null)continue}_.f&33554432||p.push(_),d=_,l=Nr(_.next)}if(e.outrogroups!==null){for(let t of e.outrogroups)t.pending.size===0&&(Ar(e,r(t.done)),e.outrogroups?.delete(t));e.outrogroups.size===0&&(e.outrogroups=null)}if(l!==null||u!==void 0){var C=[];if(u!==void 0)for(_ of u)_.f&8192||C.push(_);for(;l!==null;)!(l.f&8192)&&l!==e.fallback&&C.push(l),l=Nr(l.next);var ne=C.length;if(ne>0){var re=i&4&&s===0?n:null;if(o){for(v=0;v<ne;v+=1)C[v].nodes?.a?.measure();for(v=0;v<ne;v+=1)C[v].nodes?.a?.fix()}kr(e,C,re)}}o&&Ke(()=>{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function Fr(e,t,n,r,i,a,o,s){var c=o&1?o&16?Rt(n):zt(n,!1,!1):null,l=o&2?Rt(i):null;return{v:c,i:l,e:gn(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function Ir(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=Xt(r);if(a.before(r),r===i)return;r=o}}function Lr(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function Rr(e,t,...n){var r=new Dr(e);hn(()=>{let e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},x)}var zr=[...`
|
|
2
|
-
\r\f\xA0\v`];function Br(e,t,n){var r=e==null?``:``+e;if(t&&(r=r?r+` `+t:t),n){for(var i of Object.keys(n))if(n[i])r=r?r+` `+i:i;else if(r.length)for(var a=i.length,o=0;(o=r.indexOf(i,o))>=0;){var s=o+a;(o===0||zr.includes(r[o-1]))&&(s===r.length||zr.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function Vr(e,t=!1){var n=t?` !important;`:`;`,r=``;for(var i of Object.keys(e)){var a=e[i];a!=null&&a!==``&&(r+=` `+i+`: `+a+n)}return r}function Hr(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function Ur(e,t){if(t){var n=``,r,i;if(Array.isArray(t)?(r=t[0],i=t[1]):r=t,e){e=String(e).replaceAll(/\/\*.*?\*\//g,``).trim();var a=!1,o=0,s=!1,c=[];r&&c.push(...Object.keys(r).map(Hr)),i&&c.push(...Object.keys(i).map(Hr));var l=0,u=-1;let t=e.length;for(var d=0;d<t;d++){var f=e[d];if(s?f===`/`&&e[d-1]===`*`&&(s=!1):a?a===f&&(a=!1):f===`/`&&e[d+1]===`*`?s=!0:f===`"`||f===`'`?a=f:f===`(`?o++:f===`)`&&o--,!s&&a===!1&&o===0){if(f===`:`&&u===-1)u=d;else if(f===`;`||d===t-1){if(u!==-1){var p=Hr(e.substring(l,u).trim());if(!c.includes(p)){f!==`;`&&d++;var m=e.substring(l,d).trim();n+=` `+m+`;`}}l=d+1,u=-1}}}}return r&&(n+=Vr(r)),i&&(n+=Vr(i,!0)),n=n.trim(),n===``?null:n}return e==null?null:String(e)}function Wr(e,t,n,r,i,a){var o=e[le];if(T||o!==n||o===void 0){var s=Br(n,r,a);(!T||s!==e.getAttribute(`class`))&&(s==null?e.removeAttribute(`class`):t?e.className=s:e.setAttribute(`class`,s)),e[le]=n}else if(a&&i!==a)for(var c in a){var l=!!a[c];(i==null||l!==!!i[c])&&e.classList.toggle(c,l)}return a}function Gr(e,t={},n,r){for(var i in n){var a=n[i];t[i]!==a&&(n[i]==null?e.style.removeProperty(i):e.style.setProperty(i,a,r))}}function Kr(e,t,n,r){var i=e[ue];if(T||i!==t){var a=Ur(t,r);(!T||a!==e.getAttribute(`style`))&&(a==null?e.removeAttribute(`style`):e.style.cssText=a),e[ue]=t}else r&&(Array.isArray(r)?(Gr(e,n?.[0],r[0]),Gr(e,n?.[1],r[1],`important`)):Gr(e,n,r));return r}var qr=Symbol(`is custom element`),Jr=Symbol(`is html`),Yr=me?`link`:`LINK`;function Xr(e){if(T){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;Q(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;Q(e,`checked`,null),e.checked=r}}};e[fe]=n,Ke(n),tt()}}function Zr(e,t){var n=Qr(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=Qr(e);T&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===Yr)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[se]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&ei(e).has(t)?e[t]=n:e.setAttribute(t,n))}function Qr(e){return e[ce]??={[qr]:e.nodeName.includes(`-`),[Jr]:e.namespaceURI===ge}}var $r=new Map;function ei(e){var t=e.getAttribute(`is`)||e.nodeName,n=$r.get(t);if(n)return n;$r.set(t,n=new Set);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.add(s);i=l(i)}return n}function ti(e,t,n=t){var r=new WeakSet;rt(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=ni(e)?ri(a):a,n(a),M!==null&&r.add(M),await Xn(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(T&&e.defaultValue!==e.value||$n(t)==null&&e.value)&&(n(ni(e)?ri(e.value):e.value),M!==null&&r.add(M)),mn(()=>{var n=t();if(e===document.activeElement){var i=M;if(r.has(i))return}ni(e)&&n===ri(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}function ni(e){var t=e.type;return t===`number`||t===`range`}function ri(e){return e===``?null:+e}function ii(e){k===null&&Oe(`onMount`),un(()=>{let t=$n(e);if(typeof t==`function`)return t})}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);var ai=gr(`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3.4 8.4 3 3 6.2-6.8"></path></svg>`),oi=gr(`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M8 4v5"></path><path d="M8 12h.01"></path></svg>`),si=gr(`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"></path></svg>`),ci=J(`<span class="fix svelte-1grjtup"> </span>`),li=J(`<li class="svelte-1grjtup"><span class="mark svelte-1grjtup" aria-hidden="true"><!></span> <span class="body svelte-1grjtup"><b class="svelte-1grjtup"> </b> <span class="msg svelte-1grjtup"> </span> <!></span> <span class="sr svelte-1grjtup"> </span></li>`),ui=J(`<section class="health svelte-1grjtup" aria-label="Health"><header class="svelte-1grjtup"><h2 class="svelte-1grjtup"> </h2> <p class="svelte-1grjtup">This is the same check <code>npx verbaly doctor</code> runs, read out loud. It looks at your
|
|
3
|
-
settings, your catalogs and the way your build is wired, and it never changes anything.</p> <button class="close svelte-1grjtup">Back to the messages</button></header> <ul class="svelte-1grjtup"></ul></section>`);function di(e,t){Be(t,!0);let n={config:`Your settings`,cli:`The verbaly command`,catalogs:`Your catalogs`,routing:`Where the language lives in your urls`,plugin:`The piece that wires your build`,types:`The generated types`,sources:`Reading your code`,orphans:`Keys nothing in your code uses`,bundle:`What the browser downloads`,translations:`The translations themselves`},r=j(()=>t.entries.filter(e=>e.level!==`ok`).length);var i=ui(),a=L(i),o=L(a),s=R(o,!0),c=z(o,4);O(a);var l=z(a,2);Mr(l,21,()=>t.entries,Or,(e,t)=>{var r=li(),i=L(r),a=L(i),o=e=>{Y(e,ai())},s=e=>{Y(e,oi())},c=e=>{Y(e,si())};Z(a,e=>{K(t).level===`ok`?e(o):K(t).level===`warn`?e(s,1):e(c,-1)}),O(i);var l=z(i,2),u=L(l),d=R(u,!0),f=z(u,2),p=R(f,!0),m=z(f,2),h=e=>{var n=ci(),r=R(n,!0);B(()=>X(r,K(t).fix)),Y(e,n)};Z(m,e=>{K(t).fix&&e(h)}),O(l);var g=R(z(l,2),!0);O(r),B(()=>{Q(r,`data-level`,K(t).level),X(d,n[K(t).check]??K(t).check),X(p,K(t).message),X(g,K(t).level)}),Y(e,r)}),O(l),O(i),B(()=>X(s,t.ok?`Nothing is broken`:`${K(r)} of ${t.entries.length} need you`)),q(`click`,c,function(...e){t.onClose?.apply(this,e)}),Y(e,i),Ve()}sr([`click`]);var fi={done:{short:`ready`,long:`ready`},draft:{short:`unread`,long:`written by a machine, nobody has read it`},missing:{short:`missing`,long:`missing, so your visitor sees the source language`},broken:{short:`breaks`,long:`breaks your site`}},pi={all:`everything`,missing:`missing`,draft:`unread`,broken:`breaks your site`,look:`worth a look`},mi={divergent:`the source says this two ways`,collision:`came back as two translations`,echo:`still identical to the source`,digits:`the numbers moved`,url:`a link changed`,code:`a code span changed`},hi=`Undo`,$={find:`Find new text`,findWhy:`Reads your code and adds what your catalogs do not have yet.`,translate:`Translate what is missing`,translateWhy:`Calls your provider, so it costs money and takes minutes.`,cancel:`Not now`,working:`Reading your code`,running:`Translating`,nothingNew:`Nothing new: your catalogs already have every message your code uses.`,nothingMissing:`Nothing missing in the languages you ticked.`,pickFirst:`Tick a language to translate it.`,onlyLocale:`This project has one language, so there is nothing to translate into.`,scanOff:`Source scanning is off in your config, so there is nothing to read.`},gi={noCatalogs:`No messages yet. Studio reads the catalogs in your project, and there are none here.`,oneLocale:`One language is all you have, so there is nothing to compare it against yet.`,oneLocaleFix:`Add another one to your config and it shows up in the rail.`,pickOne:`Tick a language in the rail to see its translations.`,noMatch:`Nothing matches. Every message here is in the state you asked for.`};function _i(e){return`${e} ${e===1?`message`:`messages`}`}var vi={broken:{one:`translation breaks your site`,many:`translations break your site`},missing:{one:`message is missing`,many:`messages are missing`},draft:{one:`translation nobody has read`,many:`translations nobody has read`},undefined:{one:`key your code calls has no message`,many:`keys your code calls have no message`}},yi={broken:`It lost a parameter or a tag, so the sentence would ship incomplete.`,missing:`Your visitor sees the source language until one is written.`,draft:`A machine wrote it and nobody has looked. It is already on your site.`,undefined:`Nothing defines it, so the build fails and the raw key would reach your page.`},bi={here:`Overview`,clear:`Nothing is waiting for you.`,clearWhy:`Every language is complete and the build passes.`,project:`Project`,healthy:`Healthy`,problems:`Needs a look`,checks:`checks`,history:`Last changes to your catalogs`,noHistory:`No git history for your catalog directory.`,countMessages:`Messages`,countLocales:`Languages`,open:`Open`},xi=J(`<span> </span>`),Si=J(`<li><button><span> </span> <!></button></li>`),Ci=J(`<button class="read svelte-l3e5c7"> <span class="n svelte-l3e5c7"> </span></button>`),wi=J(`<li><label><input type="checkbox" class="svelte-l3e5c7"/> <span class="meta svelte-l3e5c7"><span class="name svelte-l3e5c7"> </span> <span class="state svelte-l3e5c7"> </span></span></label> <!></li>`),Ti=J(`<p class="undo svelte-l3e5c7"><span> </span> <button class="svelte-l3e5c7"> </button></p>`),Ei=J(`<li><button type="button"><span> </span> <span class="count svelte-l3e5c7"> </span></button></li>`),Di=J(`<nav class="rail svelte-l3e5c7" aria-label="Languages and filters"><ul class="views svelte-l3e5c7"></ul> <!> <h2 class="cap svelte-l3e5c7">Languages</h2> <ul class="langs svelte-l3e5c7"></ul> <!> <h2 class="cap svelte-l3e5c7">Show</h2> <ul class="filters svelte-l3e5c7"></ul></nav>`);function Oi(e,t){Be(t,!0);let n=[{id:`overview`,label:`Overview`},{id:`messages`,label:`Messages`},{id:`health`,label:`Health`}],r=[`all`,`look`,`missing`,`draft`,`broken`];function i(e){return e.source?`the one you write`:e.broken?`${e.broken} breaks your site`:e.missing?`${e.missing} missing`:e.draft?`${e.draft} nobody has read`:`all read`}function a(e){return e.source?`done`:e.broken?`broken`:e.missing?`missing`:e.draft?`draft`:`done`}var o=Di(),s=L(o);Mr(s,21,()=>n,e=>e.id,(e,n)=>{var r=Si(),i=L(r);let a;var o=L(i),s=R(o,!0),c=z(o,2),l=e=>{var n=xi();let r;var i=R(n,!0);B(()=>{r=Wr(n,1,`bad svelte-l3e5c7`,null,r,{clean:!t.checks.bad}),X(i,t.checks.bad||`ok`)}),Y(e,n)};Z(c,e=>{K(n).id===`health`&&t.checks&&e(l)}),O(i),O(r),B(()=>{a=Wr(i,1,`nav svelte-l3e5c7`,null,a,{on:t.view===K(n).id}),Q(i,`aria-current`,t.view===K(n).id?`page`:void 0),X(s,K(n).label)}),q(`click`,i,()=>t.onView(K(n).id)),Y(e,r)}),O(s);var c=z(s,2);Rr(c,()=>t.actions);var l=z(c,4);Mr(l,21,()=>t.health,e=>e.locale,(e,n)=>{var r=wi(),o=L(r);let s;var c=L(o);Xr(c);var l=z(c,2),u=L(l),d=R(u,!0),f=z(u,2),p=R(f,!0);O(l),O(o);var m=z(o,2),h=e=>{var r=Ci(),i=L(r),a=R(z(i),!0);O(r),B(()=>{X(i,`Mark as read `),X(a,K(n).draft)}),q(`click`,r,()=>t.onRead(K(n).locale)),Y(e,r)};Z(m,e=>{!K(n).source&&K(n).draft>0&&e(h)}),O(r),B((e,t,r)=>{s=Wr(o,1,`lang svelte-l3e5c7`,null,s,{source:K(n).source}),Zr(c,e),c.disabled=K(n).source,X(d,K(n).locale),Q(f,`data-state`,t),X(p,r)},[()=>t.shown.includes(K(n).locale),()=>a(K(n)),()=>i(K(n))]),q(`change`,c,()=>t.onToggle(K(n).locale)),Y(e,r)}),O(l);var u=z(l,2),d=e=>{var n=Ti(),r=L(n),i=R(r),a=z(r,2),o=R(a,!0);O(n),B(()=>{X(i,`${t.pending.keys.length??``} in ${t.pending.locale??``} marked as read`),X(o,hi)}),q(`click`,a,function(...e){t.onUndo?.apply(this,e)}),Y(e,n)};Z(u,e=>{t.pending&&e(d)});var f=z(u,4);Mr(f,20,()=>r,e=>e,(e,n)=>{var r=Ei(),i=L(r);let a;var o=L(i),s=R(o,!0),c=R(z(o,2),!0);O(i),O(r),B(()=>{a=Wr(i,1,`svelte-l3e5c7`,null,a,{on:t.state===n}),X(s,pi[n]),X(c,t.counts[n]??0)}),q(`click`,i,()=>t.onState(n)),Y(e,r)}),O(f),O(o),Y(e,o),Ve()}sr([`click`,`change`]);var ki=gr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true"><path d="M5 11h12" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></svg>`),Ai=gr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true" fill="none"><path d="M6 12.5 11 7l5 5.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11 8v7" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"></path></svg>`),ji=gr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true" fill="none"><path d="M4.5 12.5c1.6-2.2 3.2-2.2 4.8 0s3.2 2.2 4.8 0 3.2-2.2 4.8 0" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"></path></svg>`),Mi=gr(`<svg viewBox="0 0 22 22" width="15" height="15" aria-hidden="true"><path d="M11 6v6.4" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path><circle cx="11" cy="16" r="1.2" fill="currentColor"></circle></svg>`),Ni=J(`<!> <span class="sr svelte-1fu82r1"> </span>`,1);function Pi(e,t){let n={done:`translated`,draft:`written by a machine`,missing:`not translated, shows in your source language`,broken:`breaks your site`};var r=Ni(),i=Zt(r),a=e=>{Y(e,ki())},o=e=>{Y(e,Ai())},s=e=>{Y(e,ji())},c=e=>{Y(e,Mi())};Z(i,e=>{t.state===`done`?e(a):t.state===`missing`?e(o,1):t.state===`draft`?e(s,2):e(c,-1)});var l=R(z(i,2),!0);B(()=>X(l,n[t.state])),Y(e,r)}var Fi=new Set;function Ii(e){Fi.has(e)||(Fi.add(e),console.warn(`[verbaly] ${e}`))}var Li=/\{\s*[a-zA-Z0-9_]+\s*,\s*(?:plural|selectordinal|select|number|date|time)\b/;function Ri(e){return Li.test(e)}function zi(e){let t=0,n=()=>e.charAt(t),r=()=>{for(;t<e.length&&/\s/.test(n());)t++},i=()=>{let r=``;for(;t<e.length&&/[a-zA-Z0-9_]/.test(n());)r+=e[t++];return r};function a(r){let i=[],a=``,c=()=>{a&&i.push({kind:`text`,value:a}),a=``};for(;t<e.length;){let e=n();if(e===`}`)break;e===`{`?(c(),i.push(s())):e===`#`&&r?(c(),i.push({kind:`hash`}),t++):e===`'`?a+=o():(a+=e,t++)}return c(),i}function o(){if(t++,n()===`'`)return t++,`'`;let r=n();if(r!==`{`&&r!==`}`&&r!==`#`)return`'`;let i=``;for(;t<e.length;){if(n()===`'`){if(e.charAt(t+1)===`'`){i+=`'`,t+=2;continue}return t++,i}i+=e[t++]}return i}function s(){t++,r();let o=i();if(r(),n()===`}`)return t++,{kind:`param`,name:o};n()===`,`&&t++,r();let s=i(),u={kind:`param`,name:o};if(s===`number`||s===`date`||s===`time`){r();let i=``;if(n()===`,`){for(t++,r();t<e.length&&n()!==`}`&&n()!==`,`;)i+=e[t++];i=i.trim()}return s===`number`?u.format=i===`integer`||i===`percent`||i===`currency`?i:`number`:(u.format=s,i&&(u.arg=i)),l(),u}if(s===`plural`||s===`selectordinal`||s===`select`){s===`selectordinal`&&(u.ordinal=!0);let i=[];if(r(),n()===`,`&&t++,r(),s!==`select`&&e.startsWith(`offset:`,t)){for(t+=7,r();t<e.length&&/[0-9]/.test(n());)t++;r()}for(;t<e.length&&n()!==`}`;){let e=c();if(r(),n()!==`{`)break;t++;let o=a(s!==`select`);n()===`}`&&t++,i.push([e,o]),r()}return n()===`}`&&t++,u.variants=i,u}return l(),u}function c(){if(n()===`=`){let r=`=`;for(t++;t<e.length&&/[0-9]/.test(n());)r+=e[t++];return r}let r=``;for(;t<e.length&&!/[\s{]/.test(n());)r+=e[t++];return r}function l(){for(;t<e.length&&n()!==`}`;)t++;n()===`}`&&t++}return a(!1)}var Bi=new Map,Vi=5e3;function Hi(e,t){let n=Bi.get(e);if(!n){if(Ri(e)){if(!t)return Ui(e);n=t(e)}else n=Wi(e,!1);Bi.size>=Vi&&Bi.delete(Bi.keys().next().value),Bi.set(e,n)}return n}function Ui(e){return Ii(`a message uses ICU syntax but no ICU parser is loaded: pass icu to createVerbaly (the compiler wires it when a catalog needs it, so this means it arrived after the build)`),[{kind:`text`,value:e}]}function Wi(e,t){let n=[],r=``,i=0,a=()=>{r&&n.push({kind:`text`,value:r}),r=``};for(;i<e.length;){let o=e[i];if(o===`{`){if(e[i+1]===`{`){r+=`{`,i+=2;continue}let t=Gi(e,i);if(t<0){r+=e.slice(i);break}a(),n.push(Ki(e.slice(i+1,t))),i=t+1}else o===`}`&&e[i+1]===`}`?(r+=`}`,i+=2):t&&o===`#`?e[i+1]===`#`?(r+=`#`,i+=2):(a(),n.push({kind:`hash`}),i+=1):(r+=o,i+=1)}return a(),n}function Gi(e,t){let n=0,r=t;for(;r<e.length;){let t=e[r];if(t===`{`){if(e[r+1]===`{`){r+=2;continue}n+=1}else if(t===`}`){if(e[r+1]===`}`){r+=2;continue}if(--n,n===0)return r}r+=1}return-1}function Ki(e){let t=qi(e),n=(t[0]??``).trim();if(!n)return{kind:`text`,value:`{${e}}`};let r=n.indexOf(`:`),i=(r<0?n:n.slice(0,r)).trim();if(!i)return{kind:`text`,value:`{${e}}`};let a={kind:`param`,name:i};if(r>=0){let e=n.slice(r+1).trim(),t=e.indexOf(`/`);a.format=(t<0?e:e.slice(0,t)).trim(),t>=0&&(a.arg=e.slice(t+1).trim())}if(t.length>1){a.variants=[];for(let e of t.slice(1)){let t=e.indexOf(`:`);if(t<0)continue;let n=e.slice(0,t).trim(),r=e.slice(t+1).trim();n&&a.variants.push([n,Wi(r,!0)])}}return a}function qi(e){let t=[],n=``,r=0,i=0;for(;i<e.length;){let a=e[i];if(a===`{`){if(e[i+1]===`{`){n+=`{{`,i+=2;continue}r+=1,n+=a}else if(a===`}`){if(e[i+1]===`}`){n+=`}}`,i+=2;continue}--r,n+=a}else if(a===`|`&&r===0){if(e[i+1]===`|`){n+=`|`,i+=2;continue}t.push(n),n=``}else n+=a;i+=1}return t.push(n),t}var Ji=/<(\/?)([a-zA-Z][\w-]*)(\/?)>/g,Yi=/&(?:(lt|gt|amp)|#(\d+)|#[xX]([0-9a-fA-F]+));/g,Xi={lt:`<`,gt:`>`,amp:`&`},Zi=e=>e.replace(Yi,(e,t,n,r)=>{if(t)return Xi[t];let i=n?parseInt(n,10):parseInt(r,16);return i<=1114111?String.fromCodePoint(i):e});function Qi(e){Ji.lastIndex=0;let t=[],n=[],r=()=>n.length?n[n.length-1].children:t,i=e=>{e&&r().push(Zi(e))},a=0,o;for(;(o=Ji.exec(e))!==null;){let[t,s,c,l]=o;if(i(e.slice(a,o.index)),a=o.index+t.length,l)r().push({name:c,children:[]});else if(s){if(n.length&&n[n.length-1].name===c){let e=n.pop();r().push(e)}else i(t)}else n.push({name:c,children:[]})}for(i(e.slice(a));n.length;){let e=n.pop();r().push(...e.children)}return t}function $i(e,t){for(let n of e)if(n.kind===`param`&&n.name){t.has(n.name)||t.set(n.name,new Set);for(let[e,r]of n.variants??[])t.get(n.name).add(e),$i(r,t)}}function ea(e){let t=new Map;try{$i(Hi(e,zi),t)}catch{}return t}function ta(e,t){for(let n of e)typeof n!=`string`&&(t.push(n.name),ta(n.children,t))}function na(e){let t=[];try{ta(Qi(e),t)}catch{return t}return t}function ra(e){let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);return t}var ia=e=>e.length===1?e[0]:`${e.slice(0,-1).join(`, `)} and ${e.at(-1)}`;function aa(e,t){let n=ea(e),r=ea(t),i=[...new Set([...n.keys(),...r.keys()])].sort().map(e=>({name:e,inSource:n.has(e),inTarget:r.has(e)})),a=[],o=i.filter(e=>e.inSource&&!e.inTarget).map(e=>`{${e.name}}`),s=i.filter(e=>!e.inSource&&e.inTarget).map(e=>`{${e.name}}`);o.length&&a.push(`${ia(o)} is missing, so its value never reaches the text`),s.length&&a.push(`${ia(s)} is not in the source, so it renders as literal text`);for(let[e,t]of r)t.size&&!t.has(`other`)&&a.push(`the block for {${e}} has no "other" case, so some counts render empty`);let c=ra(na(e)),l=ra(na(t));for(let[e,t]of c)(l.get(e)??0)<t&&a.push(`<${e}> is missing from the translation`);for(let[e,t]of l)(c.get(e)??0)<t&&a.push(`<${e}> is not in the source message`);return{params:i,problems:a}}var oa=J(`<span> </span>`),sa=J(`<span class="vmsg svelte-2clsr"> </span>`),ca=J(`<span class="tl edit svelte-2clsr"><span class="disc svelte-2clsr"> </span> <textarea class="tf svelte-2clsr" rows="2"></textarea></span> <span class="editbar svelte-2clsr"><!> <!> <!> <button class="btn sm svelte-2clsr"> </button> <button class="btn sm quiet svelte-2clsr">Cancel</button> <span class="keys svelte-2clsr">Enter saves · Esc closes</span></span>`,1),la=J(`<button class="tv svelte-2clsr"> </button>`),ua=J(`<button class="tv none svelte-2clsr"> </button>`),da=J(`<span class="sig svelte-2clsr"> </span>`),fa=J(`<span class="tl svelte-2clsr"><span class="disc svelte-2clsr"> </span> <!> <!></span>`),pa=J(`<article><span class="tile svelte-2clsr"><!></span> <span class="row-t svelte-2clsr"><span class="src svelte-2clsr"> </span> <!></span></article>`);function ma(e,t){Be(t,!0);let n=j(()=>t.row.cells.filter(e=>t.shown.includes(e.locale))),r=j(()=>[`broken`,`missing`,`draft`,`done`].find(e=>K(n).some(t=>t.state===e))??`done`),i=N(``),a=N(!1),o=N(null),s=j(()=>aa(t.row.source,K(i))),c=e=>`${e.locale} ${t.row.key}`;function l(e){P(i,e.text,!0),P(o,null),t.onEdit(c(e))}async function u(e){K(a)||(P(a,!0),P(o,await t.onSave(e.locale,t.row.key,K(i)),!0),P(a,!1),K(o)||t.onEdit(null))}function d(e,n){e.key===`Escape`&&t.onEdit(null),e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),u(n))}var f=pa();let p;var m=L(f);Pi(L(m),{get state(){return K(r)}}),O(m);var h=z(m,2),g=L(h),_=R(g,!0);Mr(z(g,2),17,()=>K(n),e=>e.locale,(e,n)=>{var r=vr(),f=Zt(r),p=e=>{var r=ca(),c=Zt(r),l=L(c),f=R(l,!0),p=z(l,2);$e(p),Qe(p,!0),O(c);var m=z(c,2),h=L(m);Mr(h,17,()=>K(s).params,e=>e.name,(e,t)=>{var n=oa();let r;var i=R(n);B(()=>{r=Wr(n,1,`pm svelte-2clsr`,null,r,{gone:K(t).inSource&&!K(t).inTarget}),X(i,`${K(t).inSource&&!K(t).inTarget?`+`:``}{${K(t).name??``}}`)}),Y(e,n)});var g=z(h,2);Mr(g,16,()=>K(s).problems,e=>e,(e,t)=>{var n=sa(),r=R(n,!0);B(()=>X(r,t)),Y(e,n)});var _=z(g,2),v=e=>{var t=sa(),n=R(t,!0);B(()=>X(n,K(o))),Y(e,t)};Z(_,e=>{K(o)&&!K(s).problems.length&&e(v)});var y=z(_,2),b=R(y,!0),x=z(y,2);Se(2),O(m),B(()=>{Q(l,`data-state`,K(n).state),X(f,K(n).locale),Q(p,`aria-label`,`Translation for ${K(n).locale??``}`),y.disabled=K(a),X(b,K(a)?`Saving`:`Save`)}),q(`keydown`,p,e=>d(e,K(n))),ti(p,()=>K(i),e=>P(i,e)),q(`click`,y,()=>u(K(n))),q(`click`,x,()=>t.onEdit(null)),Y(e,r)},m=j(()=>t.editing===c(K(n))),h=e=>{var t=fa(),r=L(t),i=R(r,!0),a=z(r,2),o=e=>{var t=la(),r=R(t,!0);B(()=>{Q(t,`title`,K(n).text),X(r,K(n).text)}),q(`click`,t,()=>l(K(n))),Y(e,t)},s=e=>{var t=ua(),r=R(t,!0);B(()=>X(r,fi.missing.long)),q(`click`,t,()=>l(K(n))),Y(e,t)};Z(a,e=>{K(n).text?e(o):e(s,-1)}),Mr(z(a,2),16,()=>K(n).signals,e=>e,(e,t)=>{var n=da(),r=R(n,!0);B(()=>{Q(n,`title`,mi[t]??t),X(r,mi[t]??t)}),Y(e,n)}),O(t),B(()=>{Q(r,`data-state`,K(n).state),X(i,K(n).locale)}),Y(e,t)};Z(f,e=>{K(m)?e(p):e(h,-1)}),Y(e,r)}),O(h),O(f),B(e=>{p=Wr(f,1,`row svelte-2clsr`,null,p,{open:e}),Q(f,`data-worst`,K(r)),Q(m,`data-state`,K(r)),X(_,t.row.source)},[()=>K(n).some(e=>t.editing===c(e))]),Y(e,f),Ve()}sr([`keydown`,`click`]);function ha(e,t=``,n={}){for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;typeof i==`string`?n[e]=i:i&&typeof i==`object`&&!Array.isArray(i)&&ha(i,e,n)}return n}function ga(e){let t={};for(let n of e.locales)t[n]=ha(e.catalogs[n]??{});let n=new Map;for(let t of e.check.broken)t.severity===`error`&&n.set(`${t.locale}\u0000${t.key}`,t.issue);let r=new Map;for(let[t,n]of Object.entries(e.drafts))r.set(t,new Set(n));let i=t[e.sourceLocale]??{},a=e.locales.filter(t=>t!==e.sourceLocale),o=Object.keys(i).map(o=>({key:o,source:i[o]??``,origins:e.origins[o]??[],cells:a.map(i=>{let a=t[i]?.[o]??``,s=n.get(`${i}\u0000${o}`);return{locale:i,text:a,state:s?`broken`:a?r.get(i)?.has(o)?`draft`:`done`:`missing`,issue:s,signals:(e.triage?.[i]?.[o]??[]).map(e=>e.signal)}})}));return{root:e.root,scanning:e.scanning,sourceLocale:e.sourceLocale,locales:e.locales,rows:o,undefined:e.check.unknown??[],problems:e.problems}}function _a(e){return e.locales.map(t=>{let n=e.rows.length;if(t===e.sourceLocale)return{locale:t,source:!0,total:n,done:n,draft:0,missing:0,broken:0};let r={done:0,draft:0,missing:0,broken:0};for(let n of e.rows){let e=n.cells.find(e=>e.locale===t);e&&r[e.state]++}return{locale:t,source:!1,total:n,...r}})}function va(e,t){Object.assign(e,ga(t))}function ya(e,t,n){return e.rows.length?e.locales.length<2?`oneLocale`:t.length?n.length?null:`noMatch`:`pickOne`:`noCatalogs`}function ba(e,t){let n=t.text.trim().toLowerCase(),r=new Set(t.locales);return e.filter(e=>{let i=e.cells.filter(e=>r.has(e.locale));return t.state===`look`&&!i.some(e=>e.signals.length)||t.state!==`all`&&t.state!==`look`&&!i.some(e=>e.state===t.state)?!1:!n||e.source.toLowerCase().includes(n)?!0:i.some(e=>e.text.toLowerCase().includes(n))})}var xa=J(`<div class="bill svelte-a18sfu"><p class="lede svelte-a18sfu"> </p> <p class="why svelte-a18sfu"> </p> <div class="pair svelte-a18sfu"><button class="go svelte-a18sfu"> </button> <button class="plain svelte-a18sfu"> </button></div></div>`),Sa=J(`<div class="bill svelte-a18sfu"><p class="lede svelte-a18sfu"> </p> <div class="track svelte-a18sfu"><span class="fill svelte-a18sfu"></span></div> <p class="why svelte-a18sfu"> </p></div>`),Ca=J(`<button class="act svelte-a18sfu"><span class="name svelte-a18sfu"> </span> <span class="why svelte-a18sfu"> </span></button> <button class="act svelte-a18sfu"><span class="name svelte-a18sfu"> </span> <span class="why svelte-a18sfu"> </span></button>`,1),wa=J(`<p> </p>`),Ta=J(`<section class="acts svelte-a18sfu" aria-label="Commands"><h2 class="cap svelte-a18sfu">Commands</h2> <!> <!></section>`);function Ea(e,t){Be(t,!0);let n=N(Wt({at:`idle`})),r=j(()=>K(n).at===`finding`||K(n).at===`planning`||K(n).at===`running`);function i(e,t=!1){P(n,{at:`said`,text:e,bad:t},!0)}async function a(){P(n,{at:`finding`},!0);let e=await t.api.extract();if(e.error||!e.value)return i(e.error??`no answer`,!0);let{found:r}=e.value;if(!r)return i($.nothingNew);let a=`${_i(r)} your code uses and your catalogs did not have`;await t.onDone(a),i(a)}async function o(){P(n,{at:`planning`},!0);let e=await t.api.plan(t.shown);if(e.error||!e.value)return i(e.error??`no answer`,!0);if(!e.value.total)return i($.nothingMissing);P(n,{at:`plan`,plan:e.value},!0)}async function s(e){let r=await t.api.job(e);if(r.error||!r.value)return i(r.error??`no answer`,!0);let a=r.value;if(a.state===`running`){P(n,{at:`running`,job:a},!0);return}let o=`${_i(a.done)} translated, unread until you read them`;await t.onDone(o),i(a.state===`failed`?a.message??`the run failed`:o,a.state===`failed`)}async function c(){let e=await t.api.translate(t.shown);if(e.error||!e.value)return i(e.error??`no answer`,!0);P(n,{at:`running`,job:e.value},!0)}ii(()=>{t.api.job().then(e=>{e.value&&K(n).at===`idle`&&P(n,{at:`running`,job:e.value},!0)})}),un(()=>{if(K(n).at!==`running`)return;let e=K(n).job.id,t=setInterval(()=>void s(e),1e3);return()=>clearInterval(t)});let l=j(()=>t.targets?t.shown.length?$.translateWhy:$.pickFirst:$.onlyLocale),u=j(()=>K(n).at===`running`&&K(n).job.total?K(n).job.done/K(n).job.total:0);var d=Ta(),f=z(L(d),2),p=e=>{var t=xa(),r=L(t),i=R(r),a=z(r,2),o=R(a,!0),s=z(a,2),l=L(s),u=R(l,!0),d=z(l,2),f=R(d,!0);O(s),O(t),B((e,t)=>{X(i,`${e??``} in ${t??``}`),X(o,$.translateWhy),X(u,$.translate),X(f,$.cancel)},[()=>_i(K(n).plan.total),()=>Object.keys(K(n).plan.pending).join(`, `)]),q(`click`,l,c),q(`click`,d,()=>P(n,{at:`idle`},!0)),Y(e,t)},m=e=>{var t=Sa(),r=L(t),i=R(r),a=z(r,2),o=R(a),s=R(z(a,2));O(t),B(e=>{X(i,`${$.running??``} ${K(n).job.locale??``??``}`),Kr(o,`width: ${e??``}%`),X(s,`${K(n).job.done??``} of ${K(n).job.total??``}`)},[()=>Math.round(K(u)*100)]),Y(e,t)},h=e=>{var i=Ca(),s=Zt(i),c=L(s),u=R(c,!0),d=R(z(c,2),!0);O(s);var f=z(s,2),p=L(f),m=R(p,!0),h=R(z(p,2),!0);O(f),B(()=>{s.disabled=K(r)||!t.scanning,X(u,K(n).at===`finding`?$.working:$.find),X(d,t.scanning?$.findWhy:$.scanOff),f.disabled=K(r)||!t.shown.length,X(m,$.translate),X(h,K(l))}),q(`click`,s,a),q(`click`,f,o),Y(e,i)};Z(f,e=>{K(n).at===`plan`?e(p):K(n).at===`running`?e(m,1):e(h,-1)});var g=z(f,2),_=e=>{var t=wa();let r;var i=R(t,!0);B(()=>{r=Wr(t,1,`said svelte-a18sfu`,null,r,{bad:K(n).bad}),X(i,K(n).text)}),Y(e,t)};Z(g,e=>{K(n).at===`said`&&e(_)}),O(d),Y(e,d),Ve()}sr([`click`]);var Da=J(`<h2 class="svelte-1qmtve8"> </h2>`),Oa=J(`<h2 class="svelte-1qmtve8"> </h2> <p class="svelte-1qmtve8"> </p>`,1),ka=J(`<code class="keys svelte-1qmtve8"> </code>`),Aa=J(`<button class="svelte-1qmtve8"> </button>`),ja=J(`<div class="job svelte-1qmtve8"><span class="tile svelte-1qmtve8"><!></span> <span class="what svelte-1qmtve8"><b class="svelte-1qmtve8"> </b> <span class="svelte-1qmtve8"> </span> <!></span> <!></div>`),Ma=J(`<p class="empty svelte-1qmtve8">…</p>`),Na=J(`<p class="empty svelte-1qmtve8"> </p>`),Pa=J(`<p class="commit svelte-1qmtve8"><code class="svelte-1qmtve8"> </code> <span class="svelte-1qmtve8"><b class="svelte-1qmtve8"> </b><span class="svelte-1qmtve8"> </span></span></p>`),Fa=J(`<main class="overview svelte-1qmtve8"><header class="svelte-1qmtve8"><span class="chip svelte-1qmtve8"> </span> <!></header> <div class="cols svelte-1qmtve8"><section class="jobs svelte-1qmtve8" aria-label="What needs you"></section> <aside class="side svelte-1qmtve8"><div class="card svelte-1qmtve8"><button class="ring svelte-1qmtve8"><b class="svelte-1qmtve8"> </b> <strong class="svelte-1qmtve8"> </strong> <span class="svelte-1qmtve8"> </span></button> <p class="kv svelte-1qmtve8"><b class="svelte-1qmtve8"> </b><strong class="svelte-1qmtve8"> </strong></p> <p class="kv svelte-1qmtve8"><b class="svelte-1qmtve8"> </b><strong class="svelte-1qmtve8"> </strong></p></div> <div class="card svelte-1qmtve8"><p class="head svelte-1qmtve8"> </p> <!></div></aside></div></main>`);function Ia(e,t){Be(t,!0);let n=j(()=>t.health.filter(e=>!e.source)),r=j(()=>{let e=e=>K(n).reduce((t,n)=>t+e(n),0);return[{id:`broken`,n:e(e=>e.broken)},{id:`missing`,n:e(e=>e.missing)},{id:`draft`,n:e(e=>e.draft)},{id:`undefined`,n:t.undefinedKeys.length}].filter(e=>e.n>0)}),i=j(()=>K(r).reduce((e,t)=>e+t.n,0)),a=new Intl.RelativeTimeFormat(void 0,{numeric:`auto`});function o(e){let t=Math.round((Date.parse(e)-Date.now())/864e5);return t>-1?a.format(0,`day`):t>-31?a.format(t,`day`):a.format(Math.round(t/30),`month`)}var s=Fa(),c=L(s),l=L(c),u=R(l,!0),d=z(l,2),f=e=>{var t=Da(),n=R(t);B(()=>X(n,`${K(i)??``} ${K(i)===1?`thing is`:`things are`} waiting for you.`)),Y(e,t)},p=e=>{var t=Oa(),n=Zt(t),r=R(n,!0),i=R(z(n,2),!0);B(()=>{X(r,bi.clear),X(i,bi.clearWhy)}),Y(e,t)};Z(d,e=>{K(i)>0?e(f):e(p,-1)}),O(c);var m=z(c,2),h=L(m);Mr(h,21,()=>K(r),e=>e.id,(e,n)=>{var r=ja(),i=L(r),a=L(i);{let e=j(()=>K(n).id===`undefined`?`broken`:K(n).id);Pi(a,{get state(){return K(e)}})}O(i);var o=z(i,2),s=L(o),c=R(s),l=z(s,2),u=R(l,!0),d=z(l,2),f=e=>{var n=ka(),r=R(n,!0);B(e=>X(r,e),[()=>t.undefinedKeys.slice(0,3).map(e=>e.key).join(` · `)]),Y(e,n)};Z(d,e=>{K(n).id===`undefined`&&e(f)}),O(o);var p=z(o,2),m=e=>{var r=Aa(),i=R(r,!0);B(()=>X(i,bi.open)),q(`click`,r,()=>t.onFilter(K(n).id)),Y(e,r)};Z(p,e=>{K(n).id!==`undefined`&&e(m)}),O(r),B(()=>{Q(i,`data-state`,K(n).id===`undefined`?`broken`:K(n).id),X(c,`${K(n).n??``} ${(K(n).n===1?vi[K(n).id].one:vi[K(n).id].many)??``}`),X(u,yi[K(n).id])}),Y(e,r)}),O(h);var g=z(h,2),_=L(g),v=L(_),y=L(v),b=R(y,!0),x=z(y,2),S=R(x,!0),ee=R(z(x,2),!0);O(v);var te=z(v,2),C=L(te),ne=R(C,!0),re=R(z(C),!0);O(te);var ie=z(te,2),ae=L(ie),oe=R(ae,!0),se=R(z(ae),!0);O(ie),O(_);var ce=z(_,2),le=L(ce),ue=R(le,!0),de=z(le,2),fe=e=>{Y(e,Ma())},pe=e=>{var t=Na(),n=R(t,!0);B(()=>X(n,bi.noHistory)),Y(e,t)},me=e=>{var n=vr();Mr(Zt(n),17,()=>t.commits,e=>e.sha,(e,t)=>{var n=Pa(),r=L(n),i=R(r,!0),a=z(r,2),s=L(a),c=R(s,!0),l=R(z(s));O(a),O(n),B(e=>{X(i,K(t).sha),X(c,K(t).subject),X(l,`${K(t).author??``} · ${e??``}`)},[()=>o(K(t).date)]),Y(e,n)}),Y(e,n)};Z(de,e=>{t.commits===null?e(fe):t.commits.length===0?e(pe,1):e(me,-1)}),O(ce),O(g),O(m),O(s),B(()=>{X(u,bi.here),v.disabled=!t.checks,X(b,bi.project),X(S,t.checks&&t.checks.ok===t.checks.total?bi.healthy:bi.problems),X(ee,t.checks?`${t.checks.ok} of ${t.checks.total} ${bi.checks}`:`…`),X(ne,bi.countMessages),X(re,t.total),X(oe,bi.countLocales),X(se,t.locales.length),X(ue,bi.history)}),q(`click`,v,function(...e){t.onHealth?.apply(this,e)}),Y(e,s),Ve()}sr([`click`]);var La=J(`<li><code> </code> </li>`),Ra=J(`<ul class="problems svelte-1xn7ig5"></ul>`),za=J(`<p class="note svelte-1xn7ig5"> </p>`),Ba=J(`<!> <!>`,1),Va=J(`<main class="table svelte-1xn7ig5"><!></main>`),Ha=J(`Saved in <code> </code>`,1),Ua=J(`<p class="snack svelte-1xn7ig5" role="status"><svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="svelte-1xn7ig5"><path d="m3.4 8.4 3 3 6.2-6.8"></path></svg> <!> <button class="svelte-1xn7ig5">Dismiss</button></p>`),Wa=J(`<div class="shell svelte-1xn7ig5"><header class="bar svelte-1xn7ig5"><span class="brand svelte-1xn7ig5">verbaly <b class="svelte-1xn7ig5">studio</b></span> <input class="search svelte-1xn7ig5" type="search" placeholder="Search the text, not the key" aria-label="Search the text, not the key"/> <span class="root svelte-1xn7ig5"> </span></header> <!> <div class="body svelte-1xn7ig5"><!> <!></div> <!></div>`);function Ga(e,t){Be(t,!0);let n=N(null),r=N(null),i=N(null),a=N(`overview`),o=N(null),s=N(null);function c(e){e===`health`?l():P(a,e,!0)}async function l(){P(a,`health`);let e=await t.api.health();if(e.error){P(r,{text:e.error,file:``},!0);return}e.value&&P(o,e.value,!0)}un(()=>{t.api.health().then(e=>{e.value&&P(o,e.value,!0)}),t.api.history().then(e=>{P(s,e.value?.commits??[],!0)})});function u(e){P(g,K(_),!0),P(m,e,!0),P(a,`messages`)}async function d(e){let a=await t.api.state();if(a.error||!a.value){P(r,{text:a.error??`[verbaly] the server sent no state`,file:``},!0);return}P(n,null),P(i,null),va(t.panel,a.value),P(r,{text:e,file:``},!0);let s=await t.api.health();s.value&&P(o,s.value,!0)}async function f(e,n,a){let o=await t.api.setRead(e,n,a);if(o.error){P(r,{text:o.error,file:``},!0);return}let s=new Set(o.value?.keys??[]);for(let n of t.panel.rows){if(!s.has(n.key))continue;let t=n.cells.find(t=>t.locale===e);t?.text&&(t.state=a?`draft`:`done`)}P(i,a?null:{locale:e,keys:o.value?.keys??[]},!0)}async function p(e,n,i){let a=await t.api.save(e,n,i);if(a.error)return a.error;let o=t.panel.rows.find(e=>e.key===n)?.cells.find(t=>t.locale===e);return o&&(o.text=i,o.state=i?`done`:`missing`,o.issue=void 0),P(r,{text:i,file:`${e}.json`},!0),null}let m=N(`all`),h=N(``),g=N(null),_=j(()=>t.panel.locales.filter(e=>e!==t.panel.sourceLocale)),v=j(()=>K(g)??K(_).slice(0,1)),y=j(()=>_a(t.panel)),b=j(()=>ba(t.panel.rows,{text:K(h),state:K(m),locales:K(v)})),x=j(()=>ya(t.panel,K(v),K(b))),S=j(()=>{let e={all:0,look:0,missing:0,draft:0,broken:0};for(let n of[`all`,`look`,`missing`,`draft`,`broken`])e[n]=ba(t.panel.rows,{text:K(h),state:n,locales:K(v)}).length;return e}),ee=N(60);un(()=>{K(h),K(m),K(v),P(ee,60)});function te(e){let t=e.currentTarget;t.scrollTop+t.clientHeight>t.scrollHeight-600&&K(ee)<K(b).length&&P(ee,K(ee)+60)}function C(e){P(g,K(v).includes(e)?K(v).filter(t=>t!==e):[...K(v),e],!0)}var ne=Wa(),re=L(ne),ie=z(L(re),2);Xr(ie);var ae=z(ie,2),oe=R(ae,!0);O(re);var se=z(re,2),ce=e=>{var n=Ra();Mr(n,21,()=>t.panel.problems,e=>e.scope+e.message,(e,t)=>{var n=La(),r=L(n),i=R(r,!0),a=z(r);O(n),B(()=>{X(i,K(t).scope),X(a,` ${K(t).message??``}`)}),Y(e,n)}),O(n),Y(e,n)};Z(se,e=>{t.panel.problems.length&&e(ce)});var le=z(se,2),ue=L(le);{let e=e=>{Ea(e,{get api(){return t.api},get scanning(){return t.panel.scanning},get targets(){return K(_).length},get shown(){return K(v)},onDone:d})},n=j(()=>K(o)?{bad:K(o).entries.filter(e=>e.level!==`ok`).length}:null);Oi(ue,{get health(){return K(y)},get shown(){return K(v)},get state(){return K(m)},get counts(){return K(S)},get pending(){return K(i)},get checks(){return K(n)},onToggle:C,onState:e=>P(m,e,!0),onRead:e=>f(e,void 0,!1),onUndo:()=>K(i)&&f(K(i).locale,K(i).keys,!0),get view(){return K(a)},onView:c,actions:e,$$slots:{actions:!0}})}var de=z(ue,2),fe=e=>{{let n=j(()=>K(o)?{ok:K(o).entries.filter(e=>e.level===`ok`).length,total:K(o).entries.length}:null);Ia(e,{get health(){return K(y)},get undefinedKeys(){return t.panel.undefined},get locales(){return t.panel.locales},get total(){return t.panel.rows.length},get checks(){return K(n)},get commits(){return K(s)},onFilter:u,onHealth:l})}},pe=e=>{{let t=j(()=>K(o)?.entries??[]),n=j(()=>K(o)?.ok??!0);di(e,{get entries(){return K(t)},get ok(){return K(n)},onClose:()=>P(a,`overview`)})}},me=e=>{var t=Va(),r=L(t),i=e=>{var t=za(),n=R(t);B(()=>X(n,`${gi[K(x)]??``}${K(x)===`oneLocale`?` ${gi.oneLocaleFix}`:``}`)),Y(e,t)},a=e=>{var t=Ba(),r=Zt(t);Mr(r,17,()=>K(b).slice(0,K(ee)),e=>e.key,(e,t)=>{ma(e,{get row(){return K(t)},get shown(){return K(v)},get editing(){return K(n)},onEdit:e=>P(n,e,!0),onSave:p})});var i=z(r,2),a=e=>{var t=za(),n=R(t);B(()=>X(n,`${K(b).length-K(ee)} more below`)),Y(e,t)};Z(i,e=>{K(ee)<K(b).length&&e(a)}),Y(e,t)};Z(r,e=>{K(x)?e(i):e(a,-1)}),O(t),or(`scroll`,t,te),Y(e,t)};Z(de,e=>{K(a)===`overview`?e(fe):K(a)===`health`?e(pe,1):e(me,-1)}),O(le);var he=z(le,2),w=e=>{var t=Ua(),n=z(L(t),2),i=e=>{var t=Ha(),n=R(z(Zt(t)),!0);B(()=>X(n,K(r).file)),Y(e,t)},a=e=>{var t=_r();B(()=>X(t,K(r).text)),Y(e,t)};Z(n,e=>{K(r).file?e(i):e(a,-1)});var o=z(n,2);O(t),q(`click`,o,()=>P(r,null)),Y(e,t)};Z(he,e=>{K(r)&&e(w)}),O(ne),B(()=>{Q(ae,`title`,t.panel.root),X(oe,t.panel.root)}),ti(ie,()=>K(h),e=>P(h,e)),Y(e,ne),Ve()}sr([`click`]);async function Ka(e,t,n){let r=t.includes(`?`)?`&`:`?`,i;try{i=await fetch(`${t}${r}t=${encodeURIComponent(e)}`,{...n,headers:n?.body===void 0?void 0:{"content-type":`application/json`},body:n?.body===void 0?void 0:JSON.stringify(n.body)})}catch{return{error:`[verbaly] the studio server is not answering, is it still running?`}}let a=await i.json().catch(()=>({}));return i.ok?{value:a}:{error:a.error??`[verbaly] the server answered ${i.status}`}}function qa(e){return{state:()=>Ka(e,`/api/state`),health:()=>Ka(e,`/api/health`),history:()=>Ka(e,`/api/history`),save:(t,n,r)=>Ka(e,`/api/message/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,{method:`PUT`,body:{text:r}}),setRead:(t,n,r)=>Ka(e,`/api/approve`,{method:`POST`,body:{locale:t,keys:n,undo:r}}),extract:()=>Ka(e,`/api/extract`,{method:`POST`}),plan:t=>{let n=t.map(e=>`locale=${encodeURIComponent(e)}`).join(`&`);return Ka(e,`/api/translate${n?`?${n}`:``}`)},translate:t=>Ka(e,`/api/translate`,{method:`POST`,body:{locales:t}}),job:t=>Ka(e,t?`/api/job/${encodeURIComponent(t)}`:`/api/job`)}}function Ja(e){return Wt(ga(e))}var Ya=new URLSearchParams(location.search).get(`t`)??``;async function Xa(){let e=document.getElementById(`app`),t=qa(Ya),n=await t.state();if(n.error||!n.value){e.textContent=n.error??`[verbaly] the server sent no state`;return}Cr(Ga,{target:e,props:{panel:Ja(n.value),api:t}})}Xa();
|