prosebook 0.3.0 → 0.5.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 +357 -26
- package/dist/bind-BIZNv8nU.js +62 -0
- package/dist/bind-BIZNv8nU.js.map +1 -0
- package/dist/bind-ZS86jHXk.d.ts +31 -0
- package/dist/bind-ZS86jHXk.d.ts.map +1 -0
- package/dist/bun.d.ts +12 -3
- package/dist/bun.d.ts.map +1 -1
- package/dist/bun.js +77 -26
- package/dist/bun.js.map +1 -1
- package/dist/{bundle-KD-DiiFa.d.ts → bundle-CLHY_97D.d.ts} +3 -3
- package/dist/bundle-CLHY_97D.d.ts.map +1 -0
- package/dist/bundle-Ut6Y2X6N.js +217 -0
- package/dist/bundle-Ut6Y2X6N.js.map +1 -0
- package/dist/cli.js +55 -12
- package/dist/cli.js.map +1 -1
- package/dist/{config-BPSmoYel.js → config-7T4hX_f7.js} +13 -5
- package/dist/{config-BPSmoYel.js.map → config-7T4hX_f7.js.map} +1 -1
- package/dist/{config-DdMkKt_N.d.ts → config-CzaJJQ60.d.ts} +19 -5
- package/dist/{config-DdMkKt_N.d.ts.map → config-CzaJJQ60.d.ts.map} +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/{copy-B3V_QRkT.d.ts → copy-BXn0aYQn.d.ts} +37 -3
- package/dist/copy-BXn0aYQn.d.ts.map +1 -0
- package/dist/copy-Bv6S-Hr2.js +235 -0
- package/dist/copy-Bv6S-Hr2.js.map +1 -0
- package/dist/endpoints-Dhgowovz.js +217 -0
- package/dist/endpoints-Dhgowovz.js.map +1 -0
- package/dist/generate-1BeQAd1O.d.ts +72 -0
- package/dist/generate-1BeQAd1O.d.ts.map +1 -0
- package/dist/{generate-9pR3i5Bj.js → generate-CKv86Iki.js} +1724 -627
- package/dist/generate-CKv86Iki.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/next-loader.d.ts +9 -2
- package/dist/next-loader.d.ts.map +1 -1
- package/dist/next-loader.js +12 -3
- package/dist/next-loader.js.map +1 -1
- package/dist/next.d.ts +11 -3
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +94 -21
- package/dist/next.js.map +1 -1
- package/dist/preact/index.d.ts +34 -0
- package/dist/preact/index.d.ts.map +1 -0
- package/dist/preact/index.js +72 -0
- package/dist/preact/index.js.map +1 -0
- package/dist/react/index.d.ts +5 -14
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +9 -33
- package/dist/react/index.js.map +1 -1
- package/dist/react/server.d.ts +1 -1
- package/dist/react/server.js +1 -1
- package/dist/{sarif-CWyTAQ0y.js → sarif-BnwYC78_.js} +8 -98
- package/dist/sarif-BnwYC78_.js.map +1 -0
- package/dist/{scan-Bx0_yDSi.js → scan-C0ap4Mpp.js} +145 -20
- package/dist/scan-C0ap4Mpp.js.map +1 -0
- package/dist/solid/index.d.ts +29 -0
- package/dist/solid/index.d.ts.map +1 -0
- package/dist/solid/index.js +48 -0
- package/dist/solid/index.js.map +1 -0
- package/dist/svelte/Text.svelte +13 -0
- package/dist/svelte/Text.svelte.d.ts +20 -0
- package/dist/svelte/index.d.ts +31 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +35 -0
- package/dist/svelte/index.js.map +1 -0
- package/dist/tools.d.ts +44 -65
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +5 -5
- package/dist/vite.d.ts +13 -3
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +82 -25
- package/dist/vite.js.map +1 -1
- package/dist/vue/index.d.ts +43 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +76 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +63 -7
- package/src/bun.ts +77 -20
- package/src/cli.ts +62 -8
- package/src/index.ts +1 -1
- package/src/next-loader.ts +17 -5
- package/src/next.ts +120 -16
- package/src/preact/index.ts +91 -0
- package/src/react/index.tsx +12 -42
- package/src/runtime/bind.ts +96 -0
- package/src/runtime/copy.ts +148 -24
- package/src/solid/index.ts +67 -0
- package/src/svelte/Text.svelte +13 -0
- package/src/svelte/Text.svelte.d.ts +20 -0
- package/src/svelte/index.ts +65 -0
- package/src/tools/bundle.ts +143 -2
- package/src/tools/catalog.ts +10 -1
- package/src/tools/chunks.ts +142 -0
- package/src/tools/config.ts +25 -7
- package/src/tools/entry.ts +19 -20
- package/src/tools/exchange.ts +275 -0
- package/src/tools/extract.ts +2 -2
- package/src/tools/generate.ts +7 -1
- package/src/tools/index.ts +2 -1
- package/src/tools/native/android.ts +186 -0
- package/src/tools/native/apple.ts +201 -0
- package/src/tools/native/date.ts +219 -0
- package/src/tools/native/index.ts +17 -5
- package/src/tools/native/kotlin.ts +47 -6
- package/src/tools/native/model.ts +67 -29
- package/src/tools/native/printf.ts +137 -0
- package/src/tools/native/rust.ts +86 -5
- package/src/tools/native/swift.ts +62 -6
- package/src/tools/scan.ts +146 -25
- package/src/tools/todo.ts +6 -1
- package/src/vite.ts +121 -28
- package/src/vue/index.ts +117 -0
- package/dist/bundle-DboItAre.js +0 -111
- package/dist/bundle-DboItAre.js.map +0 -1
- package/dist/bundle-KD-DiiFa.d.ts.map +0 -1
- package/dist/compile-xF3F4oIp.d.ts +0 -16
- package/dist/compile-xF3F4oIp.d.ts.map +0 -1
- package/dist/copy-B3V_QRkT.d.ts.map +0 -1
- package/dist/copy-Bo_FIoLy.js +0 -154
- package/dist/copy-Bo_FIoLy.js.map +0 -1
- package/dist/endpoints-CnUfCkIk.js +0 -96
- package/dist/endpoints-CnUfCkIk.js.map +0 -1
- package/dist/generate-9pR3i5Bj.js.map +0 -1
- package/dist/sarif-CWyTAQ0y.js.map +0 -1
- package/dist/scan-Bx0_yDSi.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-BPSmoYel.js","names":[],"sources":["../src/tools/lint.ts","../src/tools/presets.ts","../src/tools/config.ts"],"sourcesContent":["/**\n * Holds every source message to the mechanical half of a writing guide: budgets, periods, case,\n * dashes, spelling, contractions, the product's one word per concept, and banned words. What needs\n * judgment stays with review. An entry a rule is wrong about says so under `allow`, with the reason,\n * and an exemption that no longer matches anything fails too, so none outlive the words they excused.\n *\n * The core rules are written as a plugin's are: a project adds its own through `lint.plugins`, as\n * code or as data, and they read the same readings of a message and are exempted the same way.\n */\nimport type { Message } from './catalog.ts';\nimport type { ResolvedConfig } from './config.ts';\nimport { staticLiteral, TYPE, walk, type MessageFormatElement } from './icu.ts';\nimport type { KindRule, Severity } from './presets.ts';\n\n/** What a rule is given about one message in one locale. */\nexport interface RuleContext {\n /** The entry, as the source catalog has it. */\n message: Message;\n /** The locale read: the source, or a translation's. */\n locale: string;\n /** The message in that locale. */\n ast: MessageFormatElement[];\n /** The shape the message's kind is held to, when it names a kind the config defines. */\n kind: KindRule | undefined;\n /** The message in that locale, as prose. */\n text: Readings;\n /** The source message as prose, to hold a translation to it: `text` itself in the source locale. */\n source: Readings;\n config: ResolvedConfig;\n}\n\ninterface RuleBase {\n /** One sentence: what the rule holds a string to. */\n description: string;\n /** Its severity under `extends: 'recommended'`; off when unset. */\n recommended?: Severity;\n /** Its severity under `extends: 'strict'`; `error` when unset. */\n strict?: Severity;\n /**\n * Only entries of these kinds, on these surfaces, or in these areas (a key's first segment); an\n * entry that says no kind or surface is skipped by a rule that names some. Only the source unless\n * `locale` says otherwise, since most writing rules are written for one language: `all` reads\n * every locale, and a list those languages and their regions (`de` covers `de-CH`).\n */\n on?: { kind?: string[]; surface?: string[]; area?: string[]; locale?: 'all' | string[] };\n}\n\n/** A rule written as code. */\nexport interface CheckRule extends RuleBase {\n /** What is wrong with the message, a sentence each that states the fix; none when it passes. */\n check(context: RuleContext): (string | Report)[];\n}\n\n/** A finding that can say where it is, and what to write instead. */\nexport interface Report {\n message: string;\n /** The words the finding is about, as a reading has them: found in the message's text, in any case. */\n match?: string;\n /** What `prosebook lint --fix` writes in place of `match`, wherever it stands; its case follows the text's. */\n fix?: string;\n}\n\n/** A replacement in a message's text, by offset. */\nexport interface Edit {\n start: number;\n end: number;\n text: string;\n}\n\n/*\n * Rules written as data, after Vale's, so a JSON config can carry them. Words and patterns are looked\n * for in every reading, so one in a `one` arm is found; counts and case read the `other` arms. A\n * pattern is a regular expression with the `u` flag, and sees a placeholder as `HOLE`. A message\n * names what was found with `{match}`, and the other fields its rule lists.\n */\n\n/** Words or patterns a string never uses. */\nexport interface ExistenceRule extends RuleBase {\n type: 'existence';\n /** Words or phrases, matched whole and in any case. `{match}` is the one listed. */\n words?: string[];\n /** `{match}` is the text matched. */\n patterns?: string[];\n ignoreCase?: boolean;\n message: string;\n}\n\n/** A word or phrase the product writes another way. */\nexport interface SubstitutionRule extends RuleBase {\n type: 'substitution';\n /** A word or phrase, matched whole and in any case, and the one written instead. */\n swap: Record<string, string>;\n /** `{match}` and `{use}`; `\"{match}\" is written \"{use}\"` when unset. */\n message?: string;\n}\n\n/** A budget, beside the one a kind sets: per surface, say, or in characters. */\nexport interface OccurrenceRule extends RuleBase {\n type: 'occurrence';\n /** Every word, placeholders included; sentences; or characters, placeholders not included. */\n count: 'words' | 'sentences' | 'characters';\n max?: number;\n min?: number;\n /** `max` and `min` are multiples of the source's count: `max: 1.4` is 40% longer than the source at most. */\n relative?: boolean;\n /** `{count}`, `{max}`, `{min}`, and with `relative`, `{source}` (the source's count) and `{limit}`. */\n message?: string;\n}\n\nexport interface CapitalizationRule extends RuleBase {\n type: 'capitalization';\n /** `sentence` capitalizes only the first word and proper nouns, `title` every word but short function words. */\n case: 'sentence' | 'title' | 'lower' | 'upper';\n /** Words that keep their case, beside `lint.properNouns`. */\n exceptions?: string[];\n /** `{match}` is the first word out of case. */\n message?: string;\n}\n\n/** A string that matches `when` (every string, when unset) matches `require` too. */\nexport interface ConditionalRule extends RuleBase {\n type: 'conditional';\n when?: string;\n require: string;\n ignoreCase?: boolean;\n /** `{match}` is the text `when` matched. */\n message: string;\n}\n\nexport type Rule = CheckRule | ExistenceRule | SubstitutionRule | OccurrenceRule | CapitalizationRule | ConditionalRule;\n\n/** A set of rules, named `<name>/<rule>` in `lint.rules` and in an entry's `allow`. */\nexport interface Plugin {\n name: string;\n rules: Record<string, Rule>;\n}\n\n/** Typed plugin, for `lint.plugins`. */\nexport function definePlugin(plugin: Plugin): Plugin {\n return plugin;\n}\n\nexport interface Finding {\n key: string;\n /** The catalog file, or for a translation, the locale's file. */\n file: string;\n /** The locale whose text the finding is about; the source for an `allow` finding. */\n locale: string;\n /** The rule's name, or `allow` for an exemption that is itself wrong. */\n rule: string;\n severity: Exclude<Severity, 'off'>;\n message: string;\n /** Where in the locale's message text, when the rule named a match and it is written there as read. */\n at?: { start: number; end: number };\n /** The edits that fix it, at every place the match stands. */\n fix?: Edit[];\n}\n\n/** Stands in for a placeholder in a reading, which no prose rule reads. */\nexport const HOLE = '\\u2063';\n/** Tags whose content is code or a literal the reader types, not prose. */\nconst VERBATIM_TAGS = new Set(['code', 'mono', 'kbd', 'keycap', 'nums']);\n\nfunction renderAs(elements: MessageFormatElement[], arm: string | null): string {\n let out = '';\n for (const el of elements) {\n if (el.type === TYPE.literal) {\n out += el.value;\n } else if (el.type === TYPE.tag) {\n out += VERBATIM_TAGS.has(el.value) ? HOLE : renderAs(el.children, arm);\n } else if (el.type === TYPE.plural || el.type === TYPE.select) {\n const option = arm === null ? undefined : (el.options[arm] ?? el.options['other']);\n out += option === undefined ? HOLE : renderAs(option.value, arm);\n } else {\n out += HOLE;\n }\n }\n return out;\n}\n\n/** The message as prose: placeholders and verbatim tags read as `HOLE`, and `’` as `'` in `variants`. */\nexport interface Readings {\n /** Every `other` arm taken: what a budget is measured on. */\n primary: string;\n /** One reading per arm, so a word hidden in `one` is still found. */\n variants: string[];\n /** Only the words the message always carries. */\n skeleton: string;\n}\n\nfunction readings(message: MessageFormatElement[]): Readings {\n const literal = staticLiteral(message);\n const ast = literal === undefined ? message : ([{ type: TYPE.literal, value: literal }] as MessageFormatElement[]);\n const arms = new Set<string>();\n const collect = (els: MessageFormatElement[]) => {\n for (const el of els) {\n if (el.type === TYPE.plural || el.type === TYPE.select) {\n for (const [name, option] of Object.entries(el.options)) {\n arms.add(name);\n collect(option.value);\n }\n }\n if (el.type === TYPE.tag) collect(el.children);\n }\n };\n collect(ast);\n const primary = renderAs(ast, 'other');\n const variants = new Set([primary, ...[...arms].map((arm) => renderAs(ast, arm))]);\n return { primary, variants: [...variants].map((v) => v.replace(/\\u2019/g, \"'\")), skeleton: renderAs(ast, null) };\n}\n\n/** What a reader sees end to end, less a placeholder appended at the very end. */\nconst prose = (text: string) => text.replace(new RegExp(`[\\\\s${HOLE}]+$`), '');\n\nconst FREE = new Set('a an the this that these those it its them your and or to of for by in on at from with'.split(' '));\n\nconst tokens = (text: string) => text.split(/\\s+/).filter((w) => /[\\p{L}\\p{N}]/u.test(w) || w.includes(HOLE));\n\n/** The words a budget counts: articles, short prepositions and asides in parentheses are free. */\nexport function words(text: string): string[] {\n return tokens(text.replace(/\\s*\\([^)]*\\)/g, '')).filter((w) => !FREE.has(w.toLowerCase().replace(/[^\\p{L}]/gu, '')));\n}\n\nconst ABBREVIATIONS = /\\b(?:e\\.g|i\\.e|vs|etc)\\.$/i;\n\nexport function sentences(text: string): number {\n let count = 1;\n const boundary = /[.!?…]+[\"')\\]]*\\s+(?=\\S)/g;\n for (let m = boundary.exec(text); m !== null; m = boundary.exec(text))\n if (!ABBREVIATIONS.test(text.slice(0, m.index + m[0].trimEnd().length))) count += 1;\n\n return count;\n}\n\n/** A word or phrase on its own, not inside a longer word or a hyphenated compound. */\nexport function phrase(p: string): RegExp {\n const escaped = p.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/ /g, '\\\\s+');\n return new RegExp(`(?<![\\\\p{L}\\\\p{N}'-])${escaped}(?![\\\\p{L}\\\\p{N}'-])`, 'iu');\n}\n\n/** The words and phrases of `list` that some reading carries. */\nconst listed = (variants: string[], list: string[]) => list.filter((w) => variants.some((v) => phrase(w).test(v)));\n\nconst unquoted = (token: string) => token.replace(/^[(\"'“‘]+|[)\"'”’.,:;!?]+$/g, '');\n\nfunction capitalizedWord(text: string, proper: Set<string>): string | undefined {\n const parts = text.split(/\\s+/).filter(Boolean);\n for (let i = 1; i < parts.length; i++) {\n const word = unquoted(parts[i]!);\n if (!/^\\p{Lu}\\p{Ll}/u.test(word) || proper.has(word)) continue;\n if (/[.:?!][\"')]*$/.test(parts[i - 1]!)) continue;\n return word;\n }\n return undefined;\n}\n\n/** Words a count is followed by that are not plural nouns, though they end in s. */\nconst NOT_PLURAL = new Set([\n 'is',\n 'was',\n 'has',\n 'does',\n 'this',\n 'its',\n 'plus',\n 'minus',\n 'less',\n 'yes',\n 'us',\n 'as',\n 'bus',\n 'gas',\n 'news',\n 'series',\n]);\n\n/**\n * The singular of an English plural noun, or nothing where it doesn't look like one. A word with no\n * vowel is a unit or an abbreviation (`kbps`, `fps`, `hrs`), which reads the same after 1.\n */\nexport function singularOf(word: string): string | undefined {\n const lower = word.toLowerCase();\n if (word.length < 3 || !lower.endsWith('s') || lower.endsWith('ss') || NOT_PLURAL.has(lower)) return undefined;\n if (!/[aeiouy]/.test(lower)) return undefined;\n if (/[^aeiou]ies$/.test(lower)) return `${word.slice(0, -3)}y`;\n if (/(?:s|x|z|ch|sh)es$/.test(lower)) return word.slice(0, -2);\n return word.slice(0, -1);\n}\n\nconst MINOR = new Set('a an the and but or nor for so yet as at by in of off on per to up via with'.split(' '));\n\n/** The first word out of `style` case, less those in `keep`. */\nfunction outOfCase(text: string, style: CapitalizationRule['case'], keep: Set<string>): string | undefined {\n if (style === 'sentence') return capitalizedWord(text, keep);\n const list = text\n .split(/\\s+/)\n .map(unquoted)\n .filter((w) => /\\p{L}/u.test(w) && !keep.has(w));\n return list.find((w, i) => {\n if (style === 'lower') return /\\p{Lu}/u.test(w);\n if (style === 'upper') return /\\p{Ll}/u.test(w);\n return /^\\p{Ll}/u.test(w) && (i === 0 || !MINOR.has(w));\n });\n}\n\nconst CONTRACTIONS: [RegExp, string][] = [\n [/\\bcannot\\b/i, \"can't\"],\n [/\\bcan not\\b/i, \"can't\"],\n [/\\bwill not\\b/i, \"won't\"],\n [/\\b(could|would|should|is|are|was|were|do|does|did|has|have|had|must|need) not\\b/i, \"n't\"],\n];\n\n/** Calls `visit` on every run of elements that sit side by side, with the arguments a plural around it counts. */\nfunction eachRun(\n elements: MessageFormatElement[],\n visit: (run: MessageFormatElement[], counted: ReadonlySet<string>) => void,\n counted: ReadonlySet<string> = new Set(),\n): void {\n visit(elements, counted);\n for (const el of elements) {\n if (el.type === TYPE.plural) for (const o of Object.values(el.options)) eachRun(o.value, visit, new Set([...counted, el.value]));\n if (el.type === TYPE.select) for (const o of Object.values(el.options)) eachRun(o.value, visit, counted);\n if (el.type === TYPE.tag) eachRun(el.children, visit, counted);\n }\n}\n\n/** A plain placeholder named as a count. A number placeholder is one whatever its name. */\nconst COUNT_NAME = /^(?:n|num|count|total|amount|quantity)$|(?:count|total)$/i;\n\n/**\n * Whether an arm ends with a stop; nothing for an arm with no words, or one that trails off in an\n * ellipsis (`Saving…`, `Save as…`), which is neither. Which stop is the arm's own: a question in\n * `one` and a second sentence after it in `other` both end well.\n */\nfunction endsWithStop(arm: MessageFormatElement[]): boolean | undefined {\n const text = prose(renderAs(arm, 'other')).trim();\n if (text.replaceAll(HOLE, '').trim() === '' || /(?:…|\\.{3})[\"')”»」』]*$/u.test(text)) return undefined;\n return hasStop(text);\n}\n\n/** Ends with a stop in any script (`。`, `؟`, `;` as Greek writes `?`), though not a comma. */\nconst hasStop = (text: string) => /(?![,,、،])[\\p{Terminal_Punctuation}…][\"')”»」』]*$/u.test(prose(text).trim());\n\nconst CURRENCY_BEFORE = /[$€£¥₹]\\s?$/;\n\n/**\n * The ways a path through menus is written, the separator in a group: an arrow or `›` however\n * spaced, and `>` or `/` only spaced between words or placeholders, with a capital after a slash,\n * since \"2 > 1\" and \"and / or\" are no paths. The match takes the spaces around, so the fix spaces\n * the separator.\n */\nconst PATH_SEPARATORS = new RegExp(\n String.raw`\\s*(→|->|›)\\s*|(?<=[\\p{L}${HOLE}])\\s+(>)\\s+(?=[\\p{L}${HOLE}])|(?<=\\p{L})\\s+(\\/)\\s+(?=\\p{Lu})`,\n 'gu',\n);\n\nconst OFF_SCREEN = new Set(['aria']);\n\nconst an = (word = 'string') => `${/^[aeiou]/i.test(word) ? 'an' : 'a'} ${word}`;\n\nexport const CORE_RULES = {\n whitespace: {\n description: 'No leading, trailing or doubled spaces.',\n recommended: 'error',\n on: { locale: 'all' },\n check: ({ text }) => {\n const message = 'no leading, trailing or doubled spaces';\n // As a match, two spaces stand for a run of any length.\n if (text.variants.some((v) => v.includes(' '))) return [{ message, match: ' ', fix: ' ' }];\n return text.variants.some((v) => /^\\s|\\s$/.test(v.replaceAll(HOLE, 'x'))) ? [message] : [];\n },\n },\n 'word-budget': {\n description: \"A kind with `maxWords` stays within it. Articles, short prepositions and asides in parentheses don't count.\",\n recommended: 'warn',\n check: ({ message: m, kind, text }) => {\n if (kind?.maxWords === undefined || OFF_SCREEN.has(m.surface ?? '')) return [];\n const n = words(text.primary).length;\n return n > kind.maxWords ? [`${an(m.kind)} is ${kind.maxWords} words at most, and this is ${n}`] : [];\n },\n },\n 'sentence-budget': {\n description: 'A kind with `maxSentences` stays within it.',\n recommended: 'warn',\n check: ({ message: m, kind, text }) => {\n const most = (m.surface !== undefined ? kind?.maxSentencesOn?.[m.surface] : undefined) ?? kind?.maxSentences;\n if (most === undefined) return [];\n const n = sentences(prose(text.primary));\n return n > most\n ? [\n `${an(m.kind)}${kind?.maxSentencesOn?.[m.surface ?? ''] !== undefined ? ` on ${m.surface}` : ''} is ${most} sentence(s) at most, and this is ${n}`,\n ]\n : [];\n },\n },\n period: {\n description: 'A kind with `period: always` (or on a listed surface) ends with a period, unless the entry is a fragment.',\n recommended: 'warn',\n check: ({ message: m, kind, text }) => {\n const rule = kind?.period;\n const applies = rule === 'always' || (Array.isArray(rule) && rule.includes(m.surface ?? ''));\n return applies && !m.fragment && !/[.?!…:][\"')”]*$/.test(prose(text.primary))\n ? [`${an(m.kind)} ends with a period, or is marked fragment: true`]\n : [];\n },\n },\n 'no-period': {\n description: 'A kind with `period: never` ends without one.',\n recommended: 'warn',\n check: ({ message: m, kind, text }) =>\n kind?.period === 'never' && /[^.]\\.$/.test(prose(text.primary)) ? [`${an(m.kind)} ends without a period`] : [],\n },\n 'bare-name': {\n description: 'A kind with `bare: true` carries no explanation after a dash or a colon.',\n recommended: 'warn',\n // A colon before a value is a readout, as in \"Zoom: 120%\", not an explanation.\n check: ({ message: m, kind, text }) =>\n kind?.bare === true && new RegExp(`\\\\s[—–-]\\\\s|\\\\p{L}:\\\\s(?!${HOLE})`, 'u').test(text.skeleton)\n ? [`${an(m.kind)} carries no explanation after a dash or a colon`]\n : [],\n },\n 'sentence-case': {\n description: 'A kind with `sentenceCase: true` capitalizes only its first word and proper nouns.',\n check: ({ message: m, kind, text, config }) => {\n if (kind?.sentenceCase !== true) return [];\n const word = outOfCase(text.primary, 'sentence', new Set(config.lint.properNouns));\n if (word === undefined) return [];\n return [\n { message: `\"${word}\" is capitalized in a sentence-case ${m.kind}: add it to lint.properNouns if it is a name`, match: word },\n ];\n },\n },\n 'banned-word': {\n description: 'A word or phrase from the banned lists.',\n recommended: 'warn',\n check: ({ text, config }) =>\n config.lint.banned.flatMap(({ words: list, why }) =>\n listed(text.variants, list).map((w) => ({ message: `\"${w}\" ${why}`, match: w })),\n ),\n },\n spelling: {\n description: 'A spelling the product writes another way.',\n recommended: 'warn',\n check: ({ text, config: { lint } }) =>\n listed(text.variants, Object.keys(lint.spelling)).map((w) => ({\n message: `\"${w}\" is spelled \"${lint.spelling[w]}\"`,\n match: w,\n fix: lint.spelling[w],\n })),\n },\n 'one-word': {\n description: 'A near-synonym for a concept the product has one word for.',\n recommended: 'warn',\n check: ({ text, config: { lint } }) =>\n listed(text.variants, Object.keys(lint.concepts)).map((w) => ({\n message: `\"${w}\" is \"${lint.concepts[w]}\" everywhere in the product`,\n match: w,\n fix: lint.concepts[w],\n })),\n },\n 'no-em-dash': {\n description: 'No em-dashes, and no spaced hyphen standing in for one.',\n check: ({ text }) => {\n const match = text.variants.map((v) => /—|\\s[–-]\\s/.exec(v)?.[0]).find((m) => m !== undefined);\n return match === undefined ? [] : [{ message: 'no em-dash: a comma, a period or a colon does the job', match }];\n },\n },\n path: {\n description: 'A path through menus or settings is written with `lint.pathSeparator`, spaced: Settings › General.',\n check: ({ text, config }) => {\n const use = config.lint.pathSeparator;\n for (const v of text.variants) {\n for (const m of v.matchAll(PATH_SEPARATORS)) {\n if ((m[1] ?? m[2] ?? m[3]) === use) continue;\n return [{ message: `a path is written with a spaced ${use}`, match: m[0], fix: ` ${use} ` }];\n }\n }\n return [];\n },\n },\n contractions: {\n description: '`could not`, `is not` and `cannot` are written as contractions.',\n check: ({ text }) =>\n CONTRACTIONS.flatMap(([pattern, short]) => {\n const found = text.variants.map((v) => pattern.exec(v)).find((f) => f !== null);\n if (found === undefined || found === null) return [];\n const fix = short === \"n't\" ? `${found[1]}n't` : short;\n return [{ message: `\"${found[0]}\" is written as a contraction (${short})`, match: found[0], fix }];\n }),\n },\n ellipsis: {\n description: 'An ellipsis is one character, `…`, not three periods.',\n on: { locale: 'all' },\n check: ({ text }) =>\n text.variants.some((v) => v.includes('...')) ? [{ message: 'an ellipsis is one character: …', match: '...', fix: '…' }] : [],\n },\n 'plural-count': {\n description: 'A count followed by a plural noun, `{count} files`, is a plural, or it reads \"1 files\". English.',\n recommended: 'warn',\n check: ({ ast }) => {\n const said: Report[] = [];\n eachRun(ast, (run, counted) =>\n run.forEach((el, i) => {\n if (el.type !== TYPE.number && el.type !== TYPE.argument) return;\n if (counted.has(el.value) || (el.type === TYPE.argument && !COUNT_NAME.test(el.value))) return;\n const next = run[i + 1];\n const word = next?.type === TYPE.literal ? /^\\s+(\\p{L}+)(?![\\p{L}'])/u.exec(next.value)?.[1] : undefined;\n const one = word === undefined ? undefined : singularOf(word);\n if (word !== undefined && one !== undefined) {\n said.push({\n message: `${el.value} is followed by \"${word}\", which reads \"1 ${word}\": make it a plural with a \"# ${one}\" arm`,\n match: word,\n });\n }\n }),\n );\n return said;\n },\n },\n 'plural-one': {\n description: \"A plural's `one` arm says something other than `other`, and says `#` rather than `1`.\",\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ ast, locale, config }) => {\n const said: Report[] = [];\n walk(ast, (el) => {\n if (el.type !== TYPE.plural || el.pluralType !== 'cardinal') return;\n const { one, other } = el.options;\n if (one === undefined) return;\n // Turkish says \"# dosya\" for one and other alike, so only the source must tell them apart.\n if (locale === config.source && other !== undefined && renderAs(one.value, 'other') === renderAs(other.value, 'other'))\n said.push({ message: `the one and other arms of ${el.value} say the same: write the singular in one` });\n let literalOne = false;\n walk(one.value, (inner) => {\n if (inner.type === TYPE.literal && /(?<![\\d.,])1(?![\\d.,])/.test(inner.value)) literalOne = true;\n });\n // Russian's `one` is also 21 and 31, so a translator copying a written 1 gets it wrong there.\n if (!literalOne) return;\n const message = `the one arm of ${el.value} writes 1, which one is not in every language: write #, or make the arm =1`;\n said.push({ message, match: '1' });\n });\n return said;\n },\n },\n 'arm-endings': {\n description: 'The arms of a plural or select end alike: all with a stop, or all without one.',\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ ast }) => {\n const said: string[] = [];\n walk(ast, (el) => {\n if (el.type !== TYPE.plural && el.type !== TYPE.select) return;\n const endings = new Set(Object.values(el.options).flatMap((o) => endsWithStop(o.value) ?? []));\n if (endings.size > 1) said.push(`some arms of ${el.value} end with a stop and some without: end them alike`);\n });\n return said;\n },\n },\n 'formatted-by-hand': {\n description: 'A currency symbol or `%` typed beside a placeholder, or digits grouped by hand, which only suit one locale.',\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ ast, text }) => {\n const said = new Map<string, Report>();\n const say = (message: string, match: string) => said.set(message, { message, match });\n eachRun(ast, (run) =>\n run.forEach((el, i) => {\n if (el.type !== TYPE.number && el.type !== TYPE.argument) return;\n const before = run[i - 1];\n const after = run[i + 1];\n const symbol = before?.type === TYPE.literal ? CURRENCY_BEFORE.exec(before.value)?.[0].trim() : undefined;\n if (symbol !== undefined)\n say(`\"${symbol}\" is typed before ${el.value}: format it as a currency, which puts the symbol where the locale does`, symbol);\n if (after?.type === TYPE.literal && /^\\s?%/.test(after.value))\n say(`\"%\" is typed after ${el.value}: format it as a percent, which takes the fraction (0.5 for 50%)`, '%');\n }),\n );\n const grouped = text.variants.map((v) => /\\d{1,3}(?:,\\d{3})+(?!\\d)/.exec(v)?.[0]).find((g) => g !== undefined);\n if (grouped !== undefined)\n say(`\"${grouped}\" groups its digits the English way: make it a placeholder formatted as a number`, grouped);\n return [...said.values()];\n },\n },\n 'source-ending': {\n description: 'A translation ends with a stop where its source does, and without one where it does not.',\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ text, source }) => {\n const ends = hasStop(text.primary);\n if (ends === hasStop(source.primary)) return [];\n return [\n ends\n ? 'ends with a stop, and the source does not: drop it'\n : 'the source ends with a stop, and this does not: end it as the source does',\n ];\n },\n },\n} satisfies Record<string, CheckRule>;\n\nexport type CoreRule = keyof typeof CORE_RULES;\n\nconst fill = (message: string, values: Record<string, string | number | undefined>) =>\n message.replace(/\\{(\\w+)\\}/g, (all, name: string) => (values[name] === undefined ? all : String(values[name])));\n\nconst graphemes = new Intl.Segmenter();\n\nconst COUNTERS: Record<OccurrenceRule['count'], (text: string) => number> = {\n words: (text) => tokens(text).length,\n sentences: (text) => sentences(prose(text)),\n characters: (text) => [...graphemes.segment(text.replaceAll(HOLE, ''))].length,\n};\n\n/** A rule as code, checked once when the config loads: a JSON config is not type-checked. */\nexport function compileRule(name: string, rule: Rule): CheckRule {\n const fail = (problem: string): never => {\n throw new Error(`lint rule ${name} ${problem}`);\n };\n const pattern = (source: unknown, field: string, ignoreCase: boolean | undefined) => {\n if (typeof source !== 'string') return fail(`${field} is not a string: write the pattern as one`);\n try {\n return new RegExp(source, ignoreCase === true ? 'iu' : 'u');\n } catch (e) {\n return fail(`${field} is not a regular expression: ${e instanceof Error ? e.message : String(e)}`);\n }\n };\n const said = (message: unknown) =>\n typeof message === 'string' && message !== '' ? message : fail('has no message: say what to write instead');\n if (typeof rule.description !== 'string' || rule.description === '') fail('has no description: say what it holds a string to');\n if ('check' in rule) return typeof rule.check === 'function' ? rule : fail('has a check that is not a function');\n const { description, recommended, strict, on } = rule;\n const base = { description, recommended, strict, on };\n switch (rule.type) {\n case 'existence': {\n const list = rule.words ?? [];\n const patterns = (rule.patterns ?? []).map((p, i) => pattern(p, `patterns[${i}]`, rule.ignoreCase));\n if (list.length + patterns.length === 0) fail('has no words or patterns: list what a string never says');\n const message = said(rule.message);\n return {\n ...base,\n check: ({ text }) => {\n const matched = patterns.flatMap((p) => text.variants.map((v) => p.exec(v)?.[0]).find((m) => m !== undefined) ?? []);\n return [...new Set([...listed(text.variants, list), ...matched])].map((match) => ({ message: fill(message, { match }), match }));\n },\n };\n }\n case 'substitution': {\n const swap = rule.swap ?? {};\n if (Object.keys(swap).length === 0) fail('has nothing in swap: map a word to the one written instead');\n const message = rule.message === undefined ? '\"{match}\" is written \"{use}\"' : said(rule.message);\n return {\n ...base,\n check: ({ text }) =>\n listed(text.variants, Object.keys(swap)).map((match) => ({\n message: fill(message, { match, use: swap[match] }),\n match,\n fix: swap[match],\n })),\n };\n }\n case 'occurrence': {\n const { count: unit, max, min, relative } = rule;\n const counter = Object.hasOwn(COUNTERS, unit) ? COUNTERS[unit] : fail(`counts ${unit}: count words, sentences or characters`);\n if (max === undefined && min === undefined) fail('has no max or min: give it one');\n if (rule.message !== undefined) said(rule.message);\n return {\n ...base,\n check: ({ text, source }) => {\n const count = counter(text.primary);\n const of = relative === true ? counter(source.primary) : 1;\n const over = max !== undefined && count > max * of;\n const under = min !== undefined && count < min * of;\n if (!over && !under) return [];\n // The limit shown is one the count could meet: 1.5 times 11 characters is 16 at most, 17 at least.\n const limit = over && max !== undefined ? Math.floor(max * of) : Math.ceil((min ?? 0) * of);\n const bound = over ? 'at most' : 'at least';\n const fallback =\n relative === true\n ? `{limit} ${unit} ${bound} ({${over ? 'max' : 'min'}} times the source's {source}), and this is {count}`\n : `{${over ? 'max' : 'min'}} ${unit} ${bound}, and this is {count}`;\n return [fill(rule.message ?? fallback, { count, max, min, source: relative === true ? of : undefined, limit })];\n },\n };\n }\n case 'capitalization': {\n const style = rule.case;\n if (!['sentence', 'title', 'lower', 'upper'].includes(style)) fail(`has case ${style}: use sentence, title, lower or upper`);\n const message =\n rule.message === undefined\n ? `\"{match}\" is out of ${style} case: change it, or add it to exceptions if it is a name`\n : said(rule.message);\n const exceptions = rule.exceptions ?? [];\n return {\n ...base,\n check: ({ text, config }) => {\n const match = outOfCase(text.primary, style, new Set([...config.lint.properNouns, ...exceptions]));\n return match === undefined ? [] : [{ message: fill(message, { match }), match }];\n },\n };\n }\n case 'conditional': {\n const when = rule.when === undefined ? undefined : pattern(rule.when, 'when', rule.ignoreCase);\n const required = pattern(rule.require, 'require', rule.ignoreCase);\n const message = said(rule.message);\n return {\n ...base,\n check: ({ text }) => {\n for (const v of text.variants) {\n const match = when === undefined ? '' : when.exec(v)?.[0];\n if (match !== undefined && !required.test(v)) return [fill(message, { match })];\n }\n return [];\n },\n };\n }\n default:\n return fail(\n `has type ${String((rule as { type?: unknown }).type)}: use existence, substitution, occurrence, capitalization or conditional, or give it a check`,\n );\n }\n}\n\n/** A reason is a sentence a reviewer can check, not a shrug. */\nfunction reasonProblem(why: string): string | undefined {\n if (why.split(/\\s+/).length < 4) return 'is four words at least: say why the rule is wrong here';\n if (/^(?:intentional|needed|required|ok|fine|false positive|by design|legacy|todo)\\b/i.test(why))\n return 'names the reason, not that there is one';\n return undefined;\n}\n\n/** A locale is one a rule reads when it names its language, or the locale and a region of it. */\nconst readsLocale = (locales: 'all' | string[] | undefined, locale: string, sourceLocale: string) =>\n locales === undefined\n ? locale === sourceLocale\n : locales === 'all' ||\n locales.some((l) => locale.toLowerCase() === l.toLowerCase() || locale.toLowerCase().startsWith(`${l.toLowerCase()}-`));\n\nfunction applies(rule: RuleBase, message: Message, locale: string, sourceLocale: string): boolean {\n const { kind, surface, area, locale: locales } = rule.on ?? {};\n return (\n readsLocale(locales, locale, sourceLocale) &&\n (kind === undefined || (message.kind !== undefined && kind.includes(message.kind))) &&\n (surface === undefined || (message.surface !== undefined && surface.includes(message.surface))) &&\n (area === undefined || area.includes(message.area))\n );\n}\n\n/** A rule's severity for an entry: its area's, where `lint.areas` sets one. */\nexport const severityOf = (config: ResolvedConfig, name: string, message: Message): Severity | undefined =>\n config.lint.areas[message.area]?.[name] ?? config.lint.rules[name]?.severity;\n\ninterface Literal {\n start: number;\n value: string;\n}\n\n/**\n * Where the message's literals are written in its text, each looked for after the one before. A\n * literal escaped in the text (`''`, `\\{`) isn't written as read, so it has no place, and nor does a\n * finding in it.\n */\nfunction literalsIn(ast: MessageFormatElement[], text: string): Literal[] {\n const found: Literal[] = [];\n let from = 0;\n walk(ast, (el) => {\n if (el.type !== TYPE.literal || el.value === '') return;\n // MF2's `.match` is read into arms in another order than they are written, so look from the top too.\n const next = text.indexOf(el.value, from);\n const start = next === -1 ? text.indexOf(el.value) : next;\n if (start === -1) return;\n found.push({ start, value: el.value });\n from = start + el.value.length;\n });\n return found;\n}\n\n/** Every place `match` stands in the literals, in any case, whole where it starts or ends with a letter. */\nfunction placesOf(match: string, literals: Literal[]): { start: number; end: number }[] {\n const body = match\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/ /g, '\\\\s+')\n .replace(/'/g, \"['’]\");\n const before = /^[\\p{L}\\p{N}]/u.test(match) ? '(?<![\\\\p{L}\\\\p{N}])' : '';\n const after = /[\\p{L}\\p{N}]$/u.test(match) ? '(?![\\\\p{L}\\\\p{N}])' : '';\n const pattern = new RegExp(`${before}${body}${after}`, 'giu');\n const places = new Map<number, number>();\n for (const { start, value } of literals)\n for (const m of value.matchAll(pattern)) places.set(start + m.index, start + m.index + m[0].length);\n return [...places].sort(([a], [b]) => a - b).map(([start, end]) => ({ start, end }));\n}\n\n/** A fix in the case of what it replaces: \"Colour\" becomes \"Color\". */\nconst inCaseOf = (found: string, fix: string) =>\n /^\\p{Lu}/u.test(found) && /^\\p{Ll}/u.test(fix) ? fix.charAt(0).toUpperCase() + fix.slice(1) : fix;\n\n/** `text` with the edits made, leaving out any that overlaps one before it. */\nexport function applyEdits(text: string, edits: Edit[]): string {\n let out = '';\n let at = 0;\n for (const edit of [...edits].sort((a, b) => a.start - b.start)) {\n if (edit.start < at) continue;\n out += text.slice(at, edit.start) + edit.text;\n at = edit.end;\n }\n return out + text.slice(at);\n}\n\nexport function lint(messages: Message[], config: ResolvedConfig): Finding[] {\n const findings: Finding[] = [];\n const rules = Object.entries(config.lint.rules);\n for (const message of messages) {\n const kind = message.kind === undefined ? undefined : config.kinds[message.kind];\n const source = readings(message.ast);\n const locales = [\n { locale: config.source, ast: message.ast, written: message.text, file: message.file },\n ...[...message.translations].map(([locale, t]) => ({ locale, ast: t.ast, written: t.text, file: t.file })),\n ];\n // An exemption is the entry's, so it holds in every locale, and is still needed if any locale needs it.\n const fired = new Set<string>();\n for (const { locale, ast, written, file } of locales) {\n const text = locale === config.source ? source : readings(ast);\n const context: RuleContext = { message, locale, ast, kind, text, source, config };\n let literals: Literal[] | undefined;\n for (const [name, { rule }] of rules) {\n const severity = severityOf(config, name, message)!;\n if (severity === 'off' || !applies(rule, message, locale, config.source)) continue;\n let said: (string | Report)[];\n try {\n said = rule.check(context);\n } catch (cause) {\n throw new Error(`lint rule ${name} failed on ${message.key} in ${locale}: fix or turn off the rule`, { cause });\n }\n if (said.length === 0) continue;\n fired.add(name);\n if (message.allow.has(name)) continue;\n for (const s of said) {\n const { message: text, match, fix } = typeof s === 'string' ? { message: s } : s;\n const finding: Finding = { key: message.key, file, locale, rule: name, severity, message: text };\n if (match !== undefined && match !== '') {\n literals ??= literalsIn(ast, written);\n const places = placesOf(match, literals);\n if (places.length > 0) finding.at = places[0];\n if (places.length > 0 && fix !== undefined)\n finding.fix = places.map((p) => ({ ...p, text: inCaseOf(written.slice(p.start, p.end), fix) }));\n }\n findings.push(finding);\n }\n }\n }\n for (const [name, why] of message.allow) {\n const at = { key: message.key, file: message.file, locale: config.source, rule: 'allow', severity: 'error' as const };\n const rule = config.lint.rules[name];\n if (rule === undefined) {\n findings.push({ ...at, message: `allow.${name} is not a rule: ${rules.map(([n]) => n).join(', ')}` });\n } else if (severityOf(config, name, message) === 'off') {\n continue;\n } else if (!fired.has(name)) {\n findings.push({ ...at, message: `allow.${name} exempts the entry from a rule it passes: remove it` });\n } else {\n const problem = reasonProblem(why);\n if (problem !== undefined) findings.push({ ...at, message: `allow.${name} ${problem}` });\n }\n }\n }\n return findings;\n}\n","/**\n * The defaults: four kinds of string, the surfaces they sit on, and the word lists of the strict lint preset.\n *\n * The kinds are the four any UI writing guide comes down to. A name identifies, an action says what\n * pressing it does, a description adds what the name cannot carry, a state reports what is true.\n * Each carries a budget and a grammar, which is what makes a mechanical check of the words possible.\n */\nexport type Severity = 'error' | 'warn' | 'off';\n\nexport interface KindRule {\n /** What the kind is for, shown when an editor completes it. */\n doc: string;\n /** The most words it may have. Articles, short prepositions and asides in parentheses are free. */\n maxWords?: number;\n /** The most sentences it may have, and per surface where that differs. */\n maxSentences?: number;\n maxSentencesOn?: Record<string, number>;\n /** Whether it ends with a period: always, never, or only on the surfaces listed. */\n period?: 'always' | 'never' | string[];\n /** Capitalizes only its first word and proper nouns. */\n sentenceCase?: boolean;\n /** Carries no explanation after a dash or colon: `Quick capture`, not `Quick capture: choose an area`. */\n bare?: boolean;\n}\n\nexport const DEFAULT_KINDS: Record<string, KindRule> = {\n name: {\n doc: 'Identifies a thing so it can be found again. One to four words, a noun phrase, no period.',\n maxWords: 4,\n period: 'never',\n sentenceCase: true,\n bare: true,\n },\n action: {\n doc: 'Says what pressing it does. One to three words, verb first, no period.',\n maxWords: 3,\n period: 'never',\n sentenceCase: true,\n },\n description: {\n doc: 'Adds only what the name cannot carry. One sentence, two at most, with a period.',\n maxSentences: 2,\n period: 'always',\n },\n state: {\n doc: 'Reports what is true right now. One sentence, present tense; on an error or empty state, one more saying what to do.',\n maxSentences: 1,\n maxSentencesOn: { error: 2, empty: 2, hint: 2, status: 2 },\n period: ['hint', 'status', 'error', 'empty', 'confirm'],\n },\n};\n\nexport const DEFAULT_SURFACES: Record<string, string> = {\n action: 'The text of a button or a menu entry.',\n aria: 'Reached only by a screen reader, so nothing on screen carries it.',\n choice: 'One option among a set offered together.',\n confirm: 'The question of a confirmation, or the verb that answers it.',\n empty: 'Fills a list or a panel that has nothing in it.',\n error: 'Says what failed.',\n heading: 'Heads a section, group, dialog or list.',\n hint: 'A subordinate line under the thing it qualifies.',\n label: 'Names a control, a field, a section or a destination.',\n placeholder: 'Sits inside an empty field, and goes when typing starts.',\n status: 'Reports what is true right now, on a badge or beside a row.',\n title: 'The title of a page, window or document.',\n toast: 'A notification that comes and goes.',\n tooltip: 'Appears on hover.',\n};\n\n/** The word lists of the strict preset: filler, marketing and reassurance, and American spelling. */\nexport const STRICT_LISTS = {\n banned: [\n {\n words: ['seamless', 'seamlessly', 'effortless', 'effortlessly', 'hassle-free', 'frictionless'],\n why: 'promises a feeling rather than saying what happens',\n },\n {\n words: ['leverage', 'leverages', 'leveraging', 'utilize', 'utilizes', 'utilizing', 'harness', 'take advantage of'],\n why: 'is a long way to say use',\n },\n {\n words: [\n 'delve',\n 'dive into',\n 'deep dive',\n 'embark',\n 'journey',\n 'tapestry',\n 'realm',\n 'landscape',\n 'testament',\n 'synergy',\n 'paradigm',\n 'holistic',\n ],\n why: 'is filler, not a thing on the screen',\n },\n {\n words: [\n 'robust',\n 'powerful',\n 'cutting-edge',\n 'state-of-the-art',\n 'best-in-class',\n 'world-class',\n 'next-generation',\n 'revolutionary',\n 'game-changing',\n ],\n why: 'is marketing: say what it does',\n },\n {\n words: ['streamline', 'streamlined', 'empower', 'unlock', 'unleash', 'elevate', 'supercharge', 'boost', 'enhance', 'enhanced'],\n why: 'claims an improvement without naming it',\n },\n { words: ['meticulous', 'crucial', 'pivotal', 'vital', 'paramount'], why: 'tells the reader how to feel instead of what it is' },\n {\n words: ['comprehensive', 'myriad', 'plethora', 'a variety of', 'a wide range of'],\n why: 'is padding: name the things, or say how many',\n },\n {\n words: ['furthermore', 'moreover', 'additionally', 'in order to', 'please note', 'note that', 'keep in mind', 'rest assured'],\n why: 'is a connective a short string has no room for',\n },\n { words: ['intuitive', 'sleek', 'stunning', 'beautiful', 'delightful', 'magical'], why: 'grades the product instead of describing it' },\n { words: ['simply', 'just', 'easily', 'easy', 'quickly'], why: 'says it is easy, which helps nobody it is not easy for' },\n { words: ['so you can', 'allows you to', 'lets you', 'enables you to', \"don't worry\"], why: 'justifies or reassures: state the fact' },\n { words: ['please', 'oops', 'whoops', 'sorry'], why: 'pleads or apologizes: say what failed and what to do' },\n { words: ['etc', 'and more', 'and so on'], why: 'trails off: name the things or stop' },\n ],\n spelling: {\n colour: 'color',\n colours: 'colors',\n behaviour: 'behavior',\n favourite: 'favorite',\n cancelled: 'canceled',\n cancelling: 'canceling',\n labelled: 'labeled',\n centre: 'center',\n licence: 'license',\n grey: 'gray',\n organise: 'organize',\n recognise: 'recognize',\n customise: 'customize',\n optimise: 'optimize',\n minimise: 'minimize',\n maximise: 'maximize',\n synchronise: 'synchronize',\n authorise: 'authorize',\n initialise: 'initialize',\n analyse: 'analyze',\n catalogue: 'catalog',\n dialogue: 'dialog',\n artefact: 'artifact',\n judgement: 'judgment',\n whilst: 'while',\n amongst: 'among',\n } as Record<string, string>,\n};\n","/**\n * `prosebook/config`: where the catalog lives, what an entry may say about itself, and how strictly\n * its words are checked. Written as `prosebook.config.ts` (or `.js`, `.mjs`, `.json`) at the project root.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { isAbsolute, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { compileRule, CORE_RULES, type CheckRule, type CoreRule, type Plugin } from './lint.ts';\nimport type { Isolate } from './mf2.ts';\nimport { DEFAULT_KINDS, DEFAULT_SURFACES, STRICT_LISTS, type KindRule, type Severity } from './presets.ts';\n\nexport type { KindRule, Severity };\nexport {\n definePlugin,\n HOLE,\n phrase,\n sentences,\n words,\n type CapitalizationRule,\n type CheckRule,\n type ConditionalRule,\n type ExistenceRule,\n type OccurrenceRule,\n type Plugin,\n type Readings,\n type Report,\n type Rule,\n type RuleContext,\n type SubstitutionRule,\n} from './lint.ts';\n\nexport interface WordLists {\n /** Words a string never uses, in groups that say why. */\n banned?: { words: string[]; why: string }[];\n /** A spelling, and the one the product uses instead. */\n spelling?: Record<string, string>;\n /** A near-synonym, and the one word the product uses for that concept. */\n concepts?: Record<string, string>;\n /** Words that keep their capital inside a sentence-case string: product names, platforms. */\n properNouns?: string[];\n /** What a path through menus or settings is written with, spaced: `›` by default, as in Settings › General. */\n pathSeparator?: string;\n}\n\ntype RuleSeverities = Partial<Record<CoreRule, Severity>> & Record<string, Severity>;\n\nexport interface LintConfig extends WordLists {\n /** `recommended` (the default) checks shape; `strict` adds the word lists and rules of a house style guide. */\n extends?: 'recommended' | 'strict' | 'none';\n /** Rules of your own, as `<plugin>/<rule>`. Each takes the severity it gives itself under `extends`. */\n plugins?: Plugin[];\n rules?: RuleSeverities;\n /** Severities for one area's entries (a key's first segment) over `rules`: `{ native: { 'sentence-case': 'off' } }`. */\n areas?: Record<string, RuleSeverities>;\n}\n\n/**\n * Native code generated from the catalog, for the parts of an app outside the browser: a tray, a\n * menu bar, a CLI. One file, holding every locale, with a typed function per message.\n */\nexport interface NativeTarget {\n language: 'rust' | 'swift' | 'kotlin';\n /** The file written. */\n out: string;\n /**\n * Key prefixes the file holds: `['native']` takes every `native.*` key, which it names without the\n * prefix (`native.tray.quit` is `tray_quit`). Every key, named in full, by default.\n */\n keys?: string[];\n /** The type holding the locales and messages: `Locale` in Rust, `Copy` in Swift and Kotlin. */\n name?: string;\n /** Kotlin's package. */\n package?: string;\n}\n\nexport interface ProsebookConfig {\n /** The source-language catalog: one `<area>.yaml` per area. */\n catalog?: string;\n /** Translations: `<locale>/<area>.yaml` or `<locale>.yaml`, holding `key: message`. */\n locales?: string;\n /** Where the generated modules go. */\n out?: string;\n /** Records which source text each translation was made from, so a changed source marks it stale. */\n lock?: string;\n /** The locale the catalog is written in. Its code is also the field holding the message. */\n source?: string;\n /**\n * The syntax messages are written in: ICU MessageFormat (1) or Unicode MessageFormat 2. Source and\n * translations alike; `prosebook migrate` rewrites a catalog from one to the other.\n */\n messageFormat?: 1 | 2;\n /**\n * In MF2, when a placeholder is wrapped in Unicode isolation marks, so a value written the other\n * way (a Latin name in Hebrew) can't reorder the text around it. `'rtl'`, the default: in locales\n * written right to left, and wherever `u:dir` asks. `'always'`: also every string in any locale,\n * as the spec's default has it. `false`: never.\n */\n isolate?: Isolate;\n /** Locales that ship in the main bundle beside the source, rather than loading when first used. */\n bundled?: string[];\n /** A pseudo-locale generated from the source (accented and lengthened) to find layout bugs and hardcoded text. */\n pseudo?: string | false;\n /** What a translation whose source changed since does: still show (`use`) or show the source (`fallback`). */\n stale?: 'use' | 'fallback';\n /** Generated modules as TypeScript or as JavaScript with a `.d.ts` beside the index. */\n language?: 'ts' | 'js';\n /** The extension generated imports name: `.js` suits most TypeScript setups, `.ts` suits Node's type stripping. */\n importExtension?: '.js' | '.ts' | '';\n /** The fields every entry must have. A shorthand `key: message` entry satisfies none of them. */\n require?: ('context' | 'kind' | 'surface')[];\n /** The kinds of string an entry may say it is, with the shape each one is held to. */\n kinds?: Record<string, KindRule>;\n /** Where a string may sit, with what each surface means. */\n surfaces?: Record<string, string>;\n lint?: LintConfig;\n /** Rust, Swift or Kotlin files `generate` writes beside the TypeScript. */\n native?: NativeTarget[];\n /** Where `prosebook scan` looks for hardcoded text and catalog keys. */\n scan?: {\n dirs?: string[];\n extensions?: string[];\n /** JSX attributes whose literal value a person reads. */\n attributes?: string[];\n };\n}\n\nexport interface ResolvedConfig {\n root: string;\n catalog: string;\n locales: string;\n out: string;\n lock: string;\n source: string;\n messageFormat: 1 | 2;\n isolate: Isolate;\n bundled: string[];\n pseudo: string | false;\n stale: 'use' | 'fallback';\n language: 'ts' | 'js';\n importExtension: '.js' | '.ts' | '';\n require: ('context' | 'kind' | 'surface')[];\n kinds: Record<string, KindRule>;\n surfaces: Record<string, string>;\n lint: {\n rules: Record<string, { rule: CheckRule; severity: Severity }>;\n areas: Record<string, Record<string, Severity>>;\n } & Required<WordLists>;\n native: (NativeTarget & { name: string })[];\n scan: { dirs: string[]; extensions: string[]; attributes: string[] };\n}\n\nconst NATIVE_NAMES = { rust: 'Locale', swift: 'Copy', kotlin: 'Copy' };\n\n/** Typed config, for `prosebook.config.ts`. */\nexport function defineConfig(config: ProsebookConfig): ProsebookConfig {\n return config;\n}\n\nexport const CONFIG_FILES = [\n 'prosebook.config.ts',\n 'prosebook.config.mts',\n 'prosebook.config.js',\n 'prosebook.config.mjs',\n 'prosebook.config.json',\n];\n\n/** Finds and reads the config at `root`, or the defaults when there is none. */\nexport async function loadConfig(root: string, inline?: ProsebookConfig): Promise<ResolvedConfig> {\n if (inline) return resolveConfig(root, inline);\n for (const name of CONFIG_FILES) {\n const path = join(root, name);\n if (!existsSync(path)) continue;\n if (name.endsWith('.json')) return resolveConfig(root, JSON.parse(readFileSync(path, 'utf8')) as ProsebookConfig);\n const mod = (await import(pathToFileURL(path).href)) as { default?: ProsebookConfig };\n return resolveConfig(root, mod.default ?? {});\n }\n return resolveConfig(root, {});\n}\n\nexport function resolveConfig(root: string, config: ProsebookConfig): ResolvedConfig {\n const at = (path: string) => (isAbsolute(path) ? path : resolve(root, path));\n const lint = config.lint ?? {};\n const base = lint.extends ?? 'recommended';\n const strict = base === 'strict';\n const rules = lintRules(lint);\n for (const [area, severities] of Object.entries(lint.areas ?? {})) {\n for (const name of Object.keys(severities))\n if (!(name in rules)) throw new Error(`lint.areas.${area}.${name} is not a rule: name one of ${Object.keys(rules).join(', ')}`);\n }\n return {\n root,\n catalog: at(config.catalog ?? 'copy/catalog'),\n locales: at(config.locales ?? 'copy/locales'),\n out: at(config.out ?? 'src/copy'),\n lock: at(config.lock ?? 'copy/lock.json'),\n source: config.source ?? 'en',\n messageFormat: config.messageFormat ?? 1,\n isolate: config.isolate ?? 'rtl',\n bundled: config.bundled ?? [],\n pseudo: config.pseudo ?? false,\n stale: config.stale ?? 'use',\n language: config.language ?? 'ts',\n importExtension: config.importExtension ?? '.js',\n require: config.require ?? ['context'],\n kinds: config.kinds ?? DEFAULT_KINDS,\n surfaces: config.surfaces ?? DEFAULT_SURFACES,\n lint: {\n rules,\n areas: lint.areas ?? {},\n banned: [...(strict ? STRICT_LISTS.banned : []), ...(lint.banned ?? [])],\n spelling: { ...(strict ? STRICT_LISTS.spelling : {}), ...lint.spelling },\n concepts: { ...lint.concepts },\n properNouns: lint.properNouns ?? [],\n pathSeparator: lint.pathSeparator ?? '›',\n },\n native: (config.native ?? []).map((target, i) => {\n if (!(target.language in NATIVE_NAMES))\n throw new Error(`native[${i}].language is \"${target.language}\": name one of ${Object.keys(NATIVE_NAMES).join(', ')}`);\n return { ...target, out: at(target.out), name: target.name ?? NATIVE_NAMES[target.language] };\n }),\n scan: {\n dirs: (config.scan?.dirs ?? ['src']).map(at),\n extensions: config.scan?.extensions ?? ['.ts', '.tsx', '.js', '.jsx', '.mts', '.mjs'],\n attributes: config.scan?.attributes ?? ['alt', 'title', 'placeholder', 'label', 'aria-label', 'aria-description', 'aria-placeholder'],\n },\n };\n}\n\nfunction lintRules(lint: LintConfig): ResolvedConfig['lint']['rules'] {\n const base = lint.extends ?? 'recommended';\n const all: [string, CheckRule][] = Object.entries(CORE_RULES);\n const seen = new Set<string>();\n for (const plugin of lint.plugins ?? []) {\n if (!/^[a-z][a-z0-9-]*$/i.test(plugin.name))\n throw new Error(`lint.plugins: \"${plugin.name}\" is not a plugin name: use letters, digits and dashes`);\n if (seen.has(plugin.name)) throw new Error(`lint.plugins: \"${plugin.name}\" is added twice: remove one`);\n seen.add(plugin.name);\n for (const [name, rule] of Object.entries(plugin.rules)) {\n const full = `${plugin.name}/${name}`;\n all.push([full, compileRule(full, rule)]);\n }\n }\n const preset = (rule: CheckRule): Severity =>\n base === 'none' ? 'off' : base === 'strict' ? (rule.strict ?? 'error') : (rule.recommended ?? 'off');\n const rules = Object.fromEntries(all.map(([name, rule]) => [name, { rule, severity: lint.rules?.[name] ?? preset(rule) }]));\n for (const name of Object.keys(lint.rules ?? {}))\n if (!(name in rules)) throw new Error(`lint.rules.${name} is not a rule: name one of ${Object.keys(rules).join(', ')}`);\n return rules;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-7T4hX_f7.js","names":[],"sources":["../src/tools/lint.ts","../src/tools/presets.ts","../src/tools/config.ts"],"sourcesContent":["/**\n * Holds every source message to the mechanical half of a writing guide: budgets, periods, case,\n * dashes, spelling, contractions, the product's one word per concept, and banned words. What needs\n * judgment stays with review. An entry a rule is wrong about says so under `allow`, with the reason,\n * and an exemption that no longer matches anything fails too, so none outlive the words they excused.\n *\n * The core rules are written as a plugin's are: a project adds its own through `lint.plugins`, as\n * code or as data, and they read the same readings of a message and are exempted the same way.\n */\nimport type { Message } from './catalog.ts';\nimport type { ResolvedConfig } from './config.ts';\nimport { staticLiteral, TYPE, walk, type MessageFormatElement } from './icu.ts';\nimport type { KindRule, Severity } from './presets.ts';\n\n/** What a rule is given about one message in one locale. */\nexport interface RuleContext {\n /** The entry, as the source catalog has it. */\n message: Message;\n /** The locale read: the source, or a translation's. */\n locale: string;\n /** The message in that locale. */\n ast: MessageFormatElement[];\n /** The shape the message's kind is held to, when it names a kind the config defines. */\n kind: KindRule | undefined;\n /** The message in that locale, as prose. */\n text: Readings;\n /** The source message as prose, to hold a translation to it: `text` itself in the source locale. */\n source: Readings;\n config: ResolvedConfig;\n}\n\ninterface RuleBase {\n /** One sentence: what the rule holds a string to. */\n description: string;\n /** Its severity under `extends: 'recommended'`; off when unset. */\n recommended?: Severity;\n /** Its severity under `extends: 'strict'`; `error` when unset. */\n strict?: Severity;\n /**\n * Only entries of these kinds, on these surfaces, or in these areas (a key's first segment); an\n * entry that says no kind or surface is skipped by a rule that names some. Only the source unless\n * `locale` says otherwise, since most writing rules are written for one language: `all` reads\n * every locale, and a list those languages and their regions (`de` covers `de-CH`).\n */\n on?: { kind?: string[]; surface?: string[]; area?: string[]; locale?: 'all' | string[] };\n}\n\n/** A rule written as code. */\nexport interface CheckRule extends RuleBase {\n /** What is wrong with the message, a sentence each that states the fix; none when it passes. */\n check(context: RuleContext): (string | Report)[];\n}\n\n/** A finding that can say where it is, and what to write instead. */\nexport interface Report {\n message: string;\n /** The words the finding is about, as a reading has them: found in the message's text, in any case. */\n match?: string;\n /** What `prosebook lint --fix` writes in place of `match`, wherever it stands; its case follows the text's. */\n fix?: string;\n}\n\n/** A replacement in a message's text, by offset. */\nexport interface Edit {\n start: number;\n end: number;\n text: string;\n}\n\n/*\n * Rules written as data, after Vale's, so a JSON config can carry them. Words and patterns are looked\n * for in every reading, so one in a `one` arm is found; counts and case read the `other` arms. A\n * pattern is a regular expression with the `u` flag, and sees a placeholder as `HOLE`. A message\n * names what was found with `{match}`, and the other fields its rule lists.\n */\n\n/** Words or patterns a string never uses. */\nexport interface ExistenceRule extends RuleBase {\n type: 'existence';\n /** Words or phrases, matched whole and in any case. `{match}` is the one listed. */\n words?: string[];\n /** `{match}` is the text matched. */\n patterns?: string[];\n ignoreCase?: boolean;\n message: string;\n}\n\n/** A word or phrase the product writes another way. */\nexport interface SubstitutionRule extends RuleBase {\n type: 'substitution';\n /** A word or phrase, matched whole and in any case, and the one written instead. */\n swap: Record<string, string>;\n /** `{match}` and `{use}`; `\"{match}\" is written \"{use}\"` when unset. */\n message?: string;\n}\n\n/** A budget, beside the one a kind sets: per surface, say, or in characters. */\nexport interface OccurrenceRule extends RuleBase {\n type: 'occurrence';\n /** Every word, placeholders included; sentences; or characters, placeholders not included. */\n count: 'words' | 'sentences' | 'characters';\n max?: number;\n min?: number;\n /** `max` and `min` are multiples of the source's count: `max: 1.4` is 40% longer than the source at most. */\n relative?: boolean;\n /** `{count}`, `{max}`, `{min}`, and with `relative`, `{source}` (the source's count) and `{limit}`. */\n message?: string;\n}\n\nexport interface CapitalizationRule extends RuleBase {\n type: 'capitalization';\n /** `sentence` capitalizes only the first word and proper nouns, `title` every word but short function words. */\n case: 'sentence' | 'title' | 'lower' | 'upper';\n /** Words that keep their case, beside `lint.properNouns`. */\n exceptions?: string[];\n /** `{match}` is the first word out of case. */\n message?: string;\n}\n\n/** A string that matches `when` (every string, when unset) matches `require` too. */\nexport interface ConditionalRule extends RuleBase {\n type: 'conditional';\n when?: string;\n require: string;\n ignoreCase?: boolean;\n /** `{match}` is the text `when` matched. */\n message: string;\n}\n\nexport type Rule = CheckRule | ExistenceRule | SubstitutionRule | OccurrenceRule | CapitalizationRule | ConditionalRule;\n\n/** A set of rules, named `<name>/<rule>` in `lint.rules` and in an entry's `allow`. */\nexport interface Plugin {\n name: string;\n rules: Record<string, Rule>;\n}\n\n/** Typed plugin, for `lint.plugins`. */\nexport function definePlugin(plugin: Plugin): Plugin {\n return plugin;\n}\n\nexport interface Finding {\n key: string;\n /** The catalog file, or for a translation, the locale's file. */\n file: string;\n /** The locale whose text the finding is about; the source for an `allow` finding. */\n locale: string;\n /** The rule's name, or `allow` for an exemption that is itself wrong. */\n rule: string;\n severity: Exclude<Severity, 'off'>;\n message: string;\n /** Where in the locale's message text, when the rule named a match and it is written there as read. */\n at?: { start: number; end: number };\n /** The edits that fix it, at every place the match stands. */\n fix?: Edit[];\n}\n\n/** Stands in for a placeholder in a reading, which no prose rule reads. */\nexport const HOLE = '\\u2063';\n/** Tags whose content is code or a literal the reader types, not prose. */\nconst VERBATIM_TAGS = new Set(['code', 'mono', 'kbd', 'keycap', 'nums']);\n\nfunction renderAs(elements: MessageFormatElement[], arm: string | null): string {\n let out = '';\n for (const el of elements) {\n if (el.type === TYPE.literal) {\n out += el.value;\n } else if (el.type === TYPE.tag) {\n out += VERBATIM_TAGS.has(el.value) ? HOLE : renderAs(el.children, arm);\n } else if (el.type === TYPE.plural || el.type === TYPE.select) {\n const option = arm === null ? undefined : (el.options[arm] ?? el.options['other']);\n out += option === undefined ? HOLE : renderAs(option.value, arm);\n } else {\n out += HOLE;\n }\n }\n return out;\n}\n\n/** The message as prose: placeholders and verbatim tags read as `HOLE`, and `’` as `'` in `variants`. */\nexport interface Readings {\n /** Every `other` arm taken: what a budget is measured on. */\n primary: string;\n /** One reading per arm, so a word hidden in `one` is still found. */\n variants: string[];\n /** Only the words the message always carries. */\n skeleton: string;\n}\n\nfunction readings(message: MessageFormatElement[]): Readings {\n const literal = staticLiteral(message);\n const ast = literal === undefined ? message : ([{ type: TYPE.literal, value: literal }] as MessageFormatElement[]);\n const arms = new Set<string>();\n const collect = (els: MessageFormatElement[]) => {\n for (const el of els) {\n if (el.type === TYPE.plural || el.type === TYPE.select) {\n for (const [name, option] of Object.entries(el.options)) {\n arms.add(name);\n collect(option.value);\n }\n }\n if (el.type === TYPE.tag) collect(el.children);\n }\n };\n collect(ast);\n const primary = renderAs(ast, 'other');\n const variants = new Set([primary, ...[...arms].map((arm) => renderAs(ast, arm))]);\n return { primary, variants: [...variants].map((v) => v.replace(/\\u2019/g, \"'\")), skeleton: renderAs(ast, null) };\n}\n\n/** What a reader sees end to end, less a placeholder appended at the very end. */\nconst prose = (text: string) => text.replace(new RegExp(`[\\\\s${HOLE}]+$`), '');\n\nconst FREE = new Set('a an the this that these those it its them your and or to of for by in on at from with'.split(' '));\n\nconst tokens = (text: string) => text.split(/\\s+/).filter((w) => /[\\p{L}\\p{N}]/u.test(w) || w.includes(HOLE));\n\n/** The words a budget counts: articles, short prepositions and asides in parentheses are free. */\nexport function words(text: string): string[] {\n return tokens(text.replace(/\\s*\\([^)]*\\)/g, '')).filter((w) => !FREE.has(w.toLowerCase().replace(/[^\\p{L}]/gu, '')));\n}\n\nconst ABBREVIATIONS = /\\b(?:e\\.g|i\\.e|vs|etc)\\.$/i;\n\nexport function sentences(text: string): number {\n let count = 1;\n const boundary = /[.!?…]+[\"')\\]]*\\s+(?=\\S)/g;\n for (let m = boundary.exec(text); m !== null; m = boundary.exec(text))\n if (!ABBREVIATIONS.test(text.slice(0, m.index + m[0].trimEnd().length))) count += 1;\n\n return count;\n}\n\n/** A word or phrase on its own, not inside a longer word or a hyphenated compound. */\nexport function phrase(p: string): RegExp {\n const escaped = p.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/ /g, '\\\\s+');\n return new RegExp(`(?<![\\\\p{L}\\\\p{N}'-])${escaped}(?![\\\\p{L}\\\\p{N}'-])`, 'iu');\n}\n\n/** The words and phrases of `list` that some reading carries. */\nconst listed = (variants: string[], list: string[]) => list.filter((w) => variants.some((v) => phrase(w).test(v)));\n\nconst unquoted = (token: string) => token.replace(/^[(\"'“‘]+|[)\"'”’.,:;!?]+$/g, '');\n\nfunction capitalizedWord(text: string, proper: Set<string>): string | undefined {\n const parts = text.split(/\\s+/).filter(Boolean);\n for (let i = 1; i < parts.length; i++) {\n const word = unquoted(parts[i]!);\n if (!/^\\p{Lu}\\p{Ll}/u.test(word) || proper.has(word)) continue;\n if (/[.:?!][\"')]*$/.test(parts[i - 1]!)) continue;\n return word;\n }\n return undefined;\n}\n\n/** Words a count is followed by that are not plural nouns, though they end in s. */\nconst NOT_PLURAL = new Set([\n 'is',\n 'was',\n 'has',\n 'does',\n 'this',\n 'its',\n 'plus',\n 'minus',\n 'less',\n 'yes',\n 'us',\n 'as',\n 'bus',\n 'gas',\n 'news',\n 'series',\n]);\n\n/**\n * The singular of an English plural noun, or nothing where it doesn't look like one. A word with no\n * vowel is a unit or an abbreviation (`kbps`, `fps`, `hrs`), which reads the same after 1.\n */\nexport function singularOf(word: string): string | undefined {\n const lower = word.toLowerCase();\n if (word.length < 3 || !lower.endsWith('s') || lower.endsWith('ss') || NOT_PLURAL.has(lower)) return undefined;\n if (!/[aeiouy]/.test(lower)) return undefined;\n if (/[^aeiou]ies$/.test(lower)) return `${word.slice(0, -3)}y`;\n if (/(?:s|x|z|ch|sh)es$/.test(lower)) return word.slice(0, -2);\n return word.slice(0, -1);\n}\n\nconst MINOR = new Set('a an the and but or nor for so yet as at by in of off on per to up via with'.split(' '));\n\n/** The first word out of `style` case, less those in `keep`. */\nfunction outOfCase(text: string, style: CapitalizationRule['case'], keep: Set<string>): string | undefined {\n if (style === 'sentence') return capitalizedWord(text, keep);\n const list = text\n .split(/\\s+/)\n .map(unquoted)\n .filter((w) => /\\p{L}/u.test(w) && !keep.has(w));\n return list.find((w, i) => {\n if (style === 'lower') return /\\p{Lu}/u.test(w);\n if (style === 'upper') return /\\p{Ll}/u.test(w);\n return /^\\p{Ll}/u.test(w) && (i === 0 || !MINOR.has(w));\n });\n}\n\nconst CONTRACTIONS: [RegExp, string][] = [\n [/\\bcannot\\b/i, \"can't\"],\n [/\\bcan not\\b/i, \"can't\"],\n [/\\bwill not\\b/i, \"won't\"],\n [/\\b(could|would|should|is|are|was|were|do|does|did|has|have|had|must|need) not\\b/i, \"n't\"],\n];\n\n/** Calls `visit` on every run of elements that sit side by side, with the arguments a plural around it counts. */\nfunction eachRun(\n elements: MessageFormatElement[],\n visit: (run: MessageFormatElement[], counted: ReadonlySet<string>) => void,\n counted: ReadonlySet<string> = new Set(),\n): void {\n visit(elements, counted);\n for (const el of elements) {\n if (el.type === TYPE.plural) for (const o of Object.values(el.options)) eachRun(o.value, visit, new Set([...counted, el.value]));\n if (el.type === TYPE.select) for (const o of Object.values(el.options)) eachRun(o.value, visit, counted);\n if (el.type === TYPE.tag) eachRun(el.children, visit, counted);\n }\n}\n\n/** A plain placeholder named as a count. A number placeholder is one whatever its name. */\nconst COUNT_NAME = /^(?:n|num|count|total|amount|quantity)$|(?:count|total)$/i;\n\n/**\n * Whether an arm ends with a stop; nothing for an arm with no words, or one that trails off in an\n * ellipsis (`Saving…`, `Save as…`), which is neither. Which stop is the arm's own: a question in\n * `one` and a second sentence after it in `other` both end well.\n */\nfunction endsWithStop(arm: MessageFormatElement[]): boolean | undefined {\n const text = prose(renderAs(arm, 'other')).trim();\n if (text.replaceAll(HOLE, '').trim() === '' || /(?:…|\\.{3})[\"')”»」』]*$/u.test(text)) return undefined;\n return hasStop(text);\n}\n\n/** Ends with a stop in any script (`。`, `؟`, `;` as Greek writes `?`), though not a comma. */\nconst hasStop = (text: string) => /(?![,,、،])[\\p{Terminal_Punctuation}…][\"')”»」』]*$/u.test(prose(text).trim());\n\nconst CURRENCY_BEFORE = /[$€£¥₹]\\s?$/;\n\n/**\n * The ways a path through menus is written, the separator in a group: an arrow or `›` however\n * spaced, and `>` or `/` only spaced between words or placeholders, with a capital after a slash,\n * since \"2 > 1\" and \"and / or\" are no paths. The match takes the spaces around, so the fix spaces\n * the separator.\n */\nconst PATH_SEPARATORS = new RegExp(\n String.raw`\\s*(→|->|›)\\s*|(?<=[\\p{L}${HOLE}])\\s+(>)\\s+(?=[\\p{L}${HOLE}])|(?<=\\p{L})\\s+(\\/)\\s+(?=\\p{Lu})`,\n 'gu',\n);\n\nconst OFF_SCREEN = new Set(['aria']);\n\nconst an = (word = 'string') => `${/^[aeiou]/i.test(word) ? 'an' : 'a'} ${word}`;\n\nexport const CORE_RULES = {\n whitespace: {\n description: 'No leading, trailing or doubled spaces.',\n recommended: 'error',\n on: { locale: 'all' },\n check: ({ text }) => {\n const message = 'no leading, trailing or doubled spaces';\n // As a match, two spaces stand for a run of any length.\n if (text.variants.some((v) => v.includes(' '))) return [{ message, match: ' ', fix: ' ' }];\n return text.variants.some((v) => /^\\s|\\s$/.test(v.replaceAll(HOLE, 'x'))) ? [message] : [];\n },\n },\n 'word-budget': {\n description: \"A kind with `maxWords` stays within it. Articles, short prepositions and asides in parentheses don't count.\",\n recommended: 'warn',\n check: ({ message: m, kind, text }) => {\n if (kind?.maxWords === undefined || OFF_SCREEN.has(m.surface ?? '')) return [];\n const n = words(text.primary).length;\n return n > kind.maxWords ? [`${an(m.kind)} is ${kind.maxWords} words at most, and this is ${n}`] : [];\n },\n },\n 'sentence-budget': {\n description: 'A kind with `maxSentences` stays within it.',\n recommended: 'warn',\n check: ({ message: m, kind, text }) => {\n const most = (m.surface !== undefined ? kind?.maxSentencesOn?.[m.surface] : undefined) ?? kind?.maxSentences;\n if (most === undefined) return [];\n const n = sentences(prose(text.primary));\n return n > most\n ? [\n `${an(m.kind)}${kind?.maxSentencesOn?.[m.surface ?? ''] !== undefined ? ` on ${m.surface}` : ''} is ${most} sentence(s) at most, and this is ${n}`,\n ]\n : [];\n },\n },\n period: {\n description: 'A kind with `period: always` (or on a listed surface) ends with a period, unless the entry is a fragment.',\n recommended: 'warn',\n check: ({ message: m, kind, text }) => {\n const rule = kind?.period;\n const applies = rule === 'always' || (Array.isArray(rule) && rule.includes(m.surface ?? ''));\n return applies && !m.fragment && !/[.?!…:][\"')”]*$/.test(prose(text.primary))\n ? [`${an(m.kind)} ends with a period, or is marked fragment: true`]\n : [];\n },\n },\n 'no-period': {\n description: 'A kind with `period: never` ends without one.',\n recommended: 'warn',\n check: ({ message: m, kind, text }) =>\n kind?.period === 'never' && /[^.]\\.$/.test(prose(text.primary)) ? [`${an(m.kind)} ends without a period`] : [],\n },\n 'bare-name': {\n description: 'A kind with `bare: true` carries no explanation after a dash or a colon.',\n recommended: 'warn',\n // A colon before a value is a readout, as in \"Zoom: 120%\", not an explanation.\n check: ({ message: m, kind, text }) =>\n kind?.bare === true && new RegExp(`\\\\s[—–-]\\\\s|\\\\p{L}:\\\\s(?!${HOLE})`, 'u').test(text.skeleton)\n ? [`${an(m.kind)} carries no explanation after a dash or a colon`]\n : [],\n },\n 'sentence-case': {\n description: 'A kind with `sentenceCase: true` capitalizes only its first word and proper nouns.',\n check: ({ message: m, kind, text, config }) => {\n if (kind?.sentenceCase !== true) return [];\n const word = outOfCase(text.primary, 'sentence', new Set(config.lint.properNouns));\n if (word === undefined) return [];\n return [\n { message: `\"${word}\" is capitalized in a sentence-case ${m.kind}: add it to lint.properNouns if it is a name`, match: word },\n ];\n },\n },\n 'banned-word': {\n description: 'A word or phrase from the banned lists.',\n recommended: 'warn',\n check: ({ text, config }) =>\n config.lint.banned.flatMap(({ words: list, why }) =>\n listed(text.variants, list).map((w) => ({ message: `\"${w}\" ${why}`, match: w })),\n ),\n },\n spelling: {\n description: 'A spelling the product writes another way.',\n recommended: 'warn',\n check: ({ text, config: { lint } }) =>\n listed(text.variants, Object.keys(lint.spelling)).map((w) => ({\n message: `\"${w}\" is spelled \"${lint.spelling[w]}\"`,\n match: w,\n fix: lint.spelling[w],\n })),\n },\n 'one-word': {\n description: 'A near-synonym for a concept the product has one word for.',\n recommended: 'warn',\n check: ({ text, config: { lint } }) =>\n listed(text.variants, Object.keys(lint.concepts)).map((w) => ({\n message: `\"${w}\" is \"${lint.concepts[w]}\" everywhere in the product`,\n match: w,\n fix: lint.concepts[w],\n })),\n },\n 'no-em-dash': {\n description: 'No em-dashes, and no spaced hyphen standing in for one.',\n check: ({ text }) => {\n const match = text.variants.map((v) => /—|\\s[–-]\\s/.exec(v)?.[0]).find((m) => m !== undefined);\n return match === undefined ? [] : [{ message: 'no em-dash: a comma, a period or a colon does the job', match }];\n },\n },\n path: {\n description: 'A path through menus or settings is written with `lint.pathSeparator`, spaced: Settings › General.',\n check: ({ text, config }) => {\n const use = config.lint.pathSeparator;\n for (const v of text.variants) {\n for (const m of v.matchAll(PATH_SEPARATORS)) {\n if ((m[1] ?? m[2] ?? m[3]) === use) continue;\n return [{ message: `a path is written with a spaced ${use}`, match: m[0], fix: ` ${use} ` }];\n }\n }\n return [];\n },\n },\n contractions: {\n description: '`could not`, `is not` and `cannot` are written as contractions.',\n check: ({ text }) =>\n CONTRACTIONS.flatMap(([pattern, short]) => {\n const found = text.variants.map((v) => pattern.exec(v)).find((f) => f !== null);\n if (found === undefined || found === null) return [];\n const fix = short === \"n't\" ? `${found[1]}n't` : short;\n return [{ message: `\"${found[0]}\" is written as a contraction (${short})`, match: found[0], fix }];\n }),\n },\n ellipsis: {\n description: 'An ellipsis is one character, `…`, not three periods.',\n on: { locale: 'all' },\n check: ({ text }) =>\n text.variants.some((v) => v.includes('...')) ? [{ message: 'an ellipsis is one character: …', match: '...', fix: '…' }] : [],\n },\n 'plural-count': {\n description: 'A count followed by a plural noun, `{count} files`, is a plural, or it reads \"1 files\". English.',\n recommended: 'warn',\n check: ({ ast }) => {\n const said: Report[] = [];\n eachRun(ast, (run, counted) =>\n run.forEach((el, i) => {\n if (el.type !== TYPE.number && el.type !== TYPE.argument) return;\n if (counted.has(el.value) || (el.type === TYPE.argument && !COUNT_NAME.test(el.value))) return;\n const next = run[i + 1];\n const word = next?.type === TYPE.literal ? /^\\s+(\\p{L}+)(?![\\p{L}'])/u.exec(next.value)?.[1] : undefined;\n const one = word === undefined ? undefined : singularOf(word);\n if (word !== undefined && one !== undefined) {\n said.push({\n message: `${el.value} is followed by \"${word}\", which reads \"1 ${word}\": make it a plural with a \"# ${one}\" arm`,\n match: word,\n });\n }\n }),\n );\n return said;\n },\n },\n 'plural-one': {\n description: \"A plural's `one` arm says something other than `other`, and says `#` rather than `1`.\",\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ ast, locale, config }) => {\n const said: Report[] = [];\n walk(ast, (el) => {\n if (el.type !== TYPE.plural || el.pluralType !== 'cardinal') return;\n const { one, other } = el.options;\n if (one === undefined) return;\n // Turkish says \"# dosya\" for one and other alike, so only the source must tell them apart.\n if (locale === config.source && other !== undefined && renderAs(one.value, 'other') === renderAs(other.value, 'other'))\n said.push({ message: `the one and other arms of ${el.value} say the same: write the singular in one` });\n let literalOne = false;\n walk(one.value, (inner) => {\n if (inner.type === TYPE.literal && /(?<![\\d.,])1(?![\\d.,])/.test(inner.value)) literalOne = true;\n });\n // Russian's `one` is also 21 and 31, so a translator copying a written 1 gets it wrong there.\n if (!literalOne) return;\n const message = `the one arm of ${el.value} writes 1, which one is not in every language: write #, or make the arm =1`;\n said.push({ message, match: '1' });\n });\n return said;\n },\n },\n 'arm-endings': {\n description: 'The arms of a plural or select end alike: all with a stop, or all without one.',\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ ast }) => {\n const said: string[] = [];\n walk(ast, (el) => {\n if (el.type !== TYPE.plural && el.type !== TYPE.select) return;\n const endings = new Set(Object.values(el.options).flatMap((o) => endsWithStop(o.value) ?? []));\n if (endings.size > 1) said.push(`some arms of ${el.value} end with a stop and some without: end them alike`);\n });\n return said;\n },\n },\n 'formatted-by-hand': {\n description: 'A currency symbol or `%` typed beside a placeholder, or digits grouped by hand, which only suit one locale.',\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ ast, text }) => {\n const said = new Map<string, Report>();\n const say = (message: string, match: string) => said.set(message, { message, match });\n eachRun(ast, (run) =>\n run.forEach((el, i) => {\n if (el.type !== TYPE.number && el.type !== TYPE.argument) return;\n const before = run[i - 1];\n const after = run[i + 1];\n const symbol = before?.type === TYPE.literal ? CURRENCY_BEFORE.exec(before.value)?.[0].trim() : undefined;\n if (symbol !== undefined)\n say(`\"${symbol}\" is typed before ${el.value}: format it as a currency, which puts the symbol where the locale does`, symbol);\n if (after?.type === TYPE.literal && /^\\s?%/.test(after.value))\n say(`\"%\" is typed after ${el.value}: format it as a percent, which takes the fraction (0.5 for 50%)`, '%');\n }),\n );\n const grouped = text.variants.map((v) => /\\d{1,3}(?:,\\d{3})+(?!\\d)/.exec(v)?.[0]).find((g) => g !== undefined);\n if (grouped !== undefined)\n say(`\"${grouped}\" groups its digits the English way: make it a placeholder formatted as a number`, grouped);\n return [...said.values()];\n },\n },\n 'source-ending': {\n description: 'A translation ends with a stop where its source does, and without one where it does not.',\n recommended: 'warn',\n on: { locale: 'all' },\n check: ({ text, source }) => {\n const ends = hasStop(text.primary);\n if (ends === hasStop(source.primary)) return [];\n return [\n ends\n ? 'ends with a stop, and the source does not: drop it'\n : 'the source ends with a stop, and this does not: end it as the source does',\n ];\n },\n },\n} satisfies Record<string, CheckRule>;\n\nexport type CoreRule = keyof typeof CORE_RULES;\n\nconst fill = (message: string, values: Record<string, string | number | undefined>) =>\n message.replace(/\\{(\\w+)\\}/g, (all, name: string) => (values[name] === undefined ? all : String(values[name])));\n\nconst graphemes = new Intl.Segmenter();\n\nconst COUNTERS: Record<OccurrenceRule['count'], (text: string) => number> = {\n words: (text) => tokens(text).length,\n sentences: (text) => sentences(prose(text)),\n characters: (text) => [...graphemes.segment(text.replaceAll(HOLE, ''))].length,\n};\n\n/** A rule as code, checked once when the config loads: a JSON config is not type-checked. */\nexport function compileRule(name: string, rule: Rule): CheckRule {\n const fail = (problem: string): never => {\n throw new Error(`lint rule ${name} ${problem}`);\n };\n const pattern = (source: unknown, field: string, ignoreCase: boolean | undefined) => {\n if (typeof source !== 'string') return fail(`${field} is not a string: write the pattern as one`);\n try {\n return new RegExp(source, ignoreCase === true ? 'iu' : 'u');\n } catch (e) {\n return fail(`${field} is not a regular expression: ${e instanceof Error ? e.message : String(e)}`);\n }\n };\n const said = (message: unknown) =>\n typeof message === 'string' && message !== '' ? message : fail('has no message: say what to write instead');\n if (typeof rule.description !== 'string' || rule.description === '') fail('has no description: say what it holds a string to');\n if ('check' in rule) return typeof rule.check === 'function' ? rule : fail('has a check that is not a function');\n const { description, recommended, strict, on } = rule;\n const base = { description, recommended, strict, on };\n switch (rule.type) {\n case 'existence': {\n const list = rule.words ?? [];\n const patterns = (rule.patterns ?? []).map((p, i) => pattern(p, `patterns[${i}]`, rule.ignoreCase));\n if (list.length + patterns.length === 0) fail('has no words or patterns: list what a string never says');\n const message = said(rule.message);\n return {\n ...base,\n check: ({ text }) => {\n const matched = patterns.flatMap((p) => text.variants.map((v) => p.exec(v)?.[0]).find((m) => m !== undefined) ?? []);\n return [...new Set([...listed(text.variants, list), ...matched])].map((match) => ({ message: fill(message, { match }), match }));\n },\n };\n }\n case 'substitution': {\n const swap = rule.swap ?? {};\n if (Object.keys(swap).length === 0) fail('has nothing in swap: map a word to the one written instead');\n const message = rule.message === undefined ? '\"{match}\" is written \"{use}\"' : said(rule.message);\n return {\n ...base,\n check: ({ text }) =>\n listed(text.variants, Object.keys(swap)).map((match) => ({\n message: fill(message, { match, use: swap[match] }),\n match,\n fix: swap[match],\n })),\n };\n }\n case 'occurrence': {\n const { count: unit, max, min, relative } = rule;\n const counter = Object.hasOwn(COUNTERS, unit) ? COUNTERS[unit] : fail(`counts ${unit}: count words, sentences or characters`);\n if (max === undefined && min === undefined) fail('has no max or min: give it one');\n if (rule.message !== undefined) said(rule.message);\n return {\n ...base,\n check: ({ text, source }) => {\n const count = counter(text.primary);\n const of = relative === true ? counter(source.primary) : 1;\n const over = max !== undefined && count > max * of;\n const under = min !== undefined && count < min * of;\n if (!over && !under) return [];\n // The limit shown is one the count could meet: 1.5 times 11 characters is 16 at most, 17 at least.\n const limit = over && max !== undefined ? Math.floor(max * of) : Math.ceil((min ?? 0) * of);\n const bound = over ? 'at most' : 'at least';\n const fallback =\n relative === true\n ? `{limit} ${unit} ${bound} ({${over ? 'max' : 'min'}} times the source's {source}), and this is {count}`\n : `{${over ? 'max' : 'min'}} ${unit} ${bound}, and this is {count}`;\n return [fill(rule.message ?? fallback, { count, max, min, source: relative === true ? of : undefined, limit })];\n },\n };\n }\n case 'capitalization': {\n const style = rule.case;\n if (!['sentence', 'title', 'lower', 'upper'].includes(style)) fail(`has case ${style}: use sentence, title, lower or upper`);\n const message =\n rule.message === undefined\n ? `\"{match}\" is out of ${style} case: change it, or add it to exceptions if it is a name`\n : said(rule.message);\n const exceptions = rule.exceptions ?? [];\n return {\n ...base,\n check: ({ text, config }) => {\n const match = outOfCase(text.primary, style, new Set([...config.lint.properNouns, ...exceptions]));\n return match === undefined ? [] : [{ message: fill(message, { match }), match }];\n },\n };\n }\n case 'conditional': {\n const when = rule.when === undefined ? undefined : pattern(rule.when, 'when', rule.ignoreCase);\n const required = pattern(rule.require, 'require', rule.ignoreCase);\n const message = said(rule.message);\n return {\n ...base,\n check: ({ text }) => {\n for (const v of text.variants) {\n const match = when === undefined ? '' : when.exec(v)?.[0];\n if (match !== undefined && !required.test(v)) return [fill(message, { match })];\n }\n return [];\n },\n };\n }\n default:\n return fail(\n `has type ${String((rule as { type?: unknown }).type)}: use existence, substitution, occurrence, capitalization or conditional, or give it a check`,\n );\n }\n}\n\n/** A reason is a sentence a reviewer can check, not a shrug. */\nfunction reasonProblem(why: string): string | undefined {\n if (why.split(/\\s+/).length < 4) return 'is four words at least: say why the rule is wrong here';\n if (/^(?:intentional|needed|required|ok|fine|false positive|by design|legacy|todo)\\b/i.test(why))\n return 'names the reason, not that there is one';\n return undefined;\n}\n\n/** A locale is one a rule reads when it names its language, or the locale and a region of it. */\nconst readsLocale = (locales: 'all' | string[] | undefined, locale: string, sourceLocale: string) =>\n locales === undefined\n ? locale === sourceLocale\n : locales === 'all' ||\n locales.some((l) => locale.toLowerCase() === l.toLowerCase() || locale.toLowerCase().startsWith(`${l.toLowerCase()}-`));\n\nfunction applies(rule: RuleBase, message: Message, locale: string, sourceLocale: string): boolean {\n const { kind, surface, area, locale: locales } = rule.on ?? {};\n return (\n readsLocale(locales, locale, sourceLocale) &&\n (kind === undefined || (message.kind !== undefined && kind.includes(message.kind))) &&\n (surface === undefined || (message.surface !== undefined && surface.includes(message.surface))) &&\n (area === undefined || area.includes(message.area))\n );\n}\n\n/** A rule's severity for an entry: its area's, where `lint.areas` sets one. */\nexport const severityOf = (config: ResolvedConfig, name: string, message: Message): Severity | undefined =>\n config.lint.areas[message.area]?.[name] ?? config.lint.rules[name]?.severity;\n\ninterface Literal {\n start: number;\n value: string;\n}\n\n/**\n * Where the message's literals are written in its text, each looked for after the one before. A\n * literal escaped in the text (`''`, `\\{`) isn't written as read, so it has no place, and nor does a\n * finding in it.\n */\nfunction literalsIn(ast: MessageFormatElement[], text: string): Literal[] {\n const found: Literal[] = [];\n let from = 0;\n walk(ast, (el) => {\n if (el.type !== TYPE.literal || el.value === '') return;\n // MF2's `.match` is read into arms in another order than they are written, so look from the top too.\n const next = text.indexOf(el.value, from);\n const start = next === -1 ? text.indexOf(el.value) : next;\n if (start === -1) return;\n found.push({ start, value: el.value });\n from = start + el.value.length;\n });\n return found;\n}\n\n/** Every place `match` stands in the literals, in any case, whole where it starts or ends with a letter. */\nfunction placesOf(match: string, literals: Literal[]): { start: number; end: number }[] {\n const body = match\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/ /g, '\\\\s+')\n .replace(/'/g, \"['’]\");\n const before = /^[\\p{L}\\p{N}]/u.test(match) ? '(?<![\\\\p{L}\\\\p{N}])' : '';\n const after = /[\\p{L}\\p{N}]$/u.test(match) ? '(?![\\\\p{L}\\\\p{N}])' : '';\n const pattern = new RegExp(`${before}${body}${after}`, 'giu');\n const places = new Map<number, number>();\n for (const { start, value } of literals)\n for (const m of value.matchAll(pattern)) places.set(start + m.index, start + m.index + m[0].length);\n return [...places].sort(([a], [b]) => a - b).map(([start, end]) => ({ start, end }));\n}\n\n/** A fix in the case of what it replaces: \"Colour\" becomes \"Color\". */\nconst inCaseOf = (found: string, fix: string) =>\n /^\\p{Lu}/u.test(found) && /^\\p{Ll}/u.test(fix) ? fix.charAt(0).toUpperCase() + fix.slice(1) : fix;\n\n/** `text` with the edits made, leaving out any that overlaps one before it. */\nexport function applyEdits(text: string, edits: Edit[]): string {\n let out = '';\n let at = 0;\n for (const edit of [...edits].sort((a, b) => a.start - b.start)) {\n if (edit.start < at) continue;\n out += text.slice(at, edit.start) + edit.text;\n at = edit.end;\n }\n return out + text.slice(at);\n}\n\nexport function lint(messages: Message[], config: ResolvedConfig): Finding[] {\n const findings: Finding[] = [];\n const rules = Object.entries(config.lint.rules);\n for (const message of messages) {\n const kind = message.kind === undefined ? undefined : config.kinds[message.kind];\n const source = readings(message.ast);\n const locales = [\n { locale: config.source, ast: message.ast, written: message.text, file: message.file },\n ...[...message.translations].map(([locale, t]) => ({ locale, ast: t.ast, written: t.text, file: t.file })),\n ];\n // An exemption is the entry's, so it holds in every locale, and is still needed if any locale needs it.\n const fired = new Set<string>();\n for (const { locale, ast, written, file } of locales) {\n const text = locale === config.source ? source : readings(ast);\n const context: RuleContext = { message, locale, ast, kind, text, source, config };\n let literals: Literal[] | undefined;\n for (const [name, { rule }] of rules) {\n const severity = severityOf(config, name, message)!;\n if (severity === 'off' || !applies(rule, message, locale, config.source)) continue;\n let said: (string | Report)[];\n try {\n said = rule.check(context);\n } catch (cause) {\n throw new Error(`lint rule ${name} failed on ${message.key} in ${locale}: fix or turn off the rule`, { cause });\n }\n if (said.length === 0) continue;\n fired.add(name);\n if (message.allow.has(name)) continue;\n for (const s of said) {\n const { message: text, match, fix } = typeof s === 'string' ? { message: s } : s;\n const finding: Finding = { key: message.key, file, locale, rule: name, severity, message: text };\n if (match !== undefined && match !== '') {\n literals ??= literalsIn(ast, written);\n const places = placesOf(match, literals);\n if (places.length > 0) finding.at = places[0];\n if (places.length > 0 && fix !== undefined)\n finding.fix = places.map((p) => ({ ...p, text: inCaseOf(written.slice(p.start, p.end), fix) }));\n }\n findings.push(finding);\n }\n }\n }\n for (const [name, why] of message.allow) {\n const at = { key: message.key, file: message.file, locale: config.source, rule: 'allow', severity: 'error' as const };\n const rule = config.lint.rules[name];\n if (rule === undefined) {\n findings.push({ ...at, message: `allow.${name} is not a rule: ${rules.map(([n]) => n).join(', ')}` });\n } else if (severityOf(config, name, message) === 'off') {\n continue;\n } else if (!fired.has(name)) {\n findings.push({ ...at, message: `allow.${name} exempts the entry from a rule it passes: remove it` });\n } else {\n const problem = reasonProblem(why);\n if (problem !== undefined) findings.push({ ...at, message: `allow.${name} ${problem}` });\n }\n }\n }\n return findings;\n}\n","/**\n * The defaults: four kinds of string, the surfaces they sit on, and the word lists of the strict lint preset.\n *\n * The kinds are the four any UI writing guide comes down to. A name identifies, an action says what\n * pressing it does, a description adds what the name cannot carry, a state reports what is true.\n * Each carries a budget and a grammar, which is what makes a mechanical check of the words possible.\n */\nexport type Severity = 'error' | 'warn' | 'off';\n\nexport interface KindRule {\n /** What the kind is for, shown when an editor completes it. */\n doc: string;\n /** The most words it may have. Articles, short prepositions and asides in parentheses are free. */\n maxWords?: number;\n /** The most sentences it may have, and per surface where that differs. */\n maxSentences?: number;\n maxSentencesOn?: Record<string, number>;\n /** Whether it ends with a period: always, never, or only on the surfaces listed. */\n period?: 'always' | 'never' | string[];\n /** Capitalizes only its first word and proper nouns. */\n sentenceCase?: boolean;\n /** Carries no explanation after a dash or colon: `Quick capture`, not `Quick capture: choose an area`. */\n bare?: boolean;\n}\n\nexport const DEFAULT_KINDS: Record<string, KindRule> = {\n name: {\n doc: 'Identifies a thing so it can be found again. One to four words, a noun phrase, no period.',\n maxWords: 4,\n period: 'never',\n sentenceCase: true,\n bare: true,\n },\n action: {\n doc: 'Says what pressing it does. One to three words, verb first, no period.',\n maxWords: 3,\n period: 'never',\n sentenceCase: true,\n },\n description: {\n doc: 'Adds only what the name cannot carry. One sentence, two at most, with a period.',\n maxSentences: 2,\n period: 'always',\n },\n state: {\n doc: 'Reports what is true right now. One sentence, present tense; on an error or empty state, one more saying what to do.',\n maxSentences: 1,\n maxSentencesOn: { error: 2, empty: 2, hint: 2, status: 2 },\n period: ['hint', 'status', 'error', 'empty', 'confirm'],\n },\n};\n\nexport const DEFAULT_SURFACES: Record<string, string> = {\n action: 'The text of a button or a menu entry.',\n aria: 'Reached only by a screen reader, so nothing on screen carries it.',\n choice: 'One option among a set offered together.',\n confirm: 'The question of a confirmation, or the verb that answers it.',\n empty: 'Fills a list or a panel that has nothing in it.',\n error: 'Says what failed.',\n heading: 'Heads a section, group, dialog or list.',\n hint: 'A subordinate line under the thing it qualifies.',\n label: 'Names a control, a field, a section or a destination.',\n placeholder: 'Sits inside an empty field, and goes when typing starts.',\n status: 'Reports what is true right now, on a badge or beside a row.',\n title: 'The title of a page, window or document.',\n toast: 'A notification that comes and goes.',\n tooltip: 'Appears on hover.',\n};\n\n/** The word lists of the strict preset: filler, marketing and reassurance, and American spelling. */\nexport const STRICT_LISTS = {\n banned: [\n {\n words: ['seamless', 'seamlessly', 'effortless', 'effortlessly', 'hassle-free', 'frictionless'],\n why: 'promises a feeling rather than saying what happens',\n },\n {\n words: ['leverage', 'leverages', 'leveraging', 'utilize', 'utilizes', 'utilizing', 'harness', 'take advantage of'],\n why: 'is a long way to say use',\n },\n {\n words: [\n 'delve',\n 'dive into',\n 'deep dive',\n 'embark',\n 'journey',\n 'tapestry',\n 'realm',\n 'landscape',\n 'testament',\n 'synergy',\n 'paradigm',\n 'holistic',\n ],\n why: 'is filler, not a thing on the screen',\n },\n {\n words: [\n 'robust',\n 'powerful',\n 'cutting-edge',\n 'state-of-the-art',\n 'best-in-class',\n 'world-class',\n 'next-generation',\n 'revolutionary',\n 'game-changing',\n ],\n why: 'is marketing: say what it does',\n },\n {\n words: ['streamline', 'streamlined', 'empower', 'unlock', 'unleash', 'elevate', 'supercharge', 'boost', 'enhance', 'enhanced'],\n why: 'claims an improvement without naming it',\n },\n { words: ['meticulous', 'crucial', 'pivotal', 'vital', 'paramount'], why: 'tells the reader how to feel instead of what it is' },\n {\n words: ['comprehensive', 'myriad', 'plethora', 'a variety of', 'a wide range of'],\n why: 'is padding: name the things, or say how many',\n },\n {\n words: ['furthermore', 'moreover', 'additionally', 'in order to', 'please note', 'note that', 'keep in mind', 'rest assured'],\n why: 'is a connective a short string has no room for',\n },\n { words: ['intuitive', 'sleek', 'stunning', 'beautiful', 'delightful', 'magical'], why: 'grades the product instead of describing it' },\n { words: ['simply', 'just', 'easily', 'easy', 'quickly'], why: 'says it is easy, which helps nobody it is not easy for' },\n { words: ['so you can', 'allows you to', 'lets you', 'enables you to', \"don't worry\"], why: 'justifies or reassures: state the fact' },\n { words: ['please', 'oops', 'whoops', 'sorry'], why: 'pleads or apologizes: say what failed and what to do' },\n { words: ['etc', 'and more', 'and so on'], why: 'trails off: name the things or stop' },\n ],\n spelling: {\n colour: 'color',\n colours: 'colors',\n behaviour: 'behavior',\n favourite: 'favorite',\n cancelled: 'canceled',\n cancelling: 'canceling',\n labelled: 'labeled',\n centre: 'center',\n licence: 'license',\n grey: 'gray',\n organise: 'organize',\n recognise: 'recognize',\n customise: 'customize',\n optimise: 'optimize',\n minimise: 'minimize',\n maximise: 'maximize',\n synchronise: 'synchronize',\n authorise: 'authorize',\n initialise: 'initialize',\n analyse: 'analyze',\n catalogue: 'catalog',\n dialogue: 'dialog',\n artefact: 'artifact',\n judgement: 'judgment',\n whilst: 'while',\n amongst: 'among',\n } as Record<string, string>,\n};\n","/**\n * `prosebook/config`: where the catalog lives, what an entry may say about itself, and how strictly\n * its words are checked. Written as `prosebook.config.ts` (or `.js`, `.mjs`, `.json`) at the project root.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { isAbsolute, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { compileRule, CORE_RULES, type CheckRule, type CoreRule, type Plugin } from './lint.ts';\nimport type { Isolate } from './mf2.ts';\nimport { DEFAULT_KINDS, DEFAULT_SURFACES, STRICT_LISTS, type KindRule, type Severity } from './presets.ts';\n\nexport type { KindRule, Severity };\nexport {\n definePlugin,\n HOLE,\n phrase,\n sentences,\n words,\n type CapitalizationRule,\n type CheckRule,\n type ConditionalRule,\n type ExistenceRule,\n type OccurrenceRule,\n type Plugin,\n type Readings,\n type Report,\n type Rule,\n type RuleContext,\n type SubstitutionRule,\n} from './lint.ts';\n\nexport interface WordLists {\n /** Words a string never uses, in groups that say why. */\n banned?: { words: string[]; why: string }[];\n /** A spelling, and the one the product uses instead. */\n spelling?: Record<string, string>;\n /** A near-synonym, and the one word the product uses for that concept. */\n concepts?: Record<string, string>;\n /** Words that keep their capital inside a sentence-case string: product names, platforms. */\n properNouns?: string[];\n /** What a path through menus or settings is written with, spaced: `›` by default, as in Settings › General. */\n pathSeparator?: string;\n}\n\ntype RuleSeverities = Partial<Record<CoreRule, Severity>> & Record<string, Severity>;\n\nexport interface LintConfig extends WordLists {\n /** `recommended` (the default) checks shape; `strict` adds the word lists and rules of a house style guide. */\n extends?: 'recommended' | 'strict' | 'none';\n /** Rules of your own, as `<plugin>/<rule>`. Each takes the severity it gives itself under `extends`. */\n plugins?: Plugin[];\n rules?: RuleSeverities;\n /** Severities for one area's entries (a key's first segment) over `rules`: `{ native: { 'sentence-case': 'off' } }`. */\n areas?: Record<string, RuleSeverities>;\n}\n\n/**\n * Native code generated from the catalog, for the parts of an app outside the browser: a tray, a\n * menu bar, a CLI. One file, holding every locale, with a typed function per message; for Android and\n * Apple, string resources, a file per locale.\n */\nexport interface NativeTarget {\n language: 'rust' | 'swift' | 'kotlin' | 'android' | 'apple';\n /**\n * The file written; for Android, the `res` folder its `values*` folders go in, and for Apple, the\n * folder its `.lproj` folders go in.\n */\n out: string;\n /**\n * Key prefixes the file holds: `['native']` takes every `native.*` key, which it names without the\n * prefix (`native.tray.quit` is `tray_quit`). Every key, named in full, by default.\n */\n keys?: string[];\n /**\n * The type holding the locales and messages: `Locale` in Rust, `Copy` in Swift and Kotlin. For\n * Android, the resource file's name: `strings`, for `values/strings.xml`. For Apple, the table's:\n * `Localizable`, or `InfoPlist` with `plist`.\n */\n name?: string;\n /** Kotlin's package. */\n package?: string;\n /**\n * For Apple, the Info.plist the table translates: each key names one of its strings, spelled in\n * words (`ns-camera-usage-description` is `NSCameraUsageDescription`), and the source must say\n * what the plist says.\n */\n plist?: string;\n}\n\nexport interface ProsebookConfig {\n /** The source-language catalog: one `<area>.yaml` per area. */\n catalog?: string;\n /** Translations: `<locale>/<area>.yaml` or `<locale>.yaml`, holding `key: message`. */\n locales?: string;\n /** Where the generated modules go. */\n out?: string;\n /** Records which source text each translation was made from, so a changed source marks it stale. */\n lock?: string;\n /** The locale the catalog is written in. Its code is also the field holding the message. */\n source?: string;\n /**\n * The syntax messages are written in: ICU MessageFormat (1) or Unicode MessageFormat 2. Source and\n * translations alike; `prosebook migrate` rewrites a catalog from one to the other.\n */\n messageFormat?: 1 | 2;\n /**\n * In MF2, when a placeholder is wrapped in Unicode isolation marks, so a value written the other\n * way (a Latin name in Hebrew) can't reorder the text around it. `'rtl'`, the default: in locales\n * written right to left, and wherever `u:dir` asks. `'always'`: also every string in any locale,\n * as the spec's default has it. `false`: never.\n */\n isolate?: Isolate;\n /** Locales that ship in the main bundle beside the source, rather than loading when first used. */\n bundled?: string[];\n /** A pseudo-locale generated from the source (accented and lengthened) to find layout bugs and hardcoded text. */\n pseudo?: string | false;\n /** What a translation whose source changed since does: still show (`use`) or show the source (`fallback`). */\n stale?: 'use' | 'fallback';\n /** Generated modules as TypeScript or as JavaScript with a `.d.ts` beside the index. */\n language?: 'ts' | 'js';\n /** The extension generated imports name: `.js` suits most TypeScript setups, `.ts` suits Node's type stripping. */\n importExtension?: '.js' | '.ts' | '';\n /** The fields every entry must have. A shorthand `key: message` entry satisfies none of them. */\n require?: ('context' | 'kind' | 'surface')[];\n /** The kinds of string an entry may say it is, with the shape each one is held to. */\n kinds?: Record<string, KindRule>;\n /** Where a string may sit, with what each surface means. */\n surfaces?: Record<string, string>;\n lint?: LintConfig;\n /** Rust, Swift or Kotlin files `generate` writes beside the TypeScript. */\n native?: NativeTarget[];\n /** Where `prosebook scan` looks for hardcoded text and catalog keys. */\n scan?: {\n dirs?: string[];\n extensions?: string[];\n /** JSX attributes whose literal value a person reads. */\n attributes?: string[];\n };\n}\n\nexport interface ResolvedConfig {\n root: string;\n catalog: string;\n locales: string;\n out: string;\n lock: string;\n source: string;\n messageFormat: 1 | 2;\n isolate: Isolate;\n bundled: string[];\n pseudo: string | false;\n stale: 'use' | 'fallback';\n language: 'ts' | 'js';\n importExtension: '.js' | '.ts' | '';\n require: ('context' | 'kind' | 'surface')[];\n kinds: Record<string, KindRule>;\n surfaces: Record<string, string>;\n lint: {\n rules: Record<string, { rule: CheckRule; severity: Severity }>;\n areas: Record<string, Record<string, Severity>>;\n } & Required<WordLists>;\n native: (NativeTarget & { name: string })[];\n scan: { dirs: string[]; extensions: string[]; attributes: string[] };\n}\n\nconst NATIVE_NAMES = { rust: 'Locale', swift: 'Copy', kotlin: 'Copy', android: 'strings', apple: 'Localizable' };\n\n/** Typed config, for `prosebook.config.ts`. */\nexport function defineConfig(config: ProsebookConfig): ProsebookConfig {\n return config;\n}\n\nexport const CONFIG_FILES = [\n 'prosebook.config.ts',\n 'prosebook.config.mts',\n 'prosebook.config.js',\n 'prosebook.config.mjs',\n 'prosebook.config.json',\n];\n\n/** Finds and reads the config at `root`, or the defaults when there is none. */\nexport async function loadConfig(root: string, inline?: ProsebookConfig): Promise<ResolvedConfig> {\n if (inline) return resolveConfig(root, inline);\n for (const name of CONFIG_FILES) {\n const path = join(root, name);\n if (!existsSync(path)) continue;\n if (name.endsWith('.json')) return resolveConfig(root, JSON.parse(readFileSync(path, 'utf8')) as ProsebookConfig);\n const mod = (await import(pathToFileURL(path).href)) as { default?: ProsebookConfig };\n return resolveConfig(root, mod.default ?? {});\n }\n return resolveConfig(root, {});\n}\n\nexport function resolveConfig(root: string, config: ProsebookConfig): ResolvedConfig {\n const at = (path: string) => (isAbsolute(path) ? path : resolve(root, path));\n const lint = config.lint ?? {};\n const base = lint.extends ?? 'recommended';\n const strict = base === 'strict';\n const rules = lintRules(lint);\n for (const [area, severities] of Object.entries(lint.areas ?? {})) {\n for (const name of Object.keys(severities))\n if (!(name in rules)) throw new Error(`lint.areas.${area}.${name} is not a rule: name one of ${Object.keys(rules).join(', ')}`);\n }\n return {\n root,\n catalog: at(config.catalog ?? 'copy/catalog'),\n locales: at(config.locales ?? 'copy/locales'),\n out: at(config.out ?? 'src/copy'),\n lock: at(config.lock ?? 'copy/lock.json'),\n source: config.source ?? 'en',\n messageFormat: config.messageFormat ?? 1,\n isolate: config.isolate ?? 'rtl',\n bundled: config.bundled ?? [],\n pseudo: config.pseudo ?? false,\n stale: config.stale ?? 'use',\n language: config.language ?? 'ts',\n importExtension: config.importExtension ?? '.js',\n require: config.require ?? ['context'],\n kinds: config.kinds ?? DEFAULT_KINDS,\n surfaces: config.surfaces ?? DEFAULT_SURFACES,\n lint: {\n rules,\n areas: lint.areas ?? {},\n banned: [...(strict ? STRICT_LISTS.banned : []), ...(lint.banned ?? [])],\n spelling: { ...(strict ? STRICT_LISTS.spelling : {}), ...lint.spelling },\n concepts: { ...lint.concepts },\n properNouns: lint.properNouns ?? [],\n pathSeparator: lint.pathSeparator ?? '›',\n },\n native: (config.native ?? []).map((target, i) => {\n if (!(target.language in NATIVE_NAMES))\n throw new Error(`native[${i}].language is \"${target.language}\": name one of ${Object.keys(NATIVE_NAMES).join(', ')}`);\n if (target.plist !== undefined && target.language !== 'apple')\n throw new Error(`native[${i}].plist names an Info.plist, which only the apple target reads: remove it, or set language to 'apple'`);\n const plist = target.plist === undefined ? {} : { plist: at(target.plist) };\n const name = target.name ?? (target.plist === undefined ? NATIVE_NAMES[target.language] : 'InfoPlist');\n return { ...target, out: at(target.out), name, ...plist };\n }),\n scan: {\n dirs: (config.scan?.dirs ?? ['src']).map(at),\n extensions: config.scan?.extensions ?? ['.ts', '.tsx', '.js', '.jsx', '.mts', '.mjs', '.vue', '.svelte'],\n attributes: config.scan?.attributes ?? ['alt', 'title', 'placeholder', 'label', 'aria-label', 'aria-description', 'aria-placeholder'],\n },\n };\n}\n\nfunction lintRules(lint: LintConfig): ResolvedConfig['lint']['rules'] {\n const base = lint.extends ?? 'recommended';\n const all: [string, CheckRule][] = Object.entries(CORE_RULES);\n const seen = new Set<string>();\n for (const plugin of lint.plugins ?? []) {\n if (!/^[a-z][a-z0-9-]*$/i.test(plugin.name))\n throw new Error(`lint.plugins: \"${plugin.name}\" is not a plugin name: use letters, digits and dashes`);\n if (seen.has(plugin.name)) throw new Error(`lint.plugins: \"${plugin.name}\" is added twice: remove one`);\n seen.add(plugin.name);\n for (const [name, rule] of Object.entries(plugin.rules)) {\n const full = `${plugin.name}/${name}`;\n all.push([full, compileRule(full, rule)]);\n }\n }\n const preset = (rule: CheckRule): Severity =>\n base === 'none' ? 'off' : base === 'strict' ? (rule.strict ?? 'error') : (rule.recommended ?? 'off');\n const rules = Object.fromEntries(all.map(([name, rule]) => [name, { rule, severity: lint.rules?.[name] ?? preset(rule) }]));\n for (const name of Object.keys(lint.rules ?? {}))\n if (!(name in rules)) throw new Error(`lint.rules.${name} is not a rule: name one of ${Object.keys(rules).join(', ')}`);\n return rules;\n}\n"],"mappings":"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"}
|
|
@@ -467,21 +467,35 @@ interface LintConfig extends WordLists {
|
|
|
467
467
|
}
|
|
468
468
|
/**
|
|
469
469
|
* Native code generated from the catalog, for the parts of an app outside the browser: a tray, a
|
|
470
|
-
* menu bar, a CLI. One file, holding every locale, with a typed function per message
|
|
470
|
+
* menu bar, a CLI. One file, holding every locale, with a typed function per message; for Android and
|
|
471
|
+
* Apple, string resources, a file per locale.
|
|
471
472
|
*/
|
|
472
473
|
interface NativeTarget {
|
|
473
|
-
language: 'rust' | 'swift' | 'kotlin';
|
|
474
|
-
/**
|
|
474
|
+
language: 'rust' | 'swift' | 'kotlin' | 'android' | 'apple';
|
|
475
|
+
/**
|
|
476
|
+
* The file written; for Android, the `res` folder its `values*` folders go in, and for Apple, the
|
|
477
|
+
* folder its `.lproj` folders go in.
|
|
478
|
+
*/
|
|
475
479
|
out: string;
|
|
476
480
|
/**
|
|
477
481
|
* Key prefixes the file holds: `['native']` takes every `native.*` key, which it names without the
|
|
478
482
|
* prefix (`native.tray.quit` is `tray_quit`). Every key, named in full, by default.
|
|
479
483
|
*/
|
|
480
484
|
keys?: string[];
|
|
481
|
-
/**
|
|
485
|
+
/**
|
|
486
|
+
* The type holding the locales and messages: `Locale` in Rust, `Copy` in Swift and Kotlin. For
|
|
487
|
+
* Android, the resource file's name: `strings`, for `values/strings.xml`. For Apple, the table's:
|
|
488
|
+
* `Localizable`, or `InfoPlist` with `plist`.
|
|
489
|
+
*/
|
|
482
490
|
name?: string;
|
|
483
491
|
/** Kotlin's package. */
|
|
484
492
|
package?: string;
|
|
493
|
+
/**
|
|
494
|
+
* For Apple, the Info.plist the table translates: each key names one of its strings, spelled in
|
|
495
|
+
* words (`ns-camera-usage-description` is `NSCameraUsageDescription`), and the source must say
|
|
496
|
+
* what the plist says.
|
|
497
|
+
*/
|
|
498
|
+
plist?: string;
|
|
485
499
|
}
|
|
486
500
|
interface ProsebookConfig {
|
|
487
501
|
/** The source-language catalog: one `<area>.yaml` per area. */
|
|
@@ -573,4 +587,4 @@ declare const CONFIG_FILES: string[];
|
|
|
573
587
|
declare function loadConfig(root: string, inline?: ProsebookConfig): Promise<ResolvedConfig>;
|
|
574
588
|
declare function resolveConfig(root: string, config: ProsebookConfig): ResolvedConfig;
|
|
575
589
|
export { loadCatalog as $, RuleContext as A, DEFAULT_KINDS as B, Finding as C, Readings as D, Plugin as E, lint as F, Catalog as G, KindRule as H, phrase as I, KEY_PATTERN as J, CatalogError as K, sentences as L, applyEdits as M, compileRule as N, Report as O, definePlugin as P, entryLocation as Q, singularOf as R, ExistenceRule as S, OccurrenceRule as T, STRICT_LISTS as U, DEFAULT_SURFACES as V, Severity as W, Problem as X, Message as Y, Translation as Z, CapitalizationRule as _, ResolvedConfig as a, CoreRule as b, loadConfig as c, Mf2Function as d, previewOf as et, intlDate as f, CORE_RULES as g, toMf2 as h, ProsebookConfig as i, SubstitutionRule as j, Rule as k, resolveConfig as l, parseMf2 as m, LintConfig as n, MessageFormatElement as nt, WordLists as o, intlNumber as p, EntryLocation as q, NativeTarget as r, defineConfig as s, CONFIG_FILES as t, whereOf as tt, Isolate as u, CheckRule as v, HOLE as w, Edit as x, ConditionalRule as y, words as z };
|
|
576
|
-
//# sourceMappingURL=config-
|
|
590
|
+
//# sourceMappingURL=config-CzaJJQ60.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-
|
|
1
|
+
{"version":3,"file":"config-CzaJJQ60.d.ts","names":[],"sources":["../src/tools/catalog.ts","../src/tools/presets.ts","../src/tools/lint.ts","../src/tools/mf2.ts","../src/tools/config.ts"],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as RuleContext, D as Readings, E as Plugin, H as KindRule, I as phrase, L as sentences, O as Report, P as definePlugin, S as ExistenceRule, T as OccurrenceRule, W as Severity, _ as CapitalizationRule, a as ResolvedConfig, c as loadConfig, i as ProsebookConfig, j as SubstitutionRule, k as Rule, l as resolveConfig, n as LintConfig, o as WordLists, r as NativeTarget, s as defineConfig, t as CONFIG_FILES, v as CheckRule, w as HOLE, y as ConditionalRule, z as words } from "./config-
|
|
1
|
+
import { A as RuleContext, D as Readings, E as Plugin, H as KindRule, I as phrase, L as sentences, O as Report, P as definePlugin, S as ExistenceRule, T as OccurrenceRule, W as Severity, _ as CapitalizationRule, a as ResolvedConfig, c as loadConfig, i as ProsebookConfig, j as SubstitutionRule, k as Rule, l as resolveConfig, n as LintConfig, o as WordLists, r as NativeTarget, s as defineConfig, t as CONFIG_FILES, v as CheckRule, w as HOLE, y as ConditionalRule, z as words } from "./config-CzaJJQ60.js";
|
|
2
2
|
export { CONFIG_FILES, type CapitalizationRule, type CheckRule, type ConditionalRule, type ExistenceRule, HOLE, type KindRule, LintConfig, NativeTarget, type OccurrenceRule, type Plugin, ProsebookConfig, type Readings, type Report, ResolvedConfig, type Rule, type RuleContext, type Severity, type SubstitutionRule, WordLists, defineConfig, definePlugin, loadConfig, phrase, resolveConfig, sentences, words };
|
package/dist/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as CONFIG_FILES, l as HOLE, n as defineConfig, f as definePlugin, r as loadConfig, m as phrase, i as resolveConfig, h as sentences, _ as words } from "./config-
|
|
1
|
+
export { t as CONFIG_FILES, l as HOLE, n as defineConfig, f as definePlugin, r as loadConfig, m as phrase, i as resolveConfig, h as sentences, _ as words } from "./config-7T4hX_f7.js";
|
|
@@ -108,6 +108,11 @@ type RichKey<M extends MessageShapes> = { [K in keyof M]: [M[K]['tags']] extends
|
|
|
108
108
|
type Loader = () => Promise<{
|
|
109
109
|
default: CompiledMessages;
|
|
110
110
|
}>;
|
|
111
|
+
/** Messages that ship in the bundle and loaders for the rest, per locale: a catalog's, or one area's. */
|
|
112
|
+
interface Pieces<L extends string = string> {
|
|
113
|
+
readonly messages: { readonly [locale in L]?: CompiledMessages; };
|
|
114
|
+
readonly loaders: { readonly [locale in L]?: Loader; };
|
|
115
|
+
}
|
|
111
116
|
/** A generated catalog: which locales exist, which ship in the bundle and how to fetch the rest. */
|
|
112
117
|
interface Catalog<M extends MessageShapes = MessageShapes, L extends string = string> {
|
|
113
118
|
/** The locale the catalog is written in, which every other falls back to. */
|
|
@@ -117,9 +122,30 @@ interface Catalog<M extends MessageShapes = MessageShapes, L extends string = st
|
|
|
117
122
|
readonly messages: { readonly [locale in L]?: CompiledMessages; };
|
|
118
123
|
/** Locales fetched when first asked for. */
|
|
119
124
|
readonly loaders: { readonly [locale in L]?: Loader; };
|
|
125
|
+
/**
|
|
126
|
+
* Set when a build splits the catalog by area (the Vite plugin's `split`): `messages` and `loaders`
|
|
127
|
+
* are empty, and each area adds its own (`addArea`) as the code reading it loads.
|
|
128
|
+
*/
|
|
129
|
+
readonly split?: {
|
|
130
|
+
readonly id: string;
|
|
131
|
+
readonly areas: readonly string[];
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Set in a server build whose client is split (the Vite plugin's `split`): the file the browser
|
|
135
|
+
* loads each area's messages from, per lazy locale, which `CopyOptions.preload` is handed.
|
|
136
|
+
*/
|
|
137
|
+
readonly areaFiles?: {
|
|
138
|
+
readonly [area: string]: { readonly [locale in L]?: string; };
|
|
139
|
+
};
|
|
120
140
|
/** Type-only: carries the message shapes from the generated module to `createCopy`. */
|
|
121
141
|
readonly '~messages'?: M;
|
|
122
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Adds an area's messages to a split catalog. Called by generated code, from a module beside the code
|
|
145
|
+
* that reads the area; settles once every copy holds the area in its locale, so that code's first
|
|
146
|
+
* render reads it. A locale that fails to load reads in its fallback, and is reported.
|
|
147
|
+
*/
|
|
148
|
+
declare function addArea(id: string, area: string, messages: Pieces['messages'], loaders: Pieces['loaders']): Promise<void>;
|
|
123
149
|
/** Ties a generated catalog to its message shapes. Called by generated code. */
|
|
124
150
|
declare function defineCatalog<M extends MessageShapes, L extends string = string>(catalog: Omit<Catalog<M, L>, '~messages'>): Catalog<M, L>;
|
|
125
151
|
interface CopyOptions<L extends string> {
|
|
@@ -133,9 +159,17 @@ interface CopyOptions<L extends string> {
|
|
|
133
159
|
onMissing?: (key: string, locale: L) => string;
|
|
134
160
|
/**
|
|
135
161
|
* Told of a placeholder that had no value, or one `Intl` refused (`currency: 'euro'`): the message
|
|
136
|
-
* still renders, showing `{name}` there.
|
|
162
|
+
* still renders, showing `{name}` there. In a split build, also of a key read before its area
|
|
163
|
+
* loaded. Defaults to `console.error`.
|
|
137
164
|
*/
|
|
138
165
|
onError?: (error: Error, key: string, locale: L) => void;
|
|
166
|
+
/**
|
|
167
|
+
* On a server, handed each file the browser will load for the areas this copy reads, once each,
|
|
168
|
+
* so the page can link it and the browser fetch it beside the code reading it rather than after:
|
|
169
|
+
* `(href) => preloadModule(href, { as: 'script' })` under React. Only a catalog built for a split
|
|
170
|
+
* client has such files (`Catalog.areaFiles`), and only its lazy locales.
|
|
171
|
+
*/
|
|
172
|
+
preload?: (href: string) => void;
|
|
139
173
|
}
|
|
140
174
|
/** Its methods don't use `this`, so they can be passed around and destructured: `const { t } = copy`. */
|
|
141
175
|
interface Copy<M extends MessageShapes = MessageShapes, L extends string = string> {
|
|
@@ -171,5 +205,5 @@ interface Copy<M extends MessageShapes = MessageShapes, L extends string = strin
|
|
|
171
205
|
}
|
|
172
206
|
/** A catalog reader with a current locale. Create one per app, or one per request on a server. */
|
|
173
207
|
declare function createCopy<M extends MessageShapes, L extends string>(catalog: Catalog<M, L>, options?: CopyOptions<L>): Copy<M, L>;
|
|
174
|
-
export {
|
|
175
|
-
//# sourceMappingURL=copy-
|
|
208
|
+
export { RichParam as C, RichKey as S, TagFn as T, MessageShapes as _, createCopy as a, RegisteredLocale as b, ArgsParam as c, CompiledMessages as d, DefaultTags as f, MessageShape as g, HotHook as h, addArea as i, Chunks as l, Helpers as m, Copy as n, defineCatalog as o, DevHooks as p, CopyOptions as r, AnyTagFn as s, Catalog as t, Compiled as u, ReadHook as v, RichValues as w, RegisteredMessages as x, Register as y };
|
|
209
|
+
//# sourceMappingURL=copy-BXn0aYQn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-BXn0aYQn.d.ts","names":[],"sources":["../src/runtime/types.ts","../src/runtime/copy.ts"],"mappings":";;;;;;;;UASiB;EACf;EACA;;;KAIU;GAAmB,cAAc;;;;;;;;;;;;;;;UAgB5B;KAEL,qBAAqB;EAAmB,gBAAgB,UAAU;IAAkB,IAAI;KACxF,mBAAmB;EAAmB,cAAc;IAAqB;;KAEzE,cAAc;EAAmB,YAAY;IAAqB;;;;;UAM7D;WACN;;;;;EAKT,EAAE,eAAe,UAAU,KAAK,qBAAqB,QAAQ,KAAK;;EAElE,EAAE,OAAO,eAAe,UAAU,KAAK,uBAAuB,QAAQ,KAAK;;EAE3E,EAAE;;;;;EAKF,EACE,eACA,gBACA,kBACA,MAAM,MACN,UAAU,KAAK,oBACf,QAAQ,KAAK;;EAGf,EAAE,gBAAgB,MAAM;;EAExB,EAAE,QAAQ,QAAQ,aAAa;;KAGrB;GAAU;;KAIV;YAAqB;;;;;;;KAOrB,YAAY,aAAa,cAAc;;KAGvC,WAAW,gBAAgB,UAAU;;;;;KAMrC;EAAa,qBAAqB;EAAU,oBAAoB,IAAI;;;KAGpE,sBAAsB,QAAQ,QAAQ,GAAG;;KAGzC;YAA+B,cAAc;;;KAG7C,OAAO,eAAe;KACtB,MAAM,MAAM,QAAQ,OAAO,OAAO;;KAElC,YAAY;KAEnB,OAAO,gBAAgB;;KAGhB,UAAU,UAAU,gBAAgB,OAAO,2BAA2B,OAAO,cAAc,MAAM;KAExG,UAAU,UAAU,cAAc,QAAQ,KAAK,QAAQ,WAAW,eAAe,MAAM,WACzF,KAAK,QAAQ,WAAW,gBAAgB,MAAM;;KAIrC,WAAW,UAAU,cAAc,KAAK,YAAY,UAAU,GAAG;KACjE,UAAU,UAAU,cAAc,KAC5C,OAAO,WAAW,GAAG,oBAAoB,SAAS,WAAW,GAAG,OAAO,QAAQ,WAAW,GAAG;;KAGnF,QAAQ,UAAU,oBAAoB,WAAW,KAAK,EAAE,sCAAsC,WAAU;KCxG/G,eAAe;EAAU,SAAS;;;UAG7B,OAAO;WACN,sBAAsB,UAAU,KAAK;WACrC,qBAAqB,UAAU,KAAK;;;UAI9B,QAAQ,UAAU,gBAAgB,eAAe;;WAEvD,QAAQ;WACR,kBAAkB;;WAElB,sBAAsB,UAAU,KAAK;;WAErC,qBAAqB,UAAU,KAAK;;;;;WAKpC;aAAmB;aAAqB;;;;;;WAKxC;cAAwB,2BAA2B,UAAU;;;WAE7D,cAAc;;;;;;;iBAwBH,QAAQ,YAAY,cAAc,UAAU,oBAAoB,SAAS,oBAAoB;;iBASnG,cAAc,UAAU,eAAe,2BACrD,SAAS,KAAK,QAAQ,GAAG,mBACxB,QAAQ,GAAG;UAIG,YAAY;;EAE3B,SAAS;;EAET;KAAU,cAAc;;;EAExB,aAAa,aAAa,QAAQ;;;;;;EAMlC,WAAW,OAAO,OAAO,aAAa,QAAQ;;;;;;;EAO9C,WAAW;;;UAII,KAAK,UAAU,gBAAgB,eAAe;;WAEpD,QAAQ;WACR,kBAAkB;WAClB,QAAQ;;WAER;cAAkB,cAAc;;;WAEhC,OAAO;;EAEhB,EAAE,gBAAgB,YAAY,YAAY,KAAK,MAAM,MAAM,UAAU,EAAE;;EAEvE,KAAK,UAAU,QAAQ,IAAI,aAAa,YAAY,KAAK,MAAM,QAAQ,UAAU,EAAE,IAAI,KAAK,OAAO;EACnG,IAAI,YAAY,cAAc,aAAa;;EAE3C,UAAU,YAAY,MAAM,wCAAwC;;WAE3D;;EAET,UAAU,YAAY;;EAEtB,OAAO,YAAY,wBAAwB,UAAU,KAAK;;EAE1D,KAAK,YAAY,OAAO,eAAe,UAAU,KAAK;;EAEtD,KAAK,YAAY,OAAO,kBAAkB,UAAU,KAAK;;EAEzD,SAAS,YAAY,eAAe,MAAM,KAAK,wBAAwB,UAAU,KAAK;;;iBAyBxE,WAAW,UAAU,eAAe,kBAAkB,SAAS,QAAQ,GAAG,IAAI,UAAS,YAAY,KAAU,KAAK,GAAG"}
|