waybetter 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/bin/waybetter.mjs +2 -5
- package/cli/buildenv.mjs +1 -1
- package/cli/release.mjs +11 -18
- package/cli/releasecheck.mjs +15 -0
- package/cli/remote.mjs +4 -4
- package/cli/store.mjs +80 -28
- package/cli/strings.mjs +2 -0
- package/dist/runtime/stringPackHook.js +2 -2
- package/dist/runtime/stringPackHook.js.map +1 -1
- package/dist/runtime/stringPackTranslate.d.ts +3 -1
- package/dist/runtime/stringPackTranslate.js +6 -3
- package/dist/runtime/stringPackTranslate.js.map +1 -1
- package/dist/runtime/stringPacks.d.ts +53 -5
- package/dist/runtime/stringPacks.js +161 -25
- package/dist/runtime/stringPacks.js.map +1 -1
- package/dist/runtime/themeBar.d.ts +28 -0
- package/dist/runtime/themeBar.js +82 -0
- package/dist/runtime/themeBar.js.map +1 -0
- package/dist/runtime/themeComponents.js +16 -3
- package/dist/runtime/themeComponents.js.map +1 -1
- package/dist/runtime/themeDecor.js +3 -1
- package/dist/runtime/themeDecor.js.map +1 -1
- package/dist/runtime/themeDerive.d.ts +69 -0
- package/dist/runtime/themeDerive.js +117 -0
- package/dist/runtime/themeDerive.js.map +1 -0
- package/dist/runtime/themeDoctor.d.ts +44 -3
- package/dist/runtime/themeDoctor.js +86 -25
- package/dist/runtime/themeDoctor.js.map +1 -1
- package/dist/runtime/themeGuards.d.ts +60 -0
- package/dist/runtime/themeGuards.js +235 -0
- package/dist/runtime/themeGuards.js.map +1 -0
- package/dist/runtime/themeIcons.d.ts +1 -1
- package/dist/runtime/themeIcons.js +13 -5
- package/dist/runtime/themeIcons.js.map +1 -1
- package/dist/runtime/themeInk.d.ts +37 -0
- package/dist/runtime/themeInk.js +111 -0
- package/dist/runtime/themeInk.js.map +1 -0
- package/dist/runtime/themeInvariants.d.ts +39 -0
- package/dist/runtime/themeInvariants.js +273 -0
- package/dist/runtime/themeInvariants.js.map +1 -0
- package/dist/runtime/themeRuntime.d.ts +15 -1
- package/dist/runtime/themeRuntime.js +78 -5
- package/dist/runtime/themeRuntime.js.map +1 -1
- package/dist/runtime/themeSpec.d.ts +5 -1
- package/dist/runtime/themeSpec.js +9 -13
- package/dist/runtime/themeSpec.js.map +1 -1
- package/dist/shell/InstallDialog.js +14 -8
- package/dist/shell/InstallDialog.js.map +1 -1
- package/dist/shell/StoreView.d.ts +12 -0
- package/dist/shell/StoreView.js +9 -4
- package/dist/shell/StoreView.js.map +1 -1
- package/dist/shell/frame/AppMenu.d.ts +26 -3
- package/dist/shell/frame/AppMenu.js +106 -27
- package/dist/shell/frame/AppMenu.js.map +1 -1
- package/dist/shell/frame/FindBar.js +1 -1
- package/dist/shell/frame/FindBar.js.map +1 -1
- package/dist/shell/frame/Shell.d.ts +1 -0
- package/dist/shell/frame/Shell.js +10 -2
- package/dist/shell/frame/Shell.js.map +1 -1
- package/dist/shell/frame/Titlebar.d.ts +2 -1
- package/dist/shell/frame/Titlebar.js +5 -3
- package/dist/shell/frame/Titlebar.js.map +1 -1
- package/dist/shell/frame/WebPanel.js +4 -1
- package/dist/shell/frame/WebPanel.js.map +1 -1
- package/dist/shell/frame/accountSwitcher.css +10 -10
- package/dist/shell/frame/appMenu.css +19 -13
- package/dist/shell/frame/boot.js +2 -0
- package/dist/shell/frame/boot.js.map +1 -1
- package/dist/shell/frame/chromeTheme.d.ts +19 -1
- package/dist/shell/frame/chromeTheme.js +51 -14
- package/dist/shell/frame/chromeTheme.js.map +1 -1
- package/dist/shell/frame/deck.css +30 -30
- package/dist/shell/frame/edges.css +159 -0
- package/dist/shell/frame/index.d.ts +2 -2
- package/dist/shell/frame/index.js +1 -1
- package/dist/shell/frame/index.js.map +1 -1
- package/dist/shell/frame/mediaModel.d.ts +13 -0
- package/dist/shell/frame/mediaModel.js +14 -0
- package/dist/shell/frame/mediaModel.js.map +1 -1
- package/dist/shell/frame/menuMessages.en.json +43 -1
- package/dist/shell/frame/menuModel.d.ts +42 -0
- package/dist/shell/frame/menuModel.js +8 -0
- package/dist/shell/frame/menuModel.js.map +1 -1
- package/dist/shell/frame/nativeMenu.d.ts +5 -0
- package/dist/shell/frame/nativeMenu.js +178 -0
- package/dist/shell/frame/nativeMenu.js.map +1 -0
- package/dist/shell/frame/nativeMenuModel.d.ts +102 -0
- package/dist/shell/frame/nativeMenuModel.js +186 -0
- package/dist/shell/frame/nativeMenuModel.js.map +1 -0
- package/dist/shell/frame/paletteModel.js +3 -1
- package/dist/shell/frame/paletteModel.js.map +1 -1
- package/dist/shell/frame/paneTheme.css +1 -1
- package/dist/shell/frame/reportModel.d.ts +1 -1
- package/dist/shell/frame/reportModel.js +1 -1
- package/dist/shell/frame/reportModel.js.map +1 -1
- package/dist/shell/frame/shell.css +56 -51
- package/dist/shell/frame/state.d.ts +2 -0
- package/dist/shell/frame/state.js +3 -1
- package/dist/shell/frame/state.js.map +1 -1
- package/dist/shell/frame/themeStore.js +21 -6
- package/dist/shell/frame/themeStore.js.map +1 -1
- package/dist/shell/frame/workspaces.css +12 -12
- package/dist/shell/installController.d.ts +16 -1
- package/dist/shell/installController.js +31 -5
- package/dist/shell/installController.js.map +1 -1
- package/dist/shell/panel/Appearance.js +12 -3
- package/dist/shell/panel/Appearance.js.map +1 -1
- package/dist/shell/panel/Settings.d.ts +1 -1
- package/dist/shell/panel/Settings.js +4 -3
- package/dist/shell/panel/Settings.js.map +1 -1
- package/dist/shell/panel/StoreSection.d.ts +2 -1
- package/dist/shell/panel/StoreSection.js +31 -1
- package/dist/shell/panel/StoreSection.js.map +1 -1
- package/dist/shell/panel/StringPacks.d.ts +12 -3
- package/dist/shell/panel/StringPacks.js +33 -8
- package/dist/shell/panel/StringPacks.js.map +1 -1
- package/dist/shell/panel/backup.css +1 -1
- package/dist/shell/panel/builder.css +48 -40
- package/dist/shell/panel/make.css +8 -7
- package/dist/shell/panel/panel.css +401 -401
- package/dist/shell/panel/panelMessages.d.ts +41 -1
- package/dist/shell/panel/panelMessages.js +13 -1
- package/dist/shell/panel/panelMessages.js.map +1 -1
- package/dist/shell/panel/plugins.css +5 -5
- package/dist/shell/panel/strings.css +1 -1
- package/dist/shell/store.css +34 -14
- package/dist/shell/storeMessages.d.ts +24 -0
- package/dist/shell/storeMessages.js +24 -0
- package/dist/shell/storeMessages.js.map +1 -1
- package/dist/shell/storeModel.d.ts +31 -7
- package/dist/shell/storeModel.js +15 -2
- package/dist/shell/storeModel.js.map +1 -1
- package/dist/shell/stringPacksModel.js +7 -2
- package/dist/shell/stringPacksModel.js.map +1 -1
- package/icons.schema.json +9 -0
- package/locales/ar.json +109 -2
- package/locales/bg.json +109 -2
- package/locales/bn.json +109 -2
- package/locales/ca.json +109 -2
- package/locales/cs.json +109 -2
- package/locales/da.json +109 -2
- package/locales/de.json +109 -2
- package/locales/el.json +109 -2
- package/locales/en.json +108 -2
- package/locales/es.json +109 -2
- package/locales/eu.json +109 -2
- package/locales/fa.json +109 -2
- package/locales/fi.json +109 -2
- package/locales/fil.json +109 -2
- package/locales/fr.json +109 -2
- package/locales/ga.json +109 -2
- package/locales/gl.json +109 -2
- package/locales/gu.json +109 -2
- package/locales/ha.json +109 -2
- package/locales/he.json +109 -2
- package/locales/hi.json +109 -2
- package/locales/hr.json +109 -2
- package/locales/hu.json +110 -2
- package/locales/id.json +109 -2
- package/locales/ig.json +109 -2
- package/locales/it.json +109 -2
- package/locales/ja.json +109 -2
- package/locales/kn.json +109 -2
- package/locales/ko.json +109 -2
- package/locales/mr.json +109 -2
- package/locales/ms.json +109 -2
- package/locales/nb.json +109 -2
- package/locales/nl.json +109 -2
- package/locales/pl.json +109 -2
- package/locales/pt.json +109 -2
- package/locales/ro.json +109 -2
- package/locales/ru.json +109 -2
- package/locales/sk.json +109 -2
- package/locales/sr.json +109 -2
- package/locales/sv.json +109 -2
- package/locales/ta.json +109 -2
- package/locales/th.json +109 -2
- package/locales/tr.json +109 -2
- package/locales/uk.json +109 -2
- package/locales/ur.json +109 -2
- package/locales/vi.json +109 -2
- package/locales/yo.json +109 -2
- package/locales/zh-Hans.json +109 -2
- package/locales/zh-Hant.json +109 -2
- package/package.json +2 -3
- package/store-catalog.schema.json +18 -5
- package/theme.schema.json +9 -0
- package/windows/installer.nsi +22 -2
- package/cli/privacy.mjs +0 -768
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stringPacks.js","sourceRoot":"","sources":["../../../runtime/src/stringPacks.ts"],"names":[],"mappings":"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","sourcesContent":["// String packs: data-only packs that replace the wrapped site's own UI strings (published as\n// `waybetter/runtime/stringPacks`). A pack adds a language the site does not offer, fixes its\n// translation or rewords it. This file is the data side: the pack and inventory formats, the\n// validator, the ordered application engine, coverage and the drift report. It touches no DOM and\n// runs the same in the page, in the shell and in Node (`waybetter strings check`).\n//\n// The rules (they are the owner's, and every function here keeps them):\n// - Idempotent. The result is a pure function of (the site's own values, the ordered pack list):\n// applying twice equals applying once, and a later pack wins over an earlier one per key.\n// - The site's own language is the fallback. A key no pack changes keeps exactly the site's value\n// (the same object, not a copy).\n// - An inventory of the site's known keys. A pack may change only inventory keys, and only keys\n// whose kind can be replaced by data; unknown keys are reported, never applied.\n// - Packs are data: plain text in an ICU MessageFormat subset ({param}, plural, select). Never\n// HTML, never code. A message is interpreted by closures here; nothing is evaluated.\n//\n// One site can have several catalogs (each with its own key space, inventory and hook adapter,\n// see stringPackHook.ts); a pack names the one it is for.\nimport { parseMessage } from './i18n.ts';\n\ntype Parts = ReturnType<typeof parseMessage>;\n\n// -------------------------------------------------------------------------------------------\n// Formats\n\n/**\n * What the site's value for a key is:\n * - `text`: a plain string;\n * - `message`: a function of a parameter object that returns a string;\n * - `rich`: text with element slots (not replaceable by data yet);\n * - `format`: a compiled number/date/currency formatter (not text).\n * Only `text` and `message` can be replaced by a pack.\n */\nexport type StringKind = 'text' | 'message' | 'rich' | 'format';\n\nexport type InventoryEntry = {\n kind: StringKind;\n /** Parameter names the site's value takes (`message`). */\n params?: string[];\n /** Parameters the site's value pluralizes: known to be numbers, so a pack may pluralize them. */\n plural?: string[];\n /** Parameters the site's value selects on. */\n select?: string[];\n /** Tag slot names, for catalogs whose values carry `<tag>…</tag>` slots. */\n tags?: string[];\n /** Hash of the base-language value (`hashText`): drift detection; never the text itself. */\n hash: string;\n /** Part of the catalog the key arrives with (default `main`), e.g. a lazily loaded `emoji` group. */\n group?: string;\n};\n\n/** The known keys of one catalog of one site. It carries ids and shapes, never the site's text. */\nexport type StringInventory = {\n format: 1;\n site: string;\n catalog: string;\n /** Language the hashes were taken from. */\n base: string;\n /** The site build the inventory was read from. */\n build?: string;\n entries: Record<string, InventoryEntry>;\n};\n\n/** A string pack document: metadata and `key id -> text`. */\nexport type StringPack = {\n format: 1;\n site: string;\n catalog: string;\n /** BCP 47 tag of the pack's language (private-use tags are fine: `en-x-pirate`). */\n language: string;\n name: string;\n authors: string[];\n /** A language whose plural rules the pack follows when the runtime does not know `language`. */\n base?: string;\n version?: string;\n description?: string;\n strings: Record<string, string>;\n};\n\nexport const STRING_PACK_LIMITS = Object.freeze({ strings: 40000, value: 2000, name: 80, authors: 16 });\nexport const MAIN_GROUP = 'main';\n\nconst TAG = /^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$/;\nconst IDENT = /^[a-z][a-z0-9-]{0,31}$/;\nconst CONTROL = /[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f--]/;\nconst CATEGORIES = new Set(['zero', 'one', 'two', 'few', 'many', 'other']);\n\n/** Whether a pack can replace a value of this kind. */\nexport function translatable(kind: StringKind): boolean {\n return kind === 'text' || kind === 'message';\n}\n\n/** 53-bit hash of a text as 11 base-36 characters. Same result in every runtime. */\nexport function hashText(text: string): string {\n let h1 = 0xdeadbeef;\n let h2 = 0x41c6ce57;\n for (let i = 0; i < text.length; i += 1) {\n const ch = text.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36).padStart(11, '0');\n}\n\n// -------------------------------------------------------------------------------------------\n// Inventory lookup (the full inventory, or its compact page form)\n\n/** The facts the validator and the engine need about one key. */\nexport type EntryShape = Pick<InventoryEntry, 'kind' | 'params' | 'plural' | 'select' | 'tags'>;\nexport type InventoryLookup = (id: string) => EntryShape | undefined;\n\n/**\n * The inventory as it ships inside a page runtime: ids and shapes only, no hashes, a fraction of\n * the size. `text` and `closed` are space-separated ids; a message is `name name*` (`*` = plural,\n * `?` = select).\n */\nexport type PageInventory = {\n site: string;\n catalog: string;\n text: string;\n message: Record<string, string>;\n closed: string;\n /** A slice: only the keys some pack names. A key missing from a slice is not a new key of the site. */\n partial?: boolean;\n};\n\nfunction compact(site: string, catalog: string, shapes: Iterable<[string, EntryShape]>): PageInventory {\n const text: string[] = [];\n const closed: string[] = [];\n const message: Record<string, string> = {};\n for (const [id, entry] of shapes) {\n if (entry.kind === 'text' && !entry.tags?.length) text.push(id);\n else if (entry.kind === 'message' && !entry.tags?.length) {\n message[id] = (entry.params ?? []).map(name => `${name}${entry.plural?.includes(name) ? '*' : ''}${entry.select?.includes(name) ? '?' : ''}`).join(' ');\n } else closed.push(id);\n }\n return { site, catalog, text: text.join(' '), message, closed: closed.join(' ') };\n}\n\nexport function packInventory(inventory: StringInventory): PageInventory {\n return compact(inventory.site, inventory.catalog, Object.entries(inventory.entries));\n}\n\n/**\n * The part of an inventory that the given keys need: what travels to a page together with the\n * packs it should apply (a page never needs the rest). Keys the inventory does not have are left\n * out, so they stay unknown there too.\n */\nexport function sliceInventory(inventory: StringInventory | PageInventory, ids: Iterable<string>): PageInventory {\n const lookup = inventoryLookup(inventory);\n const shapes: [string, EntryShape][] = [];\n for (const id of new Set(ids)) {\n const shape = lookup(id);\n if (shape) shapes.push([id, shape]);\n }\n return { ...compact(inventory.site, inventory.catalog, shapes), partial: true };\n}\n\n/** Whether untrusted data has the shape of a page inventory (ids and parameter names only). */\nexport function isPageInventory(input: unknown): input is PageInventory {\n if (!isRecord(input)) return false;\n const ids = (value: unknown) => typeof value === 'string' && value.length <= 2_000_000 && /^[\\w$. -]*$/.test(value);\n return typeof input.site === 'string' && IDENT.test(input.site) && typeof input.catalog === 'string' && IDENT.test(input.catalog)\n && ids(input.text) && ids(input.closed) && isRecord(input.message)\n && Object.entries(input.message).every(([id, names]) => /^[\\w$.-]+$/.test(id) && typeof names === 'string' && /^[\\w$*? ]*$/.test(names))\n && (input.partial === undefined || typeof input.partial === 'boolean');\n}\n\nconst TEXT_SHAPE: EntryShape = Object.freeze({ kind: 'text' });\nconst CLOSED_SHAPE: EntryShape = Object.freeze({ kind: 'rich' });\n\n/** A lookup over either form. The page form is decoded on first use. */\nexport function inventoryLookup(inventory: StringInventory | PageInventory): InventoryLookup {\n if ('entries' in inventory) {\n const entries = inventory.entries;\n return id => (Object.prototype.hasOwnProperty.call(entries, id) ? entries[id] : undefined);\n }\n let table: Map<string, EntryShape> | null = null;\n const decode = () => {\n const map = new Map<string, EntryShape>();\n if (inventory.text) for (const id of inventory.text.split(' ')) map.set(id, TEXT_SHAPE);\n if (inventory.closed) for (const id of inventory.closed.split(' ')) map.set(id, CLOSED_SHAPE);\n for (const [id, spec] of Object.entries(inventory.message)) {\n const names = spec ? spec.split(' ') : [];\n map.set(id, {\n kind: 'message',\n params: names.map(name => name.replace(/[*?]+$/, '')),\n plural: names.filter(name => name.includes('*')).map(name => name.replace(/[*?]+$/, '')),\n select: names.filter(name => name.includes('?')).map(name => name.replace(/[*?]+$/, '')),\n });\n }\n return map;\n };\n return id => (table ??= decode()).get(id);\n}\n\n// -------------------------------------------------------------------------------------------\n// Validator\n\nexport type PackIssue = { level: 'error' | 'warning'; key?: string; message: string };\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/** Checks the document envelope. Errors mean the pack is not applied at all. */\nexport function checkPackShape(input: unknown): PackIssue[] {\n const issues: PackIssue[] = [];\n const error = (message: string) => { issues.push({ level: 'error', message }); };\n if (!isRecord(input)) return [{ level: 'error', message: 'a string pack is a JSON object' }];\n if (input.format !== 1) error('\"format\" must be 1');\n for (const field of ['site', 'catalog'] as const) {\n if (typeof input[field] !== 'string' || !IDENT.test(input[field])) error(`\"${field}\" must be a short lowercase id`);\n }\n if (typeof input.language !== 'string' || !TAG.test(input.language)) error('\"language\" must be a language tag (en, pt-BR, en-x-pirate)');\n if (input.base !== undefined && (typeof input.base !== 'string' || !TAG.test(input.base))) error('\"base\" must be a language tag');\n if (typeof input.name !== 'string' || !input.name.trim() || input.name.length > STRING_PACK_LIMITS.name || CONTROL.test(input.name) || /[<>]/.test(input.name)) {\n error(`\"name\" must be 1 to ${STRING_PACK_LIMITS.name} characters of plain text`);\n }\n if (!Array.isArray(input.authors) || input.authors.length > STRING_PACK_LIMITS.authors\n || input.authors.some(author => typeof author !== 'string' || !author.trim() || author.length > STRING_PACK_LIMITS.name || CONTROL.test(author) || /[<>]/.test(author))) {\n error(`\"authors\" must be a list of at most ${STRING_PACK_LIMITS.authors} plain-text names`);\n }\n for (const field of ['version', 'description'] as const) {\n const value = input[field];\n if (value !== undefined && (typeof value !== 'string' || value.length > 400 || CONTROL.test(value) || /[<>]/.test(value))) error(`\"${field}\" must be plain text`);\n }\n if (!isRecord(input.strings)) error('\"strings\" must be an object of key id -> text');\n else if (Object.keys(input.strings).length > STRING_PACK_LIMITS.strings) error(`\"strings\" has more than ${STRING_PACK_LIMITS.strings} entries`);\n const known = new Set(['$schema', 'format', 'site', 'catalog', 'language', 'base', 'name', 'authors', 'version', 'description', 'strings']);\n for (const key of Object.keys(input)) if (!known.has(key)) issues.push({ level: 'warning', message: `unknown field \"${key}\" is ignored` });\n return issues;\n}\n\nconst TAG_TOKEN = /<\\/?([A-Za-z][A-Za-z0-9-]*)>/g;\n\n/** Tag rule: only the original's tag slots, each opened and closed; any other `<` or `>` is refused. */\nfunction checkTags(value: string, tags: readonly string[]): string | null {\n if (!value.includes('<') && !value.includes('>')) {\n return tags.length ? `the original's tags are missing: ${tags.map(tag => `<${tag}>`).join(' ')}` : null;\n }\n if (!tags.length) return 'markup is not allowed: a pack is text, < and > cannot be used';\n const open: string[] = [];\n const seen = new Set<string>();\n for (const match of value.matchAll(TAG_TOKEN)) {\n const name = match[1]!;\n if (!tags.includes(name)) return `<${name}> is not a tag of the original`;\n if (match[0].startsWith('</')) {\n if (open.pop() !== name) return `</${name}> does not close an open tag`;\n } else {\n open.push(name);\n seen.add(name);\n }\n }\n if (open.length) return `<${open[open.length - 1]}> is not closed`;\n if (/[<>]/.test(value.replace(TAG_TOKEN, ''))) return '< and > may only be used for the original\\'s tags';\n const missing = tags.filter(tag => !seen.has(tag));\n return missing.length ? `the original's tags are missing: ${missing.map(tag => `<${tag}>`).join(' ')}` : null;\n}\n\n/** Walks a parsed message against the key's shape; returns the first problem. */\nfunction checkParts(parts: Parts, shape: EntryShape): string | null {\n const params = shape.params ?? [];\n for (const part of parts) {\n if (typeof part === 'string' || part.kind === 'pound') continue;\n if (!params.includes(part.name)) {\n return params.length ? `{${part.name}} is not a parameter of the original (it has: ${params.join(', ')})` : `{${part.name}}: the original takes no parameters`;\n }\n if (part.kind === 'arg') {\n if (part.format) return `{${part.name}, ${part.format}} is not supported: only {name}, plural and select`;\n continue;\n }\n if (part.kind === 'plural') {\n if (part.ordinal) return `{${part.name}, selectordinal} is not supported: only {name}, plural and select`;\n if (part.offset) return `{${part.name}, plural, offset:…} is not supported`;\n if (!shape.plural?.includes(part.name)) return `{${part.name}} is not a plural of the original`;\n for (const selector of Object.keys(part.options)) {\n if (!CATEGORIES.has(selector) && !/^=\\d+$/.test(selector)) return `\"${selector}\" is not a plural form (zero, one, two, few, many, other, =N)`;\n }\n } else if (!shape.select?.includes(part.name)) {\n return `{${part.name}} is not a select of the original`;\n }\n for (const option of Object.values(part.options)) {\n const nested = checkParts(option, shape);\n if (nested) return nested;\n }\n }\n return null;\n}\n\n/**\n * Validates one pack value against the key's inventory entry. Returns the parsed message, or the\n * reason it is refused (the original then stays).\n */\nexport function validateString(shape: EntryShape, value: unknown): { parts: Parts } | { reason: string } {\n if (!translatable(shape.kind)) return { reason: `not translatable yet (${shape.kind})` };\n if (typeof value !== 'string') return { reason: 'the value must be text' };\n if (!value) return { reason: 'the value is empty' };\n if (value.length > STRING_PACK_LIMITS.value) return { reason: `longer than ${STRING_PACK_LIMITS.value} characters` };\n if (CONTROL.test(value)) return { reason: 'control or bidi-override characters are not allowed' };\n const tags = checkTags(value, shape.tags ?? []);\n if (tags) return { reason: tags };\n let parts: Parts;\n try {\n parts = parseMessage(value);\n } catch (error) {\n return { reason: `invalid message syntax: ${error instanceof Error ? error.message : String(error)}` };\n }\n const problem = checkParts(parts, shape.kind === 'message' ? shape : { kind: 'text' });\n return problem ? { reason: problem } : { parts };\n}\n\n// -------------------------------------------------------------------------------------------\n// Compiling a pack (validation against an inventory)\n\nexport type CompiledValue = { text: string } | { parts: Parts };\n\nexport type PackReport = {\n /** Entries in the pack. */\n total: number;\n /** Entries that are valid for an inventory key. */\n valid: number;\n /** Ids the inventory does not have: never applied. */\n unknown: string[];\n /** Values that failed validation: not applied, the original stays. */\n rejected: { id: string; reason: string }[];\n};\n\nexport type CompiledPack = {\n name: string;\n language: string;\n base?: string;\n site: string;\n catalog: string;\n values: ReadonlyMap<string, CompiledValue>;\n report: PackReport;\n};\n\n/** A message without arguments as its literal text (quotes resolved). */\nfunction literal(parts: Parts): string {\n return parts.map(part => (typeof part === 'string' ? part : '')).join('');\n}\n\n/**\n * Validates a pack against an inventory. Throws on a malformed envelope or a pack for another\n * site/catalog; every other problem is per key and lands in `report`.\n */\nexport function compilePack(input: unknown, inventory: StringInventory | PageInventory): CompiledPack {\n const shapeErrors = checkPackShape(input).filter(issue => issue.level === 'error');\n if (shapeErrors.length) throw new Error(`invalid string pack: ${shapeErrors.map(issue => issue.message).join('; ')}`);\n const pack = input as StringPack;\n if (pack.site !== inventory.site || pack.catalog !== inventory.catalog) {\n throw new Error(`the pack is for ${pack.site}/${pack.catalog}, the inventory is ${inventory.site}/${inventory.catalog}`);\n }\n const lookup = inventoryLookup(inventory);\n const values = new Map<string, CompiledValue>();\n const report: PackReport = { total: 0, valid: 0, unknown: [], rejected: [] };\n for (const [id, value] of Object.entries(pack.strings)) {\n report.total += 1;\n const shape = lookup(id);\n if (!shape) { report.unknown.push(id); continue; }\n const result = validateString(shape, value);\n if ('reason' in result) { report.rejected.push({ id, reason: result.reason }); continue; }\n values.set(id, shape.kind === 'text' ? { text: literal(result.parts) } : { parts: result.parts });\n report.valid += 1;\n }\n return { name: pack.name, language: pack.language, base: pack.base, site: pack.site, catalog: pack.catalog, values, report };\n}\n\n// -------------------------------------------------------------------------------------------\n// Interpreting a message (closures over the parsed parts; nothing is evaluated)\n\nconst rulesCache = new Map<string, Intl.PluralRules | null>();\n\n/** Plural rules of the first language the runtime knows; `null` = every number is `other`. */\nfunction rulesFor(languages: readonly (string | undefined)[]): Intl.PluralRules | null {\n const key = languages.join('|');\n let rules = rulesCache.get(key);\n if (rules !== undefined) return rules;\n rules = null;\n for (const language of languages) {\n if (!language) continue;\n const tag = language.split(/-x-/i)[0]!;\n try {\n if (Intl.PluralRules.supportedLocalesOf([tag]).length) { rules = new Intl.PluralRules(tag); break; }\n } catch {\n // Not a tag this runtime accepts: try the next.\n }\n }\n rulesCache.set(key, rules);\n return rules;\n}\n\n/**\n * Renders a validated message. A parameter is inserted the way string concatenation would\n * (`String(value)`, nothing for a missing one); `#` is the plural's own value.\n */\nexport function renderMessage(parts: Parts, params: Readonly<Record<string, unknown>>, languages: readonly (string | undefined)[], pound: unknown = undefined): string {\n let out = '';\n for (const part of parts) {\n if (typeof part === 'string') { out += part; continue; }\n // The parser only yields `#` inside a plural, so there is always a value it stands for.\n if (part.kind === 'pound') { out += pound === undefined || pound === null ? '' : String(pound); continue; }\n const value = params[part.name];\n if (part.kind === 'arg') { out += value === undefined || value === null ? '' : String(value); continue; }\n if (part.kind === 'select') {\n out += renderMessage(part.options[String(value)] ?? part.options.other!, params, languages, pound);\n continue;\n }\n const n = typeof value === 'number' ? value : Number(value);\n const option = Number.isFinite(n)\n ? part.options[`=${n}`] ?? part.options[rulesFor(languages)?.select(n) ?? 'other'] ?? part.options.other!\n : part.options.other!;\n out += renderMessage(option, params, languages, value);\n }\n return out;\n}\n\n// -------------------------------------------------------------------------------------------\n// The ordered application engine\n\nexport type EngineStats = {\n /** Keys the site registered. */\n seen: number;\n /** Keys a pack value was used for. */\n applied: number;\n /** Keys the site registered that the inventory does not have (new keys: drift). */\n unlisted: string[];\n /** Keys whose live value does not have the inventory's kind: left untouched. */\n mismatched: string[];\n};\n\nexport type StringEngine = {\n /**\n * The value to use for `id`, given the site's own value: a pack's, or exactly `original`.\n * Feeding a value this engine produced back in returns the same value (idempotent).\n */\n resolve(id: string, original: unknown): unknown;\n /** The site's own values of the keys a pack changed: what restoring needs. */\n originals(): ReadonlyMap<string, unknown>;\n stats(): EngineStats;\n};\n\nconst MAX_LISTED = 200;\n\n/** `packs` in application order: a later pack wins over an earlier one for the same key. */\nexport function createStringEngine(inventory: StringInventory | PageInventory | InventoryLookup, packs: readonly CompiledPack[]): StringEngine {\n const lookup = typeof inventory === 'function' ? inventory : inventoryLookup(inventory);\n // A slice only knows the packs' keys: what it lacks is not a new key of the site.\n const whole = typeof inventory === 'function' || !('partial' in inventory && inventory.partial);\n const originals = new Map<string, unknown>();\n const applied = new Map<string, unknown>();\n const produced = new WeakMap<object, unknown>();\n const seen = new Set<string>();\n const unlisted = new Set<string>();\n const mismatched = new Set<string>();\n\n const winner = (id: string): { pack: CompiledPack; value: CompiledValue } | null => {\n for (let index = packs.length - 1; index >= 0; index -= 1) {\n const value = packs[index]!.values.get(id);\n if (value) return { pack: packs[index]!, value };\n }\n return null;\n };\n\n const resolve = (id: string, incoming: unknown): unknown => {\n let original = incoming;\n // A value of ours coming back in (a second application): work from the site's own value again.\n if (typeof incoming === 'function' && produced.has(incoming)) original = produced.get(incoming);\n else if (typeof incoming === 'string' && applied.has(id) && applied.get(id) === incoming) original = originals.get(id);\n seen.add(id);\n const found = winner(id);\n if (!found) {\n if (whole && unlisted.size < MAX_LISTED && !lookup(id)) unlisted.add(id);\n return original;\n }\n const shape = lookup(id);\n if (!shape || !translatable(shape.kind)) return original;\n if (shape.kind === 'text' ? typeof original !== 'string' : typeof original !== 'function') {\n if (mismatched.size < MAX_LISTED) mismatched.add(id);\n return original;\n }\n if (originals.has(id) && originals.get(id) === original) return applied.get(id);\n let next: unknown;\n if ('text' in found.value) {\n next = found.value.text;\n } else {\n const parts = found.value.parts;\n const languages = [found.pack.language, found.pack.base];\n const message = (params?: unknown): string => renderMessage(parts, isRecord(params) ? params : {}, languages);\n produced.set(message, original);\n next = message;\n }\n originals.set(id, original);\n applied.set(id, next);\n return next;\n };\n\n return {\n resolve,\n originals: () => originals,\n stats: () => ({ seen: seen.size, applied: applied.size, unlisted: [...unlisted], mismatched: [...mismatched] }),\n };\n}\n\n/**\n * The whole catalog at once: a new object with the packs applied; `catalog` itself is not\n * changed. `applyPacks(applyPacks(c, …), …)` with one engine equals `applyPacks(c, …)`.\n */\nexport function applyPacks(catalog: Readonly<Record<string, unknown>>, engine: StringEngine): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const id of Object.keys(catalog)) out[id] = engine.resolve(id, catalog[id]);\n return out;\n}\n\n/** The inverse: every value a pack changed is the site's own again; `catalog` is not changed. */\nexport function restoreCatalog(catalog: Readonly<Record<string, unknown>>, engine: StringEngine): Record<string, unknown> {\n const originals = engine.originals();\n const out: Record<string, unknown> = {};\n for (const id of Object.keys(catalog)) out[id] = originals.has(id) ? originals.get(id) : catalog[id];\n return out;\n}\n\n// -------------------------------------------------------------------------------------------\n// Coverage\n\nexport type Coverage = {\n /** Keys a pack can replace (text and messages). */\n translatable: number;\n /** Of those, keys the pack has a valid value for. */\n translated: number;\n /** Keys that exist but cannot be replaced by data yet (rich text, formatters). */\n closed: number;\n};\n\n/** Coverage of a compiled pack per group of the inventory, plus `all`. */\nexport function coverage(inventory: StringInventory, pack: Pick<CompiledPack, 'values'>): Record<string, Coverage> {\n const out: Record<string, Coverage> = { all: { translatable: 0, translated: 0, closed: 0 } };\n for (const [id, entry] of Object.entries(inventory.entries)) {\n const group = (out[entry.group ?? MAIN_GROUP] ??= { translatable: 0, translated: 0, closed: 0 });\n for (const bucket of [group, out.all!]) {\n if (!translatable(entry.kind)) { bucket.closed += 1; continue; }\n bucket.translatable += 1;\n if (pack.values.has(id)) bucket.translated += 1;\n }\n }\n return out;\n}\n\n// -------------------------------------------------------------------------------------------\n// Drift (the site shipped a new build)\n\nexport type DriftReport = {\n /** Keys the site has that the inventory lacks. */\n added: string[];\n /** Keys whose base-language value changed (same shape). */\n reworded: string[];\n /** Keys whose kind or parameters changed: pack values for them have to be checked again. */\n reshaped: string[];\n /** Inventory keys the site no longer has. Only for groups whose base catalog was loaded. */\n vanished: string[];\n};\n\nconst sameList = (a: readonly string[] = [], b: readonly string[] = []) => a.length === b.length && [...a].sort().join('\\n') === [...b].sort().join('\\n');\n\n/**\n * Compares an inventory with what was observed now. `loaded` names the groups whose base catalog\n * was actually read: a key can only be called vanished when its group was (a lazily loaded group\n * that never arrived says nothing about its keys).\n */\nexport function driftReport(inventory: StringInventory, observed: Readonly<Record<string, InventoryEntry>>, loaded: readonly string[]): DriftReport {\n const report: DriftReport = { added: [], reworded: [], reshaped: [], vanished: [] };\n for (const [id, now] of Object.entries(observed)) {\n const before = Object.prototype.hasOwnProperty.call(inventory.entries, id) ? inventory.entries[id] : undefined;\n if (!before) { report.added.push(id); continue; }\n if (before.kind !== now.kind || !sameList(before.params, now.params) || !sameList(before.plural, now.plural) || !sameList(before.select, now.select) || !sameList(before.tags, now.tags)) {\n report.reshaped.push(id);\n } else if (before.hash !== now.hash) {\n report.reworded.push(id);\n }\n }\n const groups = new Set(loaded);\n for (const [id, entry] of Object.entries(inventory.entries)) {\n if (!Object.prototype.hasOwnProperty.call(observed, id) && groups.has(entry.group ?? MAIN_GROUP)) report.vanished.push(id);\n }\n return report;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stringPacks.js","sourceRoot":"","sources":["../../../runtime/src/stringPacks.ts"],"names":[],"mappings":"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","sourcesContent":["// String packs: data-only packs that replace the wrapped site's own UI strings (published as\n// `waybetter/runtime/stringPacks`). A pack adds a language the site does not offer, fixes its\n// translation or rewords it. This file is the data side: the pack and inventory formats, the\n// validator, the ordered application engine, coverage and the drift report. It touches no DOM and\n// runs the same in the page, in the shell and in Node (`waybetter strings check`).\n//\n// The rules (they are the owner's, and every function here keeps them):\n// - Idempotent. The result is a pure function of (the site's own values, the ordered pack list):\n// applying twice equals applying once, and a later pack wins over an earlier one per key.\n// - The site's own language is the fallback. A key no pack changes keeps exactly the site's value\n// (the same object, not a copy).\n// - An inventory of the site's known keys. A pack may change only inventory keys, and only keys\n// whose kind can be replaced by data; unknown keys are reported, never applied.\n// - Packs are data: plain text in an ICU MessageFormat subset ({param}, plural, select). Never\n// HTML, never code. A message is interpreted by closures here; nothing is evaluated.\n//\n// One site can have several catalogs (each with its own key space, inventory and hook adapter,\n// see stringPackHook.ts); a pack names the one it is for.\nimport { parseMessage } from './i18n.ts';\n\ntype Parts = ReturnType<typeof parseMessage>;\n\n// -------------------------------------------------------------------------------------------\n// Formats\n\n/**\n * What the site's value for a key is:\n * - `text`: a plain string;\n * - `message`: a function of a parameter object that returns a string;\n * - `rich`: text with element slots (a link or a button inside a sentence). It can be replaced when\n * the inventory knows its slot count (`slots`): the pack value then places the site's own\n * elements with `{e0}`, `{e1}`, …, each exactly once (the last may be left out); the value itself is still plain text;\n * - `format`: a compiled number/date/currency formatter (not text).\n * Only `text`, `message` and `rich` with known `slots` can be replaced by a pack.\n */\nexport type StringKind = 'text' | 'message' | 'rich' | 'format';\n\nexport type InventoryEntry = {\n kind: StringKind;\n /** Parameter names the site's value takes (`message`). */\n params?: string[];\n /** Parameters the site's value pluralizes: known to be numbers, so a pack may pluralize them. */\n plural?: string[];\n /** Parameters the site's value selects on. */\n select?: string[];\n /** Element slots of a `rich` value (`{e0}` … `{e<slots-1>}` in a pack value; the last may be left out). Without it the key is closed. */\n slots?: number;\n /** Tag slot names, for catalogs whose values carry `<tag>…</tag>` slots. */\n tags?: string[];\n /** Hash of the base-language value (`hashText`): drift detection; never the text itself. */\n hash: string;\n /** Part of the catalog the key arrives with (default `main`), e.g. a lazily loaded `emoji` group. */\n group?: string;\n};\n\n/** The known keys of one catalog of one site. It carries ids and shapes, never the site's text. */\nexport type StringInventory = {\n format: 1;\n site: string;\n catalog: string;\n /** Language the hashes were taken from. */\n base: string;\n /** The site build the inventory was read from. */\n build?: string;\n entries: Record<string, InventoryEntry>;\n};\n\n/**\n * When a pack applies. Without a condition it always does. `languages`: only while the site shows\n * one of these languages (a tag matches itself and its regional forms: `en` matches `en-GB`), for\n * example a rewording of English that must not touch a Turkish page.\n */\nexport type PackCondition = { languages?: string[] };\n\n/**\n * A pack's rewording rule: whole words replaced inside the site's own text, wherever it appears\n * (`{ \"Post\": \"Tweet\", \"posts\": \"tweets\" }`). It carries none of the site's sentences, so it keeps\n * working when the site words a string differently, and it applies to a value of the site (or of an\n * earlier pack) that no later pack replaced. Words are matched exactly (case as written), never\n * inside a longer word, and never in a parameter's value (a user named \"Post\" stays \"Post\").\n */\nexport type PackRewrite = { words: Record<string, string> };\n\n/** A string pack document: metadata and `key id -> text`. */\nexport type StringPack = {\n format: 1;\n site: string;\n catalog: string;\n /** BCP 47 tag of the pack's language (private-use tags are fine: `en-x-pirate`). */\n language: string;\n name: string;\n authors: string[];\n /** A language whose plural rules the pack follows when the runtime does not know `language`. */\n base?: string;\n /** The pack applies only when this holds (default: always). */\n when?: PackCondition;\n /** Rewords the site's text instead of (or besides) replacing keys. */\n rewrite?: PackRewrite;\n version?: string;\n description?: string;\n strings: Record<string, string>;\n};\n\nexport const STRING_PACK_LIMITS = Object.freeze({ strings: 40000, value: 2000, name: 80, authors: 16 });\nexport const MAIN_GROUP = 'main';\n\nconst TAG = /^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$/;\nconst IDENT = /^[a-z][a-z0-9-]{0,31}$/;\nconst CONTROL = /[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f--]/;\nconst REWRITE_FROM = /^[\\p{L}\\p{N}]{1,40}$/u;\nconst REWRITE_TO = /^[\\p{L}\\p{N}][\\p{L}\\p{N}'’-]{0,39}$/u;\nconst MAX_REWRITES = 64;\nconst CATEGORIES = new Set(['zero', 'one', 'two', 'few', 'many', 'other']);\n\n/** Whether a pack can replace a value of this kind (a `rich` one only with known `slots`: pass the shape). */\nexport function translatable(kind: StringKind | Pick<EntryShape, 'kind' | 'slots'>): boolean {\n const { kind: k, slots } = typeof kind === 'string' ? { kind, slots: undefined } : kind;\n return k === 'text' || k === 'message' || (k === 'rich' && slots !== undefined);\n}\n\n/** Whether `language` (the site's) satisfies a pack's `when`. */\nexport function conditionHolds(when: PackCondition | undefined, language: string | undefined): boolean {\n if (!when?.languages) return true;\n if (!language) return false;\n const have = language.toLowerCase();\n return when.languages.some(tag => { const want = tag.toLowerCase(); return have === want || have.startsWith(`${want}-`); });\n}\n\n/** 53-bit hash of a text as 11 base-36 characters. Same result in every runtime. */\nexport function hashText(text: string): string {\n let h1 = 0xdeadbeef;\n let h2 = 0x41c6ce57;\n for (let i = 0; i < text.length; i += 1) {\n const ch = text.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36).padStart(11, '0');\n}\n\n// -------------------------------------------------------------------------------------------\n// Inventory lookup (the full inventory, or its compact page form)\n\n/** The facts the validator and the engine need about one key. */\nexport type EntryShape = Pick<InventoryEntry, 'kind' | 'params' | 'plural' | 'select' | 'tags' | 'slots'>;\nexport type InventoryLookup = (id: string) => EntryShape | undefined;\n\n/**\n * The inventory as it ships inside a page runtime: ids and shapes only, no hashes, a fraction of\n * the size. `text` and `closed` are space-separated ids; a message is `name name*` (`*` = plural,\n * `?` = select).\n */\nexport type PageInventory = {\n site: string;\n catalog: string;\n text: string;\n message: Record<string, string>;\n closed: string;\n /** Rich entries a pack can replace: id -> slot count. */\n rich?: Record<string, number>;\n /** A slice: only the keys some pack names. A key missing from a slice is not a new key of the site. */\n partial?: boolean;\n};\n\nfunction compact(site: string, catalog: string, shapes: Iterable<[string, EntryShape]>): PageInventory {\n const text: string[] = [];\n const closed: string[] = [];\n const message: Record<string, string> = {};\n const rich: Record<string, number> = {};\n for (const [id, entry] of shapes) {\n if (entry.kind === 'rich' && entry.slots !== undefined && !entry.tags?.length) rich[id] = entry.slots;\n else if (entry.kind === 'text' && !entry.tags?.length) text.push(id);\n else if (entry.kind === 'message' && !entry.tags?.length) {\n message[id] = (entry.params ?? []).map(name => `${name}${entry.plural?.includes(name) ? '*' : ''}${entry.select?.includes(name) ? '?' : ''}`).join(' ');\n } else closed.push(id);\n }\n return { site, catalog, text: text.join(' '), message, closed: closed.join(' '), ...(Object.keys(rich).length ? { rich } : {}) };\n}\n\nexport function packInventory(inventory: StringInventory): PageInventory {\n return compact(inventory.site, inventory.catalog, Object.entries(inventory.entries));\n}\n\n/**\n * The part of an inventory that the given keys need: what travels to a page together with the\n * packs it should apply (a page never needs the rest). Keys the inventory does not have are left\n * out, so they stay unknown there too.\n */\nexport function sliceInventory(inventory: StringInventory | PageInventory, ids: Iterable<string>): PageInventory {\n const lookup = inventoryLookup(inventory);\n const shapes: [string, EntryShape][] = [];\n for (const id of new Set(ids)) {\n const shape = lookup(id);\n if (shape) shapes.push([id, shape]);\n }\n return { ...compact(inventory.site, inventory.catalog, shapes), partial: true };\n}\n\n/** Whether untrusted data has the shape of a page inventory (ids and parameter names only). */\nexport function isPageInventory(input: unknown): input is PageInventory {\n if (!isRecord(input)) return false;\n const ids = (value: unknown) => typeof value === 'string' && value.length <= 2_000_000 && /^[\\w$. -]*$/.test(value);\n return typeof input.site === 'string' && IDENT.test(input.site) && typeof input.catalog === 'string' && IDENT.test(input.catalog)\n && ids(input.text) && ids(input.closed) && isRecord(input.message)\n && Object.entries(input.message).every(([id, names]) => /^[\\w$.-]+$/.test(id) && typeof names === 'string' && /^[\\w$*? ]*$/.test(names))\n && (input.rich === undefined || (isRecord(input.rich) && Object.entries(input.rich).every(([id, n]) => /^[\\w$.-]+$/.test(id) && Number.isInteger(n) && (n as number) >= 0 && (n as number) <= 32)))\n && (input.partial === undefined || typeof input.partial === 'boolean');\n}\n\nconst TEXT_SHAPE: EntryShape = Object.freeze({ kind: 'text' });\nconst CLOSED_SHAPE: EntryShape = Object.freeze({ kind: 'rich' });\n\n/** A lookup over either form. The page form is decoded on first use. */\nexport function inventoryLookup(inventory: StringInventory | PageInventory): InventoryLookup {\n if ('entries' in inventory) {\n const entries = inventory.entries;\n return id => (Object.prototype.hasOwnProperty.call(entries, id) ? entries[id] : undefined);\n }\n let table: Map<string, EntryShape> | null = null;\n const decode = () => {\n const map = new Map<string, EntryShape>();\n if (inventory.text) for (const id of inventory.text.split(' ')) map.set(id, TEXT_SHAPE);\n if (inventory.closed) for (const id of inventory.closed.split(' ')) map.set(id, CLOSED_SHAPE);\n if (inventory.rich) for (const [id, slots] of Object.entries(inventory.rich)) map.set(id, { kind: 'rich', slots });\n for (const [id, spec] of Object.entries(inventory.message)) {\n const names = spec ? spec.split(' ') : [];\n map.set(id, {\n kind: 'message',\n params: names.map(name => name.replace(/[*?]+$/, '')),\n plural: names.filter(name => name.includes('*')).map(name => name.replace(/[*?]+$/, '')),\n select: names.filter(name => name.includes('?')).map(name => name.replace(/[*?]+$/, '')),\n });\n }\n return map;\n };\n return id => (table ??= decode()).get(id);\n}\n\n// -------------------------------------------------------------------------------------------\n// Validator\n\nexport type PackIssue = { level: 'error' | 'warning'; key?: string; message: string };\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/** Checks the document envelope. Errors mean the pack is not applied at all. */\nexport function checkPackShape(input: unknown): PackIssue[] {\n const issues: PackIssue[] = [];\n const error = (message: string) => { issues.push({ level: 'error', message }); };\n if (!isRecord(input)) return [{ level: 'error', message: 'a string pack is a JSON object' }];\n if (input.format !== 1) error('\"format\" must be 1');\n for (const field of ['site', 'catalog'] as const) {\n if (typeof input[field] !== 'string' || !IDENT.test(input[field])) error(`\"${field}\" must be a short lowercase id`);\n }\n if (typeof input.language !== 'string' || !TAG.test(input.language)) error('\"language\" must be a language tag (en, pt-BR, en-x-pirate)');\n if (input.base !== undefined && (typeof input.base !== 'string' || !TAG.test(input.base))) error('\"base\" must be a language tag');\n if (typeof input.name !== 'string' || !input.name.trim() || input.name.length > STRING_PACK_LIMITS.name || CONTROL.test(input.name) || /[<>]/.test(input.name)) {\n error(`\"name\" must be 1 to ${STRING_PACK_LIMITS.name} characters of plain text`);\n }\n if (!Array.isArray(input.authors) || input.authors.length > STRING_PACK_LIMITS.authors\n || input.authors.some(author => typeof author !== 'string' || !author.trim() || author.length > STRING_PACK_LIMITS.name || CONTROL.test(author) || /[<>]/.test(author))) {\n error(`\"authors\" must be a list of at most ${STRING_PACK_LIMITS.authors} plain-text names`);\n }\n if (input.when !== undefined) {\n const when = input.when;\n if (!isRecord(when) || Object.keys(when).some(key => key !== 'languages')) error('\"when\" is an object with \"languages\"');\n else if (when.languages !== undefined && (!Array.isArray(when.languages) || !when.languages.length || when.languages.length > 16\n || when.languages.some(tag => typeof tag !== 'string' || !TAG.test(tag)))) error('\"when.languages\" must be a list of 1 to 16 language tags');\n }\n if (input.rewrite !== undefined) {\n const rewrite = input.rewrite;\n const words = isRecord(rewrite) ? rewrite.words : undefined;\n if (!isRecord(rewrite) || Object.keys(rewrite).some(key => key !== 'words') || !isRecord(words) || !Object.keys(words).length || Object.keys(words).length > MAX_REWRITES\n || Object.entries(words).some(([from, to]) => !REWRITE_FROM.test(from) || typeof to !== 'string' || !REWRITE_TO.test(to))) {\n error(`\"rewrite\" is { \"words\": { \"Word\": \"Replacement\" } } with 1 to ${MAX_REWRITES} plain words`);\n }\n }\n for (const field of ['version', 'description'] as const) {\n const value = input[field];\n if (value !== undefined && (typeof value !== 'string' || value.length > 400 || CONTROL.test(value) || /[<>]/.test(value))) error(`\"${field}\" must be plain text`);\n }\n if (!isRecord(input.strings)) error('\"strings\" must be an object of key id -> text');\n else if (Object.keys(input.strings).length > STRING_PACK_LIMITS.strings) error(`\"strings\" has more than ${STRING_PACK_LIMITS.strings} entries`);\n const known = new Set(['$schema', 'format', 'site', 'catalog', 'language', 'base', 'when', 'rewrite', 'name', 'authors', 'version', 'description', 'strings']);\n for (const key of Object.keys(input)) if (!known.has(key)) issues.push({ level: 'warning', message: `unknown field \"${key}\" is ignored` });\n return issues;\n}\n\nconst TAG_TOKEN = /<\\/?([A-Za-z][A-Za-z0-9-]*)>/g;\n\n/** Tag rule: only the original's tag slots, each opened and closed; any other `<` or `>` is refused. */\nfunction checkTags(value: string, tags: readonly string[]): string | null {\n if (!value.includes('<') && !value.includes('>')) {\n return tags.length ? `the original's tags are missing: ${tags.map(tag => `<${tag}>`).join(' ')}` : null;\n }\n if (!tags.length) return 'markup is not allowed: a pack is text, < and > cannot be used';\n const open: string[] = [];\n const seen = new Set<string>();\n for (const match of value.matchAll(TAG_TOKEN)) {\n const name = match[1]!;\n if (!tags.includes(name)) return `<${name}> is not a tag of the original`;\n if (match[0].startsWith('</')) {\n if (open.pop() !== name) return `</${name}> does not close an open tag`;\n } else {\n open.push(name);\n seen.add(name);\n }\n }\n if (open.length) return `<${open[open.length - 1]}> is not closed`;\n if (/[<>]/.test(value.replace(TAG_TOKEN, ''))) return '< and > may only be used for the original\\'s tags';\n const missing = tags.filter(tag => !seen.has(tag));\n return missing.length ? `the original's tags are missing: ${missing.map(tag => `<${tag}>`).join(' ')}` : null;\n}\n\n/** Walks a parsed message against the key's shape; returns the first problem. */\nfunction checkParts(parts: Parts, shape: EntryShape): string | null {\n const params = shape.params ?? [];\n for (const part of parts) {\n if (typeof part === 'string' || part.kind === 'pound') continue;\n if (!params.includes(part.name)) {\n return params.length ? `{${part.name}} is not a parameter of the original (it has: ${params.join(', ')})` : `{${part.name}}: the original takes no parameters`;\n }\n if (part.kind === 'arg') {\n if (part.format) return `{${part.name}, ${part.format}} is not supported: only {name}, plural and select`;\n continue;\n }\n if (part.kind === 'plural') {\n if (part.ordinal) return `{${part.name}, selectordinal} is not supported: only {name}, plural and select`;\n if (part.offset) return `{${part.name}, plural, offset:…} is not supported`;\n if (!shape.plural?.includes(part.name)) return `{${part.name}} is not a plural of the original`;\n for (const selector of Object.keys(part.options)) {\n if (!CATEGORIES.has(selector) && !/^=\\d+$/.test(selector)) return `\"${selector}\" is not a plural form (zero, one, two, few, many, other, =N)`;\n }\n } else if (!shape.select?.includes(part.name)) {\n return `{${part.name}} is not a select of the original`;\n }\n for (const option of Object.values(part.options)) {\n const nested = checkParts(option, shape);\n if (nested) return nested;\n }\n }\n return null;\n}\n\n/**\n * Validates one pack value against the key's inventory entry. Returns the parsed message, or the\n * reason it is refused (the original then stays).\n */\nexport function validateString(shape: EntryShape, value: unknown): { parts: Parts } | { reason: string } {\n if (!translatable(shape)) return { reason: `not translatable yet (${shape.kind})` };\n if (typeof value !== 'string') return { reason: 'the value must be text' };\n if (!value) return { reason: 'the value is empty' };\n if (value.length > STRING_PACK_LIMITS.value) return { reason: `longer than ${STRING_PACK_LIMITS.value} characters` };\n if (CONTROL.test(value)) return { reason: 'control or bidi-override characters are not allowed' };\n const tags = checkTags(value, shape.tags ?? []);\n if (tags) return { reason: tags };\n let parts: Parts;\n try {\n parts = parseMessage(value);\n } catch (error) {\n return { reason: `invalid message syntax: ${error instanceof Error ? error.message : String(error)}` };\n }\n if (shape.kind === 'rich') {\n // Element slots: `{e0}` … `{e<slots-1>}`, each exactly once (the last may be left out); no plural, select or other parameter.\n const slots = Array.from({ length: shape.slots ?? 0 }, (_, index) => `e${index}`);\n const bad = checkParts(parts, { kind: 'message', params: slots });\n if (bad) return { reason: bad };\n const used = parts.flatMap(part => (typeof part !== 'string' && part.kind === 'arg' ? [part.name] : []));\n for (const name of slots) {\n const count = used.filter(item => item === name).length;\n // The element after the last piece is not always there: that one slot may be left out.\n if (count === 0 && name === slots[slots.length - 1] && slots.length > 0) continue;\n if (count !== 1) return { reason: count ? `{${name}} (the original's element) must appear once, not ${count} times` : `the original's element {${name}} is missing` };\n }\n return { parts };\n }\n const problem = checkParts(parts, shape.kind === 'message' ? shape : { kind: 'text' });\n return problem ? { reason: problem } : { parts };\n}\n\n// -------------------------------------------------------------------------------------------\n// Compiling a pack (validation against an inventory)\n\n/**\n * A replaced `rich` value in the shape X's own renderer reads: piece `n` is shown, then the site's\n * element `order[n]` (the last piece has no element after it).\n */\nexport type RichTemplate = { readonly pieces: readonly string[]; readonly order: readonly number[] };\n\nexport type CompiledValue = { text: string } | { parts: Parts } | { rich: RichTemplate };\n\nexport type PackReport = {\n /** Entries in the pack. */\n total: number;\n /** Entries that are valid for an inventory key. */\n valid: number;\n /** Ids the inventory does not have: never applied. */\n unknown: string[];\n /** Values that failed validation: not applied, the original stays. */\n rejected: { id: string; reason: string }[];\n};\n\nexport type CompiledPack = {\n name: string;\n language: string;\n base?: string;\n when?: PackCondition;\n /** The pack's word rewriting, ready to apply to a text. */\n rewrite?: (text: string) => string;\n site: string;\n catalog: string;\n values: ReadonlyMap<string, CompiledValue>;\n report: PackReport;\n};\n\n/** A message without arguments as its literal text (quotes resolved). */\nfunction literal(parts: Parts): string {\n return parts.map(part => (typeof part === 'string' ? part : '')).join('');\n}\n\n/** The word-for-word rewriting of a validated `rewrite` rule. */\nfunction compileRewrite(rule: PackRewrite): (text: string) => string {\n const words = new Map(Object.entries(rule.words));\n // Words are letters and digits only (checked), so they need no escaping.\n const alternatives = [...words.keys()].sort((a, b) => b.length - a.length).join('|');\n const pattern = new RegExp(String.raw`(?<![\\p{L}\\p{N}_])(?:${alternatives})(?![\\p{L}\\p{N}_])`, 'gu');\n return text => text.replace(pattern, word => words.get(word) ?? word);\n}\n\n/** A validated rich value as pieces and element order. */\nfunction richTemplate(parts: Parts): RichTemplate {\n const pieces: string[] = [];\n const order: number[] = [];\n let current = '';\n for (const part of parts) {\n if (typeof part === 'string') current += part;\n else if (part.kind === 'arg') { pieces.push(current); order.push(Number(part.name.slice(1))); current = ''; }\n }\n pieces.push(current);\n return Object.freeze({ pieces: Object.freeze(pieces), order: Object.freeze(order) });\n}\n\n/**\n * Validates a pack against an inventory. Throws on a malformed envelope or a pack for another\n * site/catalog; every other problem is per key and lands in `report`.\n */\nexport function compilePack(input: unknown, inventory: StringInventory | PageInventory): CompiledPack {\n const shapeErrors = checkPackShape(input).filter(issue => issue.level === 'error');\n if (shapeErrors.length) throw new Error(`invalid string pack: ${shapeErrors.map(issue => issue.message).join('; ')}`);\n const pack = input as StringPack;\n if (pack.site !== inventory.site || pack.catalog !== inventory.catalog) {\n throw new Error(`the pack is for ${pack.site}/${pack.catalog}, the inventory is ${inventory.site}/${inventory.catalog}`);\n }\n const lookup = inventoryLookup(inventory);\n const values = new Map<string, CompiledValue>();\n const report: PackReport = { total: 0, valid: 0, unknown: [], rejected: [] };\n for (const [id, value] of Object.entries(pack.strings)) {\n report.total += 1;\n const shape = lookup(id);\n if (!shape) { report.unknown.push(id); continue; }\n const result = validateString(shape, value);\n if ('reason' in result) { report.rejected.push({ id, reason: result.reason }); continue; }\n values.set(id, shape.kind === 'text' ? { text: literal(result.parts) } : shape.kind === 'rich' ? { rich: richTemplate(result.parts) } : { parts: result.parts });\n report.valid += 1;\n }\n return { name: pack.name, language: pack.language, base: pack.base, when: pack.when, rewrite: pack.rewrite ? compileRewrite(pack.rewrite) : undefined, site: pack.site, catalog: pack.catalog, values, report };\n}\n\n// -------------------------------------------------------------------------------------------\n// Interpreting a message (closures over the parsed parts; nothing is evaluated)\n\nconst rulesCache = new Map<string, Intl.PluralRules | null>();\n\n/** Plural rules of the first language the runtime knows; `null` = every number is `other`. */\nfunction rulesFor(languages: readonly (string | undefined)[]): Intl.PluralRules | null {\n const key = languages.join('|');\n let rules = rulesCache.get(key);\n if (rules !== undefined) return rules;\n rules = null;\n for (const language of languages) {\n if (!language) continue;\n const tag = language.split(/-x-/i)[0]!;\n try {\n if (Intl.PluralRules.supportedLocalesOf([tag]).length) { rules = new Intl.PluralRules(tag); break; }\n } catch {\n // Not a tag this runtime accepts: try the next.\n }\n }\n rulesCache.set(key, rules);\n return rules;\n}\n\n/**\n * Renders a validated message. A parameter is inserted the way string concatenation would\n * (`String(value)`, nothing for a missing one); `#` is the plural's own value.\n */\nexport function renderMessage(parts: Parts, params: Readonly<Record<string, unknown>>, languages: readonly (string | undefined)[], pound: unknown = undefined): string {\n let out = '';\n for (const part of parts) {\n if (typeof part === 'string') { out += part; continue; }\n // The parser only yields `#` inside a plural, so there is always a value it stands for.\n if (part.kind === 'pound') { out += pound === undefined || pound === null ? '' : String(pound); continue; }\n const value = params[part.name];\n if (part.kind === 'arg') { out += value === undefined || value === null ? '' : String(value); continue; }\n if (part.kind === 'select') {\n out += renderMessage(part.options[String(value)] ?? part.options.other!, params, languages, pound);\n continue;\n }\n const n = typeof value === 'number' ? value : Number(value);\n const option = Number.isFinite(n)\n ? part.options[`=${n}`] ?? part.options[rulesFor(languages)?.select(n) ?? 'other'] ?? part.options.other!\n : part.options.other!;\n out += renderMessage(option, params, languages, value);\n }\n return out;\n}\n\n/** The site's (or a pack's) value of one key with `rewrite` applied; a message keeps its parameters' values as they are. */\nfunction rewriteValue(shape: EntryShape, value: unknown, rewrite: (text: string) => string): unknown {\n if (typeof value === 'string') return rewrite(value);\n if (Array.isArray(value)) {\n const mapped = value.map(piece => (typeof piece === 'string' ? rewrite(piece) : piece));\n return mapped.some((piece, index) => piece !== value[index]) ? mapped : value;\n }\n if (typeof value === 'function') {\n const message = value as (this: unknown, params?: unknown) => unknown;\n const plural = new Set(shape.plural ?? []);\n return function (this: unknown, params?: unknown) {\n const input = isRecord(params) ? params : {};\n // The parameters go through as private markers, so only the site's own words are reworded.\n const forward: Record<string, unknown> = { ...input };\n const held: [string, unknown][] = [];\n for (const name of shape.params ?? []) {\n if (plural.has(name) || !(name in input)) continue;\n const marker = `\\uE000${held.length}\\uE001`;\n held.push([marker, input[name]]);\n forward[name] = marker;\n }\n try {\n const out = message.call(this, forward);\n if (typeof out !== 'string') return message.call(this, params);\n let text = rewrite(out);\n for (const [marker, original] of held) text = text.split(marker).join(String(original));\n return text;\n } catch {\n return message.call(this, params);\n }\n };\n }\n if (typeof value === 'object' && value !== null && 'pieces' in value) {\n const template = value as RichTemplate;\n return Object.freeze({ pieces: Object.freeze(template.pieces.map(rewrite)), order: template.order });\n }\n return value;\n}\n\n// -------------------------------------------------------------------------------------------\n// The ordered application engine\n\nexport type EngineStats = {\n /** Keys the site registered. */\n seen: number;\n /** Keys a pack value was used for. */\n applied: number;\n /** Keys the site registered that the inventory does not have (new keys: drift). */\n unlisted: string[];\n /** Keys whose live value does not have the inventory's kind: left untouched. */\n mismatched: string[];\n};\n\nexport type StringEngine = {\n /**\n * The value to use for `id`, given the site's own value: a pack's, or exactly `original`.\n * Feeding a value this engine produced back in returns the same value (idempotent).\n */\n resolve(id: string, original: unknown): unknown;\n /**\n * The language the site shows (what packs with a `when.languages` condition are checked\n * against). Set before the first `resolve`; until then conditional packs do not apply.\n */\n setLanguage(language: string): void;\n /** The site's own values of the keys a pack changed: what restoring needs. */\n originals(): ReadonlyMap<string, unknown>;\n stats(): EngineStats;\n};\n\nconst MAX_LISTED = 200;\n\n/** `packs` in application order: a later pack wins over an earlier one for the same key. */\nexport function createStringEngine(inventory: StringInventory | PageInventory | InventoryLookup, packs: readonly CompiledPack[]): StringEngine {\n const lookup = typeof inventory === 'function' ? inventory : inventoryLookup(inventory);\n // A slice only knows the packs' keys: what it lacks is not a new key of the site.\n const whole = typeof inventory === 'function' || !('partial' in inventory && inventory.partial);\n const originals = new Map<string, unknown>();\n const applied = new Map<string, unknown>();\n const produced = new WeakMap<object, unknown>();\n const seen = new Set<string>();\n const unlisted = new Set<string>();\n const mismatched = new Set<string>();\n let siteLanguage: string | undefined;\n\n const winner = (id: string): { pack: CompiledPack; value: CompiledValue; index: number } | null => {\n for (let index = packs.length - 1; index >= 0; index -= 1) {\n if (!conditionHolds(packs[index]!.when, siteLanguage)) continue;\n const value = packs[index]!.values.get(id);\n if (value) return { pack: packs[index]!, value, index };\n }\n return null;\n };\n\n const resolve = (id: string, incoming: unknown): unknown => {\n let original = incoming;\n // A value of ours coming back in (a second application): work from the site's own value again.\n if ((typeof incoming === 'function' || (typeof incoming === 'object' && incoming !== null)) && produced.has(incoming)) original = produced.get(incoming);\n else if (typeof incoming === 'string' && applied.has(id) && applied.get(id) === incoming) original = originals.get(id);\n seen.add(id);\n const found = winner(id);\n // Word rewriting of the packs after the one whose text won (all of them when none did).\n const rewrites = packs.flatMap((pack, index) => (index > (found?.index ?? -1) && pack.rewrite && conditionHolds(pack.when, siteLanguage) ? [pack.rewrite] : []));\n if (!found && !rewrites.length) {\n if (whole && unlisted.size < MAX_LISTED && !lookup(id)) unlisted.add(id);\n return original;\n }\n const shape = lookup(id);\n if (!shape || shape.kind === 'format' || (found && !translatable(shape))) return original;\n if (shape.kind === 'text' ? typeof original !== 'string' : shape.kind === 'rich' ? !Array.isArray(original) : typeof original !== 'function') {\n if (mismatched.size < MAX_LISTED) mismatched.add(id);\n return original;\n }\n if (originals.has(id) && originals.get(id) === original) return applied.get(id);\n let next: unknown = original;\n if (found) {\n if ('text' in found.value) {\n next = found.value.text;\n } else if ('rich' in found.value) {\n next = found.value.rich;\n } else {\n const parts = found.value.parts;\n const languages = [found.pack.language, found.pack.base];\n next = (params?: unknown): string => renderMessage(parts, isRecord(params) ? params : {}, languages);\n }\n }\n for (const rewrite of rewrites) next = rewriteValue(shape, next, rewrite);\n if (next === original) return original;\n if (typeof next === 'function' || typeof next === 'object') produced.set(next as object, original as object);\n originals.set(id, original);\n applied.set(id, next);\n return next;\n };\n\n return {\n resolve,\n setLanguage(language) { siteLanguage = language; },\n originals: () => originals,\n stats: () => ({ seen: seen.size, applied: applied.size, unlisted: [...unlisted], mismatched: [...mismatched] }),\n };\n}\n\n/**\n * The whole catalog at once: a new object with the packs applied; `catalog` itself is not\n * changed. `applyPacks(applyPacks(c, …), …)` with one engine equals `applyPacks(c, …)`.\n */\nexport function applyPacks(catalog: Readonly<Record<string, unknown>>, engine: StringEngine): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const id of Object.keys(catalog)) out[id] = engine.resolve(id, catalog[id]);\n return out;\n}\n\n/** The inverse: every value a pack changed is the site's own again; `catalog` is not changed. */\nexport function restoreCatalog(catalog: Readonly<Record<string, unknown>>, engine: StringEngine): Record<string, unknown> {\n const originals = engine.originals();\n const out: Record<string, unknown> = {};\n for (const id of Object.keys(catalog)) out[id] = originals.has(id) ? originals.get(id) : catalog[id];\n return out;\n}\n\n// -------------------------------------------------------------------------------------------\n// Coverage\n\nexport type Coverage = {\n /** Keys a pack can replace (text and messages). */\n translatable: number;\n /** Of those, keys the pack has a valid value for. */\n translated: number;\n /** Keys that exist but cannot be replaced by data yet (rich text, formatters). */\n closed: number;\n};\n\n/** Coverage of a compiled pack per group of the inventory, plus `all`. */\nexport function coverage(inventory: StringInventory, pack: Pick<CompiledPack, 'values'>): Record<string, Coverage> {\n const out: Record<string, Coverage> = { all: { translatable: 0, translated: 0, closed: 0 } };\n for (const [id, entry] of Object.entries(inventory.entries)) {\n const group = (out[entry.group ?? MAIN_GROUP] ??= { translatable: 0, translated: 0, closed: 0 });\n for (const bucket of [group, out.all!]) {\n if (!translatable(entry)) { bucket.closed += 1; continue; }\n bucket.translatable += 1;\n if (pack.values.has(id)) bucket.translated += 1;\n }\n }\n return out;\n}\n\n// -------------------------------------------------------------------------------------------\n// Drift (the site shipped a new build)\n\nexport type DriftReport = {\n /** Keys the site has that the inventory lacks. */\n added: string[];\n /** Keys whose base-language value changed (same shape). */\n reworded: string[];\n /** Keys whose kind or parameters changed: pack values for them have to be checked again. */\n reshaped: string[];\n /** Inventory keys the site no longer has. Only for groups whose base catalog was loaded. */\n vanished: string[];\n};\n\nconst sameList = (a: readonly string[] = [], b: readonly string[] = []) => a.length === b.length && [...a].sort().join('\\n') === [...b].sort().join('\\n');\n\n/**\n * Compares an inventory with what was observed now. `loaded` names the groups whose base catalog\n * was actually read: a key can only be called vanished when its group was (a lazily loaded group\n * that never arrived says nothing about its keys).\n */\nexport function driftReport(inventory: StringInventory, observed: Readonly<Record<string, InventoryEntry>>, loaded: readonly string[]): DriftReport {\n const report: DriftReport = { added: [], reworded: [], reshaped: [], vanished: [] };\n for (const [id, now] of Object.entries(observed)) {\n const before = Object.prototype.hasOwnProperty.call(inventory.entries, id) ? inventory.entries[id] : undefined;\n if (!before) { report.added.push(id); continue; }\n if (before.kind !== now.kind || before.slots !== now.slots || !sameList(before.params, now.params) || !sameList(before.plural, now.plural) || !sameList(before.select, now.select) || !sameList(before.tags, now.tags)) {\n report.reshaped.push(id);\n } else if (before.hash !== now.hash) {\n report.reworded.push(id);\n }\n }\n const groups = new Set(loaded);\n for (const [id, entry] of Object.entries(inventory.entries)) {\n if (!Object.prototype.hasOwnProperty.call(observed, id) && groups.has(entry.group ?? MAIN_GROUP)) report.vanished.push(id);\n }\n return report;\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const BAR_ATTR = "data-wb-bar";
|
|
2
|
+
export type BarMode = 'labels' | 'icons';
|
|
3
|
+
/** One item as the measurer sees it: its label text and font, and the fixed parts around the label. */
|
|
4
|
+
export type BarItem = {
|
|
5
|
+
label: string;
|
|
6
|
+
font: string;
|
|
7
|
+
fixed: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Pure: the mode for `items` in `available` px, with `gap` between items. Hysteresis: leaving icons
|
|
11
|
+
* mode needs 16px more room than staying in labels mode, so a bar never flaps at the threshold.
|
|
12
|
+
*/
|
|
13
|
+
export declare function barMode(items: Array<{
|
|
14
|
+
labelWidth: number;
|
|
15
|
+
fixed: number;
|
|
16
|
+
}>, available: number, gap: number, current: BarMode | null, hysteresis?: number): BarMode;
|
|
17
|
+
export type BarMeasurerOptions = {
|
|
18
|
+
/** The bar's item container (X: the nav). */
|
|
19
|
+
nav: string;
|
|
20
|
+
/** Items inside it, and inside an item its icon box and label box. */
|
|
21
|
+
item: string;
|
|
22
|
+
icon: string;
|
|
23
|
+
label: string;
|
|
24
|
+
/** Only while this matches (a bar layout is active). */
|
|
25
|
+
when?: string;
|
|
26
|
+
};
|
|
27
|
+
/** Measures on nav resize and font loads; writes the mode on <html>. Returns a stop function. */
|
|
28
|
+
export declare function installBarMeasurer(win: Window, options: BarMeasurerOptions): () => void;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Theme engine v3, step 9 (.omc/plans/theme-engine-v3.md 4.1): one bar component. Whether a bar's
|
|
2
|
+
// items carry their labels is measured, never guessed from a width breakpoint: the sum of the whole
|
|
3
|
+
// labels (text measured in the label's own font), icons, paddings and gaps against the room the items
|
|
4
|
+
// have. The mode lands on `html[data-wb-bar="labels|icons"]`; the bar's CSS keys on it. A label is
|
|
5
|
+
// therefore whole or absent, never cut ("H…", 1.0.2).
|
|
6
|
+
export const BAR_ATTR = 'data-wb-bar';
|
|
7
|
+
/**
|
|
8
|
+
* Pure: the mode for `items` in `available` px, with `gap` between items. Hysteresis: leaving icons
|
|
9
|
+
* mode needs 16px more room than staying in labels mode, so a bar never flaps at the threshold.
|
|
10
|
+
*/
|
|
11
|
+
export function barMode(items, available, gap, current, hysteresis = 16) {
|
|
12
|
+
if (!items.length || !items.some(item => item.labelWidth > 0))
|
|
13
|
+
return 'labels';
|
|
14
|
+
const need = items.reduce((sum, item) => sum + item.labelWidth + item.fixed, 0) + gap * Math.max(0, items.length - 1);
|
|
15
|
+
const room = current === 'icons' ? available - hysteresis : available;
|
|
16
|
+
return need <= room ? 'labels' : 'icons';
|
|
17
|
+
}
|
|
18
|
+
const px = (value) => { const n = parseFloat(value); return Number.isFinite(n) ? n : 0; };
|
|
19
|
+
/** Measures on nav resize and font loads; writes the mode on <html>. Returns a stop function. */
|
|
20
|
+
export function installBarMeasurer(win, options) {
|
|
21
|
+
const doc = win.document;
|
|
22
|
+
const canvas = doc.createElement('canvas');
|
|
23
|
+
const ctx = canvas.getContext('2d');
|
|
24
|
+
const textWidth = (text, font) => { if (!ctx)
|
|
25
|
+
return text.length * 8; ctx.font = font; return Math.ceil(ctx.measureText(text).width); };
|
|
26
|
+
let nav = null;
|
|
27
|
+
let frame = 0;
|
|
28
|
+
const measure = () => {
|
|
29
|
+
frame = 0;
|
|
30
|
+
const html = doc.documentElement;
|
|
31
|
+
if (options.when && !doc.querySelector(options.when)) {
|
|
32
|
+
html.removeAttribute(BAR_ATTR);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!nav?.isConnected)
|
|
36
|
+
return;
|
|
37
|
+
const items = [...nav.querySelectorAll(`:scope > ${options.item}`)].filter(el => el.offsetParent !== null || el.getClientRects().length);
|
|
38
|
+
const measured = items.map(item => {
|
|
39
|
+
const label = item.querySelector(options.label);
|
|
40
|
+
const icon = item.querySelector(options.icon);
|
|
41
|
+
const pill = item.firstElementChild ?? item;
|
|
42
|
+
const ps = win.getComputedStyle(pill);
|
|
43
|
+
const fixed = px(ps.paddingLeft) + px(ps.paddingRight) + px(ps.borderLeftWidth) + px(ps.borderRightWidth) + (icon ? Math.max(icon.getBoundingClientRect().width, 20) : 0);
|
|
44
|
+
if (!label || !label.textContent?.trim())
|
|
45
|
+
return { labelWidth: 0, fixed };
|
|
46
|
+
const ls = win.getComputedStyle(label);
|
|
47
|
+
// The label's own font, read even while the label is display:none (computed styles resolve it).
|
|
48
|
+
const font = `${ls.fontStyle} ${ls.fontWeight} ${ls.fontSize} ${ls.fontFamily}`;
|
|
49
|
+
return { labelWidth: textWidth(label.textContent.trim(), font) + px(ls.marginLeft) + px(ls.marginRight) + 2, fixed };
|
|
50
|
+
});
|
|
51
|
+
const ns = win.getComputedStyle(nav);
|
|
52
|
+
const available = nav.clientWidth - px(ns.paddingLeft) - px(ns.paddingRight);
|
|
53
|
+
const current = html.getAttribute(BAR_ATTR);
|
|
54
|
+
const mode = barMode(measured, available, px(ns.columnGap) || 0, current);
|
|
55
|
+
if (current !== mode)
|
|
56
|
+
html.setAttribute(BAR_ATTR, mode);
|
|
57
|
+
};
|
|
58
|
+
const schedule = () => { if (!frame)
|
|
59
|
+
frame = win.requestAnimationFrame(measure); };
|
|
60
|
+
const Resize = win.ResizeObserver;
|
|
61
|
+
const sized = Resize ? new Resize(schedule) : null;
|
|
62
|
+
const attach = () => {
|
|
63
|
+
const found = doc.querySelector(options.nav);
|
|
64
|
+
if (found !== nav) {
|
|
65
|
+
if (nav)
|
|
66
|
+
sized?.unobserve(nav);
|
|
67
|
+
nav = found;
|
|
68
|
+
if (nav)
|
|
69
|
+
sized?.observe(nav);
|
|
70
|
+
}
|
|
71
|
+
schedule();
|
|
72
|
+
};
|
|
73
|
+
attach();
|
|
74
|
+
// The nav mounts late and is replaced on some navigations; items and fonts change rarely.
|
|
75
|
+
const timer = win.setInterval(attach, 1500);
|
|
76
|
+
const fonts = doc.fonts;
|
|
77
|
+
fonts?.addEventListener?.('loadingdone', schedule);
|
|
78
|
+
win.addEventListener('resize', schedule);
|
|
79
|
+
return () => { win.clearInterval(timer); sized?.disconnect(); fonts?.removeEventListener?.('loadingdone', schedule); win.removeEventListener('resize', schedule); if (frame)
|
|
80
|
+
win.cancelAnimationFrame(frame); doc.documentElement.removeAttribute(BAR_ATTR); };
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=themeBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themeBar.js","sourceRoot":"","sources":["../../../runtime/src/themeBar.ts"],"names":[],"mappings":"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","sourcesContent":["// Theme engine v3, step 9 (.omc/plans/theme-engine-v3.md 4.1): one bar component. Whether a bar's\n// items carry their labels is measured, never guessed from a width breakpoint: the sum of the whole\n// labels (text measured in the label's own font), icons, paddings and gaps against the room the items\n// have. The mode lands on `html[data-wb-bar=\"labels|icons\"]`; the bar's CSS keys on it. A label is\n// therefore whole or absent, never cut (\"H…\", 1.0.2).\n\nexport const BAR_ATTR = 'data-wb-bar';\nexport type BarMode = 'labels' | 'icons';\n\n/** One item as the measurer sees it: its label text and font, and the fixed parts around the label. */\nexport type BarItem = { label: string; font: string; fixed: number };\n\n/**\n * Pure: the mode for `items` in `available` px, with `gap` between items. Hysteresis: leaving icons\n * mode needs 16px more room than staying in labels mode, so a bar never flaps at the threshold.\n */\nexport function barMode(items: Array<{ labelWidth: number; fixed: number }>, available: number, gap: number, current: BarMode | null, hysteresis = 16): BarMode {\n if (!items.length || !items.some(item => item.labelWidth > 0)) return 'labels';\n const need = items.reduce((sum, item) => sum + item.labelWidth + item.fixed, 0) + gap * Math.max(0, items.length - 1);\n const room = current === 'icons' ? available - hysteresis : available;\n return need <= room ? 'labels' : 'icons';\n}\n\nexport type BarMeasurerOptions = {\n /** The bar's item container (X: the nav). */\n nav: string;\n /** Items inside it, and inside an item its icon box and label box. */\n item: string; icon: string; label: string;\n /** Only while this matches (a bar layout is active). */\n when?: string;\n};\n\nconst px = (value: string) => { const n = parseFloat(value); return Number.isFinite(n) ? n : 0; };\n\n/** Measures on nav resize and font loads; writes the mode on <html>. Returns a stop function. */\nexport function installBarMeasurer(win: Window, options: BarMeasurerOptions): () => void {\n const doc = win.document;\n const canvas = doc.createElement('canvas');\n const ctx = canvas.getContext('2d');\n const textWidth = (text: string, font: string) => { if (!ctx) return text.length * 8; ctx.font = font; return Math.ceil(ctx.measureText(text).width); };\n let nav: Element | null = null;\n let frame = 0;\n const measure = () => {\n frame = 0;\n const html = doc.documentElement;\n if (options.when && !doc.querySelector(options.when)) { html.removeAttribute(BAR_ATTR); return; }\n if (!nav?.isConnected) return;\n const items = [...nav.querySelectorAll(`:scope > ${options.item}`)].filter(el => (el as HTMLElement).offsetParent !== null || el.getClientRects().length);\n const measured = items.map(item => {\n const label = item.querySelector(options.label) as HTMLElement | null;\n const icon = item.querySelector(options.icon) as HTMLElement | null;\n const pill = (item.firstElementChild as HTMLElement | null) ?? (item as HTMLElement);\n const ps = win.getComputedStyle(pill);\n const fixed = px(ps.paddingLeft) + px(ps.paddingRight) + px(ps.borderLeftWidth) + px(ps.borderRightWidth) + (icon ? Math.max(icon.getBoundingClientRect().width, 20) : 0);\n if (!label || !label.textContent?.trim()) return { labelWidth: 0, fixed };\n const ls = win.getComputedStyle(label);\n // The label's own font, read even while the label is display:none (computed styles resolve it).\n const font = `${ls.fontStyle} ${ls.fontWeight} ${ls.fontSize} ${ls.fontFamily}`;\n return { labelWidth: textWidth(label.textContent.trim(), font) + px(ls.marginLeft) + px(ls.marginRight) + 2, fixed };\n });\n const ns = win.getComputedStyle(nav);\n const available = (nav as HTMLElement).clientWidth - px(ns.paddingLeft) - px(ns.paddingRight);\n const current = (html.getAttribute(BAR_ATTR) as BarMode | null);\n const mode = barMode(measured, available, px(ns.columnGap) || 0, current);\n if (current !== mode) html.setAttribute(BAR_ATTR, mode);\n };\n const schedule = () => { if (!frame) frame = win.requestAnimationFrame(measure); };\n const Resize = (win as Window & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver;\n const sized = Resize ? new Resize(schedule) : null;\n const attach = () => {\n const found = doc.querySelector(options.nav);\n if (found !== nav) { if (nav) sized?.unobserve(nav); nav = found; if (nav) sized?.observe(nav); }\n schedule();\n };\n attach();\n // The nav mounts late and is replaced on some navigations; items and fonts change rarely.\n const timer = win.setInterval(attach, 1500);\n const fonts = (doc as Document & { fonts?: FontFaceSet }).fonts;\n fonts?.addEventListener?.('loadingdone', schedule);\n win.addEventListener('resize', schedule);\n return () => { win.clearInterval(timer); sized?.disconnect(); fonts?.removeEventListener?.('loadingdone', schedule); win.removeEventListener('resize', schedule); if (frame) win.cancelAnimationFrame(frame); doc.documentElement.removeAttribute(BAR_ATTR); };\n}\n"]}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
//
|
|
15
15
|
// The bevel borders (`bevel-out`, `bevel-in`) follow 98.css's raised and sunken edges (MIT, Jordan
|
|
16
16
|
// Scales, https://github.com/jdan/98.css): four inset shadows, here computed from the theme's roles.
|
|
17
|
+
import { inkOnEvery } from "./themeInk.js";
|
|
17
18
|
import { contrastRatio, hexToRgb, mix, relativeLuminance } from "./themeApi.js";
|
|
18
19
|
// ---------------------------------------------------------------------------------------------
|
|
19
20
|
// Vocabulary
|
|
@@ -341,8 +342,9 @@ export function compileComponents(components, parts, ctx) {
|
|
|
341
342
|
decl.forEach(([property, value], index) => put(part.fill ? fillRule : box, `fill${index ? `-${index}` : ''}`, property, value));
|
|
342
343
|
}
|
|
343
344
|
let textRole = has('text') ? tokens.text : undefined;
|
|
345
|
+
const need = def.contrast ?? 4.5;
|
|
344
346
|
if (face && (def.text || textRole)) {
|
|
345
|
-
|
|
347
|
+
// A role that cannot read on this fill gives way to the best role (white label on an accent fill)...
|
|
346
348
|
if (!textRole || contrastRatio(ctx.colors[textRole], face) < need) {
|
|
347
349
|
const readable = readableRole(face, ctx.colors, textRole);
|
|
348
350
|
if (textRole && readable !== textRole)
|
|
@@ -350,8 +352,19 @@ export function compileComponents(components, parts, ctx) {
|
|
|
350
352
|
textRole = readable;
|
|
351
353
|
}
|
|
352
354
|
}
|
|
353
|
-
if (textRole)
|
|
354
|
-
|
|
355
|
+
if (textRole) {
|
|
356
|
+
// ...and the ink is then solved on the grounds it really sits on (theme engine v3 3.3): its fill, or with
|
|
357
|
+
// no fill of its own every surface it can sit on, the page canvas included (an outline button in the
|
|
358
|
+
// rail sits on the page: Solarized's accent read 4.45:1 there).
|
|
359
|
+
// A role made for another ground (onAccent, onInverse, bg: a label on a fill some parent paints, the
|
|
360
|
+
// Classic bar) is the theme's statement about that parent and stands.
|
|
361
|
+
const surfaceInk = textRole === 'text' || textRole === 'muted' || textRole === 'accent';
|
|
362
|
+
const grounds = face ? [face] : surfaceInk ? [ctx.colors.bg, ctx.colors.surface, ctx.colors.elevated, ctx.colors.page] : [];
|
|
363
|
+
const solved = grounds.length ? inkOnEvery(grounds, ctx.colors[textRole], need) : { ink: ctx.colors[textRole], adjusted: false };
|
|
364
|
+
if (solved.adjusted)
|
|
365
|
+
notes.push(`${id}: text "${textRole}" moved to ${solved.ink} to read ${need}:1 on ${grounds.join('/')}`);
|
|
366
|
+
put(type, 'text', 'color', solved.ink);
|
|
367
|
+
}
|
|
355
368
|
if (has('radius'))
|
|
356
369
|
put(box, 'radius', 'border-radius', tokens.radius === 'pill' ? '9999px' : `${tokens.radius}px`);
|
|
357
370
|
const style = has('borderStyle') ? tokens.borderStyle : undefined;
|