@pixi-ui-editor/schema 0.11.0 → 0.13.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.
@@ -1,5 +1,5 @@
1
1
  import { type Static } from "@sinclair/typebox";
2
- import type { ProjectDocument, ValidationIssue } from "./index.js";
2
+ import type { ProjectDocument, TextCase, ValidationIssue } from "./index.js";
3
3
  export declare const LocalizationLocaleSchema: import("@sinclair/typebox").TObject<{
4
4
  id: import("@sinclair/typebox").TString;
5
5
  label: import("@sinclair/typebox").TString;
@@ -91,6 +91,13 @@ export type LocalizedTextResolution = {
91
91
  */
92
92
  export declare function describeLocalizedText(input: ResolveLocalizedTextInput): LocalizedTextResolution;
93
93
  export declare function resolveLocalizedText(input: ResolveLocalizedTextInput): string;
94
+ /**
95
+ * `Text.textCase` display transform: applied last, on top of whatever `describeLocalizedText`
96
+ * resolved (authored string, live preview, or translation) — never written back into `text` or a
97
+ * catalog entry, so the source string and the case choice stay independently editable. Omitted/`"none"`
98
+ * is a no-op, keeping every existing document's rendered output unchanged.
99
+ */
100
+ export declare function applyTextCase(text: string, textCase: TextCase | undefined): string;
94
101
  /** Владелец иерархии, в которой найдена ссылка: сцена или определение пресета. */
95
102
  export type LocalizationReferenceOwner = {
96
103
  kind: "scene";
@@ -1 +1 @@
1
- {"version":3,"file":"localization.d.ts","sourceRoot":"","sources":["../src/localization.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"localization.d.ts","sourceRoot":"","sources":["../src/localization.ts"],"names":[],"mappings":"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"}
@@ -161,6 +161,19 @@ export function describeLocalizedText(input) {
161
161
  export function resolveLocalizedText(input) {
162
162
  return describeLocalizedText(input).value;
163
163
  }
164
+ /**
165
+ * `Text.textCase` display transform: applied last, on top of whatever `describeLocalizedText`
166
+ * resolved (authored string, live preview, or translation) — never written back into `text` or a
167
+ * catalog entry, so the source string and the case choice stay independently editable. Omitted/`"none"`
168
+ * is a no-op, keeping every existing document's rendered output unchanged.
169
+ */
170
+ export function applyTextCase(text, textCase) {
171
+ switch (textCase) {
172
+ case "uppercase": return text.toUpperCase();
173
+ case "lowercase": return text.toLowerCase();
174
+ default: return text;
175
+ }
176
+ }
164
177
  /**
165
178
  * Все ссылки `Text.textKey` документа: сцены, определения пресетов, локально добавленные узлы любой
166
179
  * вложенности и persisted property overrides. Унаследованные узлы инстанса ключ не «размножают»:
@@ -1 +1 @@
1
- {"version":3,"file":"localization.js","sourceRoot":"","sources":["../src/localization.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type, type Static } from \"@sinclair/typebox\";\r\nimport type { ProjectDocument, UINode, ValidationIssue } from \"./index.js\";\r\nimport { materializedPrefabNodeId } from \"./prefabs.js\";\r\n\r\n/**\r\n * Единственная реализация локализации документа: контракт каталога, канонизация locale ID,\r\n * fallback-цепочка, интерполяция параметров, сбор ссылок `Text.textKey`, покрытие и диагностики.\r\n *\r\n * Runtime, экспорт, редактор и демо обязаны переиспользовать именно её: дублирование fallback- или\r\n * interpolation-логики в другом слое немедленно расходится по поведению.\r\n */\r\n\r\nconst LocaleIdSchema = Type.String({ minLength: 1 });\r\nexport const LocalizationLocaleSchema = Type.Object({ id: LocaleIdSchema, label: Type.String({ minLength: 1 }) });\r\nexport type LocalizationLocale = Static<typeof LocalizationLocaleSchema>;\r\n/**\r\n * `entries[key][localeId]` — плоская строка перевода. Отсутствующий перевод — это отсутствие\r\n * свойства локали, а не пустая строка: `\"\"` является валидным заполненным переводом и обрывает\r\n * fallback, поэтому резолвер нигде не проверяет значения через truthiness.\r\n */\r\nexport const LocalizationSchema = Type.Object({\r\n baseLocale: LocaleIdSchema,\r\n locales: Type.Array(LocalizationLocaleSchema),\r\n entries: Type.Record(Type.String({ minLength: 1 }), Type.Record(Type.String({ minLength: 1 }), Type.String())),\r\n});\r\nexport type LocalizationCatalog = Static<typeof LocalizationSchema>;\r\n\r\nexport const DEFAULT_LOCALE_ID = \"en\";\r\n/** Каталог, который получает документ v19 при миграции и любой новый проект. */\r\nexport function createDefaultLocalization(): LocalizationCatalog {\r\n return { baseLocale: DEFAULT_LOCALE_ID, locales: [{ id: DEFAULT_LOCALE_ID, label: \"English\" }], entries: {} };\r\n}\r\n\r\n/**\r\n * Каноническая BCP-47 форма: `en`, `en-US`, `pt-BR`, `zh-Hant`, `zh-Hant-TW`.\r\n *\r\n * Грамматика намеренно узкая — только буквы, три цифры региона и дефис. Поэтому канонический ID\r\n * автоматически является безопасным сегментом пути `locales/<locale>.json`: в нём не может быть\r\n * ни `/`, ни `\\`, ни `.`, ни `..`.\r\n */\r\nexport function canonicalizeLocaleId(input: string): string | undefined {\r\n const parts = input.trim().split(\"-\");\r\n const language = parts[0];\r\n if (language === undefined || !/^[A-Za-z]{2,3}$/.test(language)) return undefined;\r\n const segments = [language.toLowerCase()];\r\n let index = 1;\r\n const script = parts[index];\r\n if (script !== undefined && /^[A-Za-z]{4}$/.test(script)) { segments.push(`${script[0]!.toUpperCase()}${script.slice(1).toLowerCase()}`); index += 1; }\r\n const region = parts[index];\r\n if (region !== undefined) {\r\n if (/^[A-Za-z]{2}$/.test(region)) segments.push(region.toUpperCase());\r\n else if (/^[0-9]{3}$/.test(region)) segments.push(region);\r\n else return undefined;\r\n index += 1;\r\n }\r\n return index === parts.length ? segments.join(\"-\") : undefined;\r\n}\r\n\r\nexport function isCanonicalLocaleId(id: string): boolean { return canonicalizeLocaleId(id) === id; }\r\n\r\n/**\r\n * Справочник популярных локалей для UI выбора языка: готовый ID в канонической форме плюс\r\n * английский display label. Он живёт рядом с `canonicalizeLocaleId`, потому что это часть\r\n * локализационной модели, а не украшение панели: каждая запись обязана удовлетворять\r\n * `canonicalizeLocaleId(id) === id`, иначе выбор из списка создал бы невалидный документ.\r\n *\r\n * Список намеренно неполон — он покрывает частые случаи и снимает ручной ввод, а редкая локаль\r\n * по-прежнему добавляется вводом канонического BCP-47 идентификатора вручную.\r\n */\r\nexport const COMMON_LOCALES: readonly { id: string; label: string }[] = [\r\n { id: \"en\", label: \"English\" },\r\n { id: \"en-US\", label: \"English (United States)\" },\r\n { id: \"en-GB\", label: \"English (United Kingdom)\" },\r\n { id: \"ru\", label: \"Russian\" },\r\n { id: \"ru-RU\", label: \"Russian (Russia)\" },\r\n { id: \"uk\", label: \"Ukrainian\" },\r\n { id: \"de\", label: \"German\" },\r\n { id: \"fr\", label: \"French\" },\r\n { id: \"fr-CA\", label: \"French (Canada)\" },\r\n { id: \"es\", label: \"Spanish\" },\r\n { id: \"es-ES\", label: \"Spanish (Spain)\" },\r\n { id: \"es-419\", label: \"Spanish (Latin America)\" },\r\n { id: \"pt-BR\", label: \"Portuguese (Brazil)\" },\r\n { id: \"pt-PT\", label: \"Portuguese (Portugal)\" },\r\n { id: \"it\", label: \"Italian\" },\r\n { id: \"pl\", label: \"Polish\" },\r\n { id: \"tr\", label: \"Turkish\" },\r\n { id: \"nl\", label: \"Dutch\" },\r\n { id: \"sv\", label: \"Swedish\" },\r\n { id: \"da\", label: \"Danish\" },\r\n { id: \"nb\", label: \"Norwegian Bokmal\" },\r\n { id: \"fi\", label: \"Finnish\" },\r\n { id: \"cs\", label: \"Czech\" },\r\n { id: \"sk\", label: \"Slovak\" },\r\n { id: \"hu\", label: \"Hungarian\" },\r\n { id: \"ro\", label: \"Romanian\" },\r\n { id: \"bg\", label: \"Bulgarian\" },\r\n { id: \"el\", label: \"Greek\" },\r\n { id: \"sr\", label: \"Serbian\" },\r\n { id: \"hr\", label: \"Croatian\" },\r\n { id: \"ar\", label: \"Arabic\" },\r\n { id: \"he\", label: \"Hebrew\" },\r\n { id: \"fa\", label: \"Persian\" },\r\n { id: \"hi\", label: \"Hindi\" },\r\n { id: \"th\", label: \"Thai\" },\r\n { id: \"vi\", label: \"Vietnamese\" },\r\n { id: \"id\", label: \"Indonesian\" },\r\n { id: \"ms\", label: \"Malay\" },\r\n { id: \"tl\", label: \"Filipino\" },\r\n { id: \"ja\", label: \"Japanese\" },\r\n { id: \"ko\", label: \"Korean\" },\r\n { id: \"zh-Hans\", label: \"Chinese (Simplified)\" },\r\n { id: \"zh-Hant\", label: \"Chinese (Traditional)\" },\r\n];\r\n\r\n/**\r\n * Порядок локалей для любого UI: base locale первой, остальные сохраняют порядок объявления.\r\n * Правило одно на весь редактор, поэтому и живёт оно здесь, а не копией в каждой панели.\r\n */\r\nexport function orderLocalesForDisplay(catalog: LocalizationCatalog): LocalizationLocale[] {\r\n return [\r\n ...catalog.locales.filter((locale) => locale.id === catalog.baseLocale),\r\n ...catalog.locales.filter((locale) => locale.id !== catalog.baseLocale),\r\n ];\r\n}\r\n\r\nexport const LOCALIZATION_DIRECTORY = \"locales\";\r\nexport const LOCALIZATION_COVERAGE_FILE = `${LOCALIZATION_DIRECTORY}/coverage.json`;\r\n/** Путь словаря внутри пакета. Безопасность сегмента гарантирует канонический ID. */\r\nexport function localeFilePath(localeId: string): string { return `${LOCALIZATION_DIRECTORY}/${localeId}.json`; }\r\n\r\nexport type LocalizationParams = Readonly<Record<string, string | number>>;\r\nconst PARAM_PATTERN = /\\{([A-Za-z0-9_.-]+)\\}/g;\r\n\r\n/** Имена runtime-параметров `{name}` внутри значения перевода, детерминированно отсортированные. */\r\nexport function collectLocalizationParams(value: string): string[] {\r\n return [...new Set([...value.matchAll(PARAM_PATTERN)].map((match) => match[1]!))].sort();\r\n}\r\n\r\n/** Неизвестный параметр остаётся видимым в фигурных скобках — это признак незаполненного значения. */\r\nexport function interpolateLocalizedText(value: string, params?: LocalizationParams): string {\r\n if (params === undefined) return value;\r\n return value.replace(PARAM_PATTERN, (match, name: string) => (Object.hasOwn(params, name) ? String(params[name]) : match));\r\n}\r\n\r\nexport type LocalizationTranslateContext = { key: string; locale: string; baseLocale: string; params?: LocalizationParams };\r\n/** Внешний переводчик потребителя. `undefined` означает «нет мнения» и не обрывает fallback. */\r\nexport type TranslateFn = (key: string, context: LocalizationTranslateContext) => string | undefined;\r\n\r\nexport type ResolveLocalizedTextInput = {\r\n /** Авторская строка `Text.text`: ручной режим и последний содержательный fallback. */\r\n text: string;\r\n textKey?: string;\r\n catalog?: LocalizationCatalog;\r\n locale?: string;\r\n translate?: TranslateFn;\r\n params?: LocalizationParams;\r\n};\r\n\r\n/** Откуда взялась итоговая строка. `literal` — у ноды нет ключа и локализация не участвовала вообще. */\r\nexport type LocalizedTextSource = \"literal\" | \"translate\" | \"locale\" | \"baseLocale\" | \"text\" | \"key\";\r\nexport type LocalizedTextResolution = { value: string; source: LocalizedTextSource };\r\n\r\n/**\r\n * Единственная fallback-цепочка: внешний `translate` → выбранная локаль → базовая локаль →\r\n * `Text.text` → сам ключ. Нода без `textKey` не обращается к локализации вообще, поэтому документ\r\n * без ключей выглядит ровно как до появления каталога.\r\n *\r\n * Возвращает и значение, и источник: редактору нужно показать, почему на макете именно эта строка,\r\n * и он обязан читать это из той же реализации, а не выводить цепочку заново.\r\n */\r\nexport function describeLocalizedText(input: ResolveLocalizedTextInput): LocalizedTextResolution {\r\n const key = input.textKey?.trim();\r\n if (key === undefined || key === \"\") return { value: input.text, source: \"literal\" };\r\n const baseLocale = input.catalog?.baseLocale ?? DEFAULT_LOCALE_ID;\r\n const locale = input.locale ?? baseLocale;\r\n const entry = input.catalog?.entries[key];\r\n const external = input.translate?.(key, { key, locale, baseLocale, params: input.params });\r\n const resolution: LocalizedTextResolution = external !== undefined\r\n ? { value: external, source: \"translate\" }\r\n : entry !== undefined && Object.hasOwn(entry, locale) ? { value: entry[locale]!, source: \"locale\" }\r\n : entry !== undefined && Object.hasOwn(entry, baseLocale) ? { value: entry[baseLocale]!, source: \"baseLocale\" }\r\n : input.text.length > 0 ? { value: input.text, source: \"text\" } : { value: key, source: \"key\" };\r\n return { value: interpolateLocalizedText(resolution.value, input.params), source: resolution.source };\r\n}\r\n\r\nexport function resolveLocalizedText(input: ResolveLocalizedTextInput): string {\r\n return describeLocalizedText(input).value;\r\n}\r\n\r\n/** Владелец иерархии, в которой найдена ссылка: сцена или определение пресета. */\r\nexport type LocalizationReferenceOwner = { kind: \"scene\"; id: string } | { kind: \"prefab\"; id: string };\r\nexport type LocalizationKeyReference = {\r\n key: string;\r\n path: string;\r\n owner: LocalizationReferenceOwner;\r\n /**\r\n * Адрес узла в терминах редактора: собственный id персистентного/локального узла либо\r\n * materialized-адрес `instanceId::prefab-node::nodePath` для property override.\r\n */\r\n nodeId: string;\r\n};\r\n/** Ссылка вместе с записью значения: одна и та же реализация обхода читает и переименовывает ключи. */\r\nexport type LocalizationKeyReferenceSite = LocalizationKeyReference & { setKey(next: string): void };\r\n\r\n/**\r\n * Все ссылки `Text.textKey` документа: сцены, определения пресетов, локально добавленные узлы любой\r\n * вложенности и persisted property overrides. Унаследованные узлы инстанса ключ не «размножают»:\r\n * их источником является узел определения, уже посчитанный обходом `document.prefabs`.\r\n *\r\n * Обход единственный: `collectTextKeyReferences` только собирает результат, а rename каталога\r\n * переписывает ключи через `setKey`, поэтому «где живут ссылки» описано ровно в одном месте.\r\n */\r\nexport function forEachTextKeyReference(document: ProjectDocument, visit: (site: LocalizationKeyReferenceSite) => void): void {\r\n const visitNode = (node: UINode, path: string, owner: LocalizationReferenceOwner): void => {\r\n if (node.type === \"text\" && node.textKey !== undefined) {\r\n visit({ key: node.textKey, path: `${path}/textKey`, owner, nodeId: node.id, setKey: (next) => { node.textKey = next; } });\r\n }\r\n if (node.type !== \"prefab-instance\") return;\r\n (node.propertyOverrides ?? []).forEach((override, index) => {\r\n const value = override.patch.textKey;\r\n if (typeof value !== \"string\") return;\r\n visit({\r\n key: value,\r\n path: `${path}/propertyOverrides/${index}/patch/textKey`,\r\n owner,\r\n nodeId: materializedPrefabNodeId(node.id, override.nodeId),\r\n setKey: (next) => { override.patch.textKey = next; },\r\n });\r\n });\r\n (node.locallyAddedNodes ?? []).forEach((local, index) => visitNode(local, `${path}/locallyAddedNodes/${index}`, owner));\r\n };\r\n document.scenes.forEach((scene, sceneIndex) => scene.nodes.forEach((node, nodeIndex) => visitNode(node, `/scenes/${sceneIndex}/nodes/${nodeIndex}`, { kind: \"scene\", id: scene.id })));\r\n document.prefabs.forEach((prefab, prefabIndex) => prefab.nodes.forEach((node, nodeIndex) => visitNode(node, `/prefabs/${prefabIndex}/nodes/${nodeIndex}`, { kind: \"prefab\", id: prefab.id })));\r\n}\r\n\r\nexport function collectTextKeyReferences(document: ProjectDocument): LocalizationKeyReference[] {\r\n const references: LocalizationKeyReference[] = [];\r\n forEachTextKeyReference(document, ({ key, path, owner, nodeId }) => references.push({ key, path, owner, nodeId }));\r\n return references;\r\n}\r\n\r\nexport type LocalizationLocaleCoverage = { id: string; label: string; isBase: boolean; translated: number; missingKeys: string[] };\r\nexport type LocalizationCoverage = {\r\n baseLocale: string;\r\n /** Все ключи каталога — покрытие считается по каталогу, а не по текущему usage. */\r\n keys: string[];\r\n keyCount: number;\r\n locales: LocalizationLocaleCoverage[];\r\n usedKeys: string[];\r\n unusedKeys: string[];\r\n /** Ключи, на которые ссылается `Text`, но которых нет в каталоге. */\r\n missingKeys: string[];\r\n};\r\n\r\n/** Детерминированное покрытие: и ключи, и локали, и списки отсортированы. */\r\nexport function computeLocalizationCoverage(document: ProjectDocument): LocalizationCoverage {\r\n const catalog = document.localization;\r\n const keys = Object.keys(catalog.entries).sort();\r\n const referenced = new Set(collectTextKeyReferences(document).map((reference) => reference.key.trim()).filter((key) => key !== \"\"));\r\n const usedKeys = keys.filter((key) => referenced.has(key));\r\n return {\r\n baseLocale: catalog.baseLocale,\r\n keys,\r\n keyCount: keys.length,\r\n locales: catalog.locales.map((locale) => {\r\n const missingKeys = keys.filter((key) => !Object.hasOwn(catalog.entries[key]!, locale.id));\r\n return { id: locale.id, label: locale.label, isBase: locale.id === catalog.baseLocale, translated: keys.length - missingKeys.length, missingKeys };\r\n }),\r\n usedKeys,\r\n unusedKeys: keys.filter((key) => !referenced.has(key)),\r\n missingKeys: [...referenced].filter((key) => !Object.hasOwn(catalog.entries, key)).sort(),\r\n };\r\n}\r\n\r\nconst issue = (code: string, path: string, message: string, severity: ValidationIssue[\"severity\"]): ValidationIssue => ({ code, path, message, severity });\r\n\r\n/**\r\n * Structural/semantic ошибки каталога: они делают документ невалидным.\r\n *\r\n * Здесь только то, что нельзя доставить ни при каком заполнении переводов: неканоничный или\r\n * дублирующийся locale ID, неизвестная base locale и пустая ссылка на ключ.\r\n */\r\nexport function collectLocalizationErrors(document: ProjectDocument): ValidationIssue[] {\r\n const issues: ValidationIssue[] = [];\r\n const catalog = document.localization;\r\n const seen = new Set<string>();\r\n catalog.locales.forEach((locale, index) => {\r\n const path = `/localization/locales/${index}/id`;\r\n if (!isCanonicalLocaleId(locale.id)) issues.push(issue(\"INVALID_LOCALE_ID\", path, `Locale '${locale.id}' is not a canonical BCP-47 identifier.`, \"error\"));\r\n if (seen.has(locale.id)) issues.push(issue(\"DUPLICATE_LOCALE\", path, `Locale '${locale.id}' is declared more than once.`, \"error\"));\r\n seen.add(locale.id);\r\n });\r\n if (!seen.has(catalog.baseLocale)) issues.push(issue(\"UNKNOWN_BASE_LOCALE\", \"/localization/baseLocale\", `Base locale '${catalog.baseLocale}' is not declared.`, \"error\"));\r\n for (const key of Object.keys(catalog.entries)) {\r\n if (key.trim() === \"\") issues.push(issue(\"EMPTY_LOCALIZATION_KEY\", `/localization/entries/${key}`, \"A localization key must not be blank.\", \"error\"));\r\n }\r\n for (const reference of collectTextKeyReferences(document)) {\r\n if (reference.key.trim() === \"\") issues.push(issue(\"EMPTY_LOCALIZATION_KEY\", reference.path, \"A textKey reference must not be blank.\", \"error\"));\r\n }\r\n return issues;\r\n}\r\n\r\n/**\r\n * Authoring diagnostics: каталог заполняется постепенно, поэтому всё это — warnings, и документ с\r\n * ними остаётся валидным и сохраняемым.\r\n */\r\nexport function collectLocalizationWarnings(document: ProjectDocument): ValidationIssue[] {\r\n const issues: ValidationIssue[] = [];\r\n const catalog = document.localization;\r\n const coverage = computeLocalizationCoverage(document);\r\n const declared = new Set(catalog.locales.map((locale) => locale.id));\r\n for (const reference of collectTextKeyReferences(document)) {\r\n const key = reference.key.trim();\r\n if (key !== \"\" && !Object.hasOwn(catalog.entries, key)) issues.push(issue(\"MISSING_LOCALIZATION_ENTRY\", reference.path, `Localization key '${key}' is not in the catalog.`, \"warning\"));\r\n }\r\n for (const key of coverage.keys) {\r\n const entry = catalog.entries[key]!;\r\n if (!Object.hasOwn(entry, catalog.baseLocale)) issues.push(issue(\"MISSING_BASE_TRANSLATION\", `/localization/entries/${key}`, `Key '${key}' has no '${catalog.baseLocale}' translation.`, \"warning\"));\r\n const baseParams = Object.hasOwn(entry, catalog.baseLocale) ? collectLocalizationParams(entry[catalog.baseLocale]!).join(\",\") : undefined;\r\n for (const localeId of Object.keys(entry).sort()) {\r\n if (!declared.has(localeId)) { issues.push(issue(\"UNKNOWN_TRANSLATION_LOCALE\", `/localization/entries/${key}/${localeId}`, `Locale '${localeId}' is not declared and will not be exported.`, \"warning\")); continue; }\r\n if (baseParams === undefined || localeId === catalog.baseLocale) continue;\r\n if (collectLocalizationParams(entry[localeId]!).join(\",\") !== baseParams) issues.push(issue(\"PARAM_MISMATCH\", `/localization/entries/${key}/${localeId}`, `Translation '${key}' for '${localeId}' uses different runtime parameters than the base locale.`, \"warning\"));\r\n }\r\n }\r\n for (const locale of coverage.locales) {\r\n if (locale.isBase || locale.missingKeys.length === 0) continue;\r\n issues.push(issue(\"INCOMPLETE_LOCALE\", `/localization/locales/${catalog.locales.findIndex((candidate) => candidate.id === locale.id)}`, `Locale '${locale.id}' is missing ${locale.missingKeys.length} translation(s).`, \"warning\"));\r\n }\r\n for (const key of coverage.unusedKeys) {\r\n issues.push(issue(\"UNUSED_LOCALIZATION_KEY\", `/localization/entries/${key}`, `Key '${key}' is not referenced by any delivered Text node.`, \"warning\"));\r\n }\r\n return issues;\r\n}\r\n\r\nexport function collectLocalizationIssues(document: ProjectDocument): ValidationIssue[] {\r\n return [...collectLocalizationErrors(document), ...collectLocalizationWarnings(document)];\r\n}\r\n\r\n/**\r\n * Строгая export-проверка: то же состояние, что в авторинге является warning, для пакета является\r\n * блокирующей ошибкой, если ключ каталога вообще нельзя доставить — у него нет base translation.\r\n * Неполные secondary locales и unused keys экспорт не блокируют и живут в coverage-отчёте.\r\n */\r\nexport function collectLocalizationExportErrors(document: ProjectDocument): ValidationIssue[] {\r\n const catalog = document.localization;\r\n const issues = collectLocalizationErrors(document);\r\n for (const key of Object.keys(catalog.entries).sort()) {\r\n if (!Object.hasOwn(catalog.entries[key]!, catalog.baseLocale)) issues.push(issue(\"MISSING_BASE_TRANSLATION\", `/localization/entries/${key}`, `Key '${key}' cannot be delivered: it has no '${catalog.baseLocale}' translation.`, \"error\"));\r\n }\r\n return issues;\r\n}\r\n\r\n/**\r\n * Словарь одной локали: плоский `Record<string, string>` без metadata wrapper, готовый любому\r\n * внешнему i18n. Ключ попадает в файл только если у него есть значение именно этой локали;\r\n * отсутствующий перевод не превращается в `\"\"`, а остаётся отмеченным в coverage.\r\n */\r\nexport function buildLocaleDictionary(catalog: LocalizationCatalog, localeId: string): Record<string, string> {\r\n const dictionary: Record<string, string> = {};\r\n for (const key of Object.keys(catalog.entries).sort()) {\r\n const entry = catalog.entries[key]!;\r\n if (Object.hasOwn(entry, localeId)) dictionary[key] = entry[localeId]!;\r\n }\r\n return dictionary;\r\n}\r\n\r\nexport function buildLocaleDictionaries(catalog: LocalizationCatalog): Record<string, Record<string, string>> {\r\n return Object.fromEntries(catalog.locales.map((locale) => [locale.id, buildLocaleDictionary(catalog, locale.id)]));\r\n}\r\n\r\nexport type LocalizationCoverageReport = LocalizationCoverage & { warnings: ValidationIssue[] };\r\n/** Отчёт покрытия пакета: он дополняет словари, а не заменяет их. */\r\nexport function buildLocalizationCoverageReport(document: ProjectDocument): LocalizationCoverageReport {\r\n return { ...computeLocalizationCoverage(document), warnings: collectLocalizationWarnings(document) };\r\n}\r\n\r\n/**\r\n * Localization-часть пакета: по одному плоскому словарю на каждую объявленную локаль плюс отчёт\r\n * покрытия. Каталог экспортируется целиком: unused-ключ может быть контрактом игрового кода, а\r\n * usage текущей иерархии не доказывает, что он не нужен.\r\n *\r\n * Раскладка описана здесь и только здесь: и ZIP-экспорт редактора, и фикстура демо обязаны звать\r\n * эту функцию, иначе демо проверяло бы не тот контракт. Документ ожидается уже подготовленным к\r\n * доставке (без `editorOnly` поддеревьев), потому что coverage говорит о доставляемых `Text`.\r\n */\r\nexport function collectPackageLocaleEntries(document: ProjectDocument): Record<string, string> {\r\n const entries: Record<string, string> = {};\r\n for (const locale of document.localization.locales) {\r\n entries[localeFilePath(locale.id)] = `${JSON.stringify(buildLocaleDictionary(document.localization, locale.id), null, 2)}\\n`;\r\n }\r\n entries[LOCALIZATION_COVERAGE_FILE] = `${JSON.stringify(buildLocalizationCoverageReport(document), null, 2)}\\n`;\r\n return entries;\r\n}\r\n\r\n/**\r\n * Блокировка экспорта каталогом. Сообщение формируется ровно здесь, чтобы UI показывал ту же\r\n * диагностику, что попадает в консоль, а не собственную формулировку.\r\n */\r\nexport class LocalizationExportError extends Error {\r\n readonly issues: ValidationIssue[];\r\n\r\n constructor(issues: ValidationIssue[]) {\r\n super(`The localization catalog cannot be packaged:\\n${issues.map((item) => `• ${item.message} (${item.code} at ${item.path})`).join(\"\\n\")}`);\r\n this.name = \"LocalizationExportError\";\r\n this.issues = issues;\r\n }\r\n}\r\n\r\n/**\r\n * Строгий pre-export gate. То, что в авторинге остаётся warning, здесь блокирует пакет, если ключ\r\n * невозможно доставить вообще: у него нет перевода базовой локали. Неполные secondary locales и\r\n * unused keys экспорт не останавливают и попадают только в `locales/coverage.json`.\r\n */\r\nexport function assertExportableLocalization(document: ProjectDocument): void {\r\n const errors = collectLocalizationExportErrors(document);\r\n if (errors.length > 0) throw new LocalizationExportError(errors);\r\n}\r\n"]}
1
+ {"version":3,"file":"localization.js","sourceRoot":"","sources":["../src/localization.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type, type Static } from \"@sinclair/typebox\";\r\nimport type { ProjectDocument, TextCase, UINode, ValidationIssue } from \"./index.js\";\r\nimport { materializedPrefabNodeId } from \"./prefabs.js\";\r\n\r\n/**\r\n * Единственная реализация локализации документа: контракт каталога, канонизация locale ID,\r\n * fallback-цепочка, интерполяция параметров, сбор ссылок `Text.textKey`, покрытие и диагностики.\r\n *\r\n * Runtime, экспорт, редактор и демо обязаны переиспользовать именно её: дублирование fallback- или\r\n * interpolation-логики в другом слое немедленно расходится по поведению.\r\n */\r\n\r\nconst LocaleIdSchema = Type.String({ minLength: 1 });\r\nexport const LocalizationLocaleSchema = Type.Object({ id: LocaleIdSchema, label: Type.String({ minLength: 1 }) });\r\nexport type LocalizationLocale = Static<typeof LocalizationLocaleSchema>;\r\n/**\r\n * `entries[key][localeId]` — плоская строка перевода. Отсутствующий перевод — это отсутствие\r\n * свойства локали, а не пустая строка: `\"\"` является валидным заполненным переводом и обрывает\r\n * fallback, поэтому резолвер нигде не проверяет значения через truthiness.\r\n */\r\nexport const LocalizationSchema = Type.Object({\r\n baseLocale: LocaleIdSchema,\r\n locales: Type.Array(LocalizationLocaleSchema),\r\n entries: Type.Record(Type.String({ minLength: 1 }), Type.Record(Type.String({ minLength: 1 }), Type.String())),\r\n});\r\nexport type LocalizationCatalog = Static<typeof LocalizationSchema>;\r\n\r\nexport const DEFAULT_LOCALE_ID = \"en\";\r\n/** Каталог, который получает документ v19 при миграции и любой новый проект. */\r\nexport function createDefaultLocalization(): LocalizationCatalog {\r\n return { baseLocale: DEFAULT_LOCALE_ID, locales: [{ id: DEFAULT_LOCALE_ID, label: \"English\" }], entries: {} };\r\n}\r\n\r\n/**\r\n * Каноническая BCP-47 форма: `en`, `en-US`, `pt-BR`, `zh-Hant`, `zh-Hant-TW`.\r\n *\r\n * Грамматика намеренно узкая — только буквы, три цифры региона и дефис. Поэтому канонический ID\r\n * автоматически является безопасным сегментом пути `locales/<locale>.json`: в нём не может быть\r\n * ни `/`, ни `\\`, ни `.`, ни `..`.\r\n */\r\nexport function canonicalizeLocaleId(input: string): string | undefined {\r\n const parts = input.trim().split(\"-\");\r\n const language = parts[0];\r\n if (language === undefined || !/^[A-Za-z]{2,3}$/.test(language)) return undefined;\r\n const segments = [language.toLowerCase()];\r\n let index = 1;\r\n const script = parts[index];\r\n if (script !== undefined && /^[A-Za-z]{4}$/.test(script)) { segments.push(`${script[0]!.toUpperCase()}${script.slice(1).toLowerCase()}`); index += 1; }\r\n const region = parts[index];\r\n if (region !== undefined) {\r\n if (/^[A-Za-z]{2}$/.test(region)) segments.push(region.toUpperCase());\r\n else if (/^[0-9]{3}$/.test(region)) segments.push(region);\r\n else return undefined;\r\n index += 1;\r\n }\r\n return index === parts.length ? segments.join(\"-\") : undefined;\r\n}\r\n\r\nexport function isCanonicalLocaleId(id: string): boolean { return canonicalizeLocaleId(id) === id; }\r\n\r\n/**\r\n * Справочник популярных локалей для UI выбора языка: готовый ID в канонической форме плюс\r\n * английский display label. Он живёт рядом с `canonicalizeLocaleId`, потому что это часть\r\n * локализационной модели, а не украшение панели: каждая запись обязана удовлетворять\r\n * `canonicalizeLocaleId(id) === id`, иначе выбор из списка создал бы невалидный документ.\r\n *\r\n * Список намеренно неполон — он покрывает частые случаи и снимает ручной ввод, а редкая локаль\r\n * по-прежнему добавляется вводом канонического BCP-47 идентификатора вручную.\r\n */\r\nexport const COMMON_LOCALES: readonly { id: string; label: string }[] = [\r\n { id: \"en\", label: \"English\" },\r\n { id: \"en-US\", label: \"English (United States)\" },\r\n { id: \"en-GB\", label: \"English (United Kingdom)\" },\r\n { id: \"ru\", label: \"Russian\" },\r\n { id: \"ru-RU\", label: \"Russian (Russia)\" },\r\n { id: \"uk\", label: \"Ukrainian\" },\r\n { id: \"de\", label: \"German\" },\r\n { id: \"fr\", label: \"French\" },\r\n { id: \"fr-CA\", label: \"French (Canada)\" },\r\n { id: \"es\", label: \"Spanish\" },\r\n { id: \"es-ES\", label: \"Spanish (Spain)\" },\r\n { id: \"es-419\", label: \"Spanish (Latin America)\" },\r\n { id: \"pt-BR\", label: \"Portuguese (Brazil)\" },\r\n { id: \"pt-PT\", label: \"Portuguese (Portugal)\" },\r\n { id: \"it\", label: \"Italian\" },\r\n { id: \"pl\", label: \"Polish\" },\r\n { id: \"tr\", label: \"Turkish\" },\r\n { id: \"nl\", label: \"Dutch\" },\r\n { id: \"sv\", label: \"Swedish\" },\r\n { id: \"da\", label: \"Danish\" },\r\n { id: \"nb\", label: \"Norwegian Bokmal\" },\r\n { id: \"fi\", label: \"Finnish\" },\r\n { id: \"cs\", label: \"Czech\" },\r\n { id: \"sk\", label: \"Slovak\" },\r\n { id: \"hu\", label: \"Hungarian\" },\r\n { id: \"ro\", label: \"Romanian\" },\r\n { id: \"bg\", label: \"Bulgarian\" },\r\n { id: \"el\", label: \"Greek\" },\r\n { id: \"sr\", label: \"Serbian\" },\r\n { id: \"hr\", label: \"Croatian\" },\r\n { id: \"ar\", label: \"Arabic\" },\r\n { id: \"he\", label: \"Hebrew\" },\r\n { id: \"fa\", label: \"Persian\" },\r\n { id: \"hi\", label: \"Hindi\" },\r\n { id: \"th\", label: \"Thai\" },\r\n { id: \"vi\", label: \"Vietnamese\" },\r\n { id: \"id\", label: \"Indonesian\" },\r\n { id: \"ms\", label: \"Malay\" },\r\n { id: \"tl\", label: \"Filipino\" },\r\n { id: \"ja\", label: \"Japanese\" },\r\n { id: \"ko\", label: \"Korean\" },\r\n { id: \"zh-Hans\", label: \"Chinese (Simplified)\" },\r\n { id: \"zh-Hant\", label: \"Chinese (Traditional)\" },\r\n];\r\n\r\n/**\r\n * Порядок локалей для любого UI: base locale первой, остальные сохраняют порядок объявления.\r\n * Правило одно на весь редактор, поэтому и живёт оно здесь, а не копией в каждой панели.\r\n */\r\nexport function orderLocalesForDisplay(catalog: LocalizationCatalog): LocalizationLocale[] {\r\n return [\r\n ...catalog.locales.filter((locale) => locale.id === catalog.baseLocale),\r\n ...catalog.locales.filter((locale) => locale.id !== catalog.baseLocale),\r\n ];\r\n}\r\n\r\nexport const LOCALIZATION_DIRECTORY = \"locales\";\r\nexport const LOCALIZATION_COVERAGE_FILE = `${LOCALIZATION_DIRECTORY}/coverage.json`;\r\n/** Путь словаря внутри пакета. Безопасность сегмента гарантирует канонический ID. */\r\nexport function localeFilePath(localeId: string): string { return `${LOCALIZATION_DIRECTORY}/${localeId}.json`; }\r\n\r\nexport type LocalizationParams = Readonly<Record<string, string | number>>;\r\nconst PARAM_PATTERN = /\\{([A-Za-z0-9_.-]+)\\}/g;\r\n\r\n/** Имена runtime-параметров `{name}` внутри значения перевода, детерминированно отсортированные. */\r\nexport function collectLocalizationParams(value: string): string[] {\r\n return [...new Set([...value.matchAll(PARAM_PATTERN)].map((match) => match[1]!))].sort();\r\n}\r\n\r\n/** Неизвестный параметр остаётся видимым в фигурных скобках — это признак незаполненного значения. */\r\nexport function interpolateLocalizedText(value: string, params?: LocalizationParams): string {\r\n if (params === undefined) return value;\r\n return value.replace(PARAM_PATTERN, (match, name: string) => (Object.hasOwn(params, name) ? String(params[name]) : match));\r\n}\r\n\r\nexport type LocalizationTranslateContext = { key: string; locale: string; baseLocale: string; params?: LocalizationParams };\r\n/** Внешний переводчик потребителя. `undefined` означает «нет мнения» и не обрывает fallback. */\r\nexport type TranslateFn = (key: string, context: LocalizationTranslateContext) => string | undefined;\r\n\r\nexport type ResolveLocalizedTextInput = {\r\n /** Авторская строка `Text.text`: ручной режим и последний содержательный fallback. */\r\n text: string;\r\n textKey?: string;\r\n catalog?: LocalizationCatalog;\r\n locale?: string;\r\n translate?: TranslateFn;\r\n params?: LocalizationParams;\r\n};\r\n\r\n/** Откуда взялась итоговая строка. `literal` — у ноды нет ключа и локализация не участвовала вообще. */\r\nexport type LocalizedTextSource = \"literal\" | \"translate\" | \"locale\" | \"baseLocale\" | \"text\" | \"key\";\r\nexport type LocalizedTextResolution = { value: string; source: LocalizedTextSource };\r\n\r\n/**\r\n * Единственная fallback-цепочка: внешний `translate` → выбранная локаль → базовая локаль →\r\n * `Text.text` → сам ключ. Нода без `textKey` не обращается к локализации вообще, поэтому документ\r\n * без ключей выглядит ровно как до появления каталога.\r\n *\r\n * Возвращает и значение, и источник: редактору нужно показать, почему на макете именно эта строка,\r\n * и он обязан читать это из той же реализации, а не выводить цепочку заново.\r\n */\r\nexport function describeLocalizedText(input: ResolveLocalizedTextInput): LocalizedTextResolution {\r\n const key = input.textKey?.trim();\r\n if (key === undefined || key === \"\") return { value: input.text, source: \"literal\" };\r\n const baseLocale = input.catalog?.baseLocale ?? DEFAULT_LOCALE_ID;\r\n const locale = input.locale ?? baseLocale;\r\n const entry = input.catalog?.entries[key];\r\n const external = input.translate?.(key, { key, locale, baseLocale, params: input.params });\r\n const resolution: LocalizedTextResolution = external !== undefined\r\n ? { value: external, source: \"translate\" }\r\n : entry !== undefined && Object.hasOwn(entry, locale) ? { value: entry[locale]!, source: \"locale\" }\r\n : entry !== undefined && Object.hasOwn(entry, baseLocale) ? { value: entry[baseLocale]!, source: \"baseLocale\" }\r\n : input.text.length > 0 ? { value: input.text, source: \"text\" } : { value: key, source: \"key\" };\r\n return { value: interpolateLocalizedText(resolution.value, input.params), source: resolution.source };\r\n}\r\n\r\nexport function resolveLocalizedText(input: ResolveLocalizedTextInput): string {\r\n return describeLocalizedText(input).value;\r\n}\r\n\r\n/**\r\n * `Text.textCase` display transform: applied last, on top of whatever `describeLocalizedText`\r\n * resolved (authored string, live preview, or translation) — never written back into `text` or a\r\n * catalog entry, so the source string and the case choice stay independently editable. Omitted/`\"none\"`\r\n * is a no-op, keeping every existing document's rendered output unchanged.\r\n */\r\nexport function applyTextCase(text: string, textCase: TextCase | undefined): string {\r\n switch (textCase) {\r\n case \"uppercase\": return text.toUpperCase();\r\n case \"lowercase\": return text.toLowerCase();\r\n default: return text;\r\n }\r\n}\r\n\r\n/** Владелец иерархии, в которой найдена ссылка: сцена или определение пресета. */\r\nexport type LocalizationReferenceOwner = { kind: \"scene\"; id: string } | { kind: \"prefab\"; id: string };\r\nexport type LocalizationKeyReference = {\r\n key: string;\r\n path: string;\r\n owner: LocalizationReferenceOwner;\r\n /**\r\n * Адрес узла в терминах редактора: собственный id персистентного/локального узла либо\r\n * materialized-адрес `instanceId::prefab-node::nodePath` для property override.\r\n */\r\n nodeId: string;\r\n};\r\n/** Ссылка вместе с записью значения: одна и та же реализация обхода читает и переименовывает ключи. */\r\nexport type LocalizationKeyReferenceSite = LocalizationKeyReference & { setKey(next: string): void };\r\n\r\n/**\r\n * Все ссылки `Text.textKey` документа: сцены, определения пресетов, локально добавленные узлы любой\r\n * вложенности и persisted property overrides. Унаследованные узлы инстанса ключ не «размножают»:\r\n * их источником является узел определения, уже посчитанный обходом `document.prefabs`.\r\n *\r\n * Обход единственный: `collectTextKeyReferences` только собирает результат, а rename каталога\r\n * переписывает ключи через `setKey`, поэтому «где живут ссылки» описано ровно в одном месте.\r\n */\r\nexport function forEachTextKeyReference(document: ProjectDocument, visit: (site: LocalizationKeyReferenceSite) => void): void {\r\n const visitNode = (node: UINode, path: string, owner: LocalizationReferenceOwner): void => {\r\n if (node.type === \"text\" && node.textKey !== undefined) {\r\n visit({ key: node.textKey, path: `${path}/textKey`, owner, nodeId: node.id, setKey: (next) => { node.textKey = next; } });\r\n }\r\n if (node.type !== \"prefab-instance\") return;\r\n (node.propertyOverrides ?? []).forEach((override, index) => {\r\n const value = override.patch.textKey;\r\n if (typeof value !== \"string\") return;\r\n visit({\r\n key: value,\r\n path: `${path}/propertyOverrides/${index}/patch/textKey`,\r\n owner,\r\n nodeId: materializedPrefabNodeId(node.id, override.nodeId),\r\n setKey: (next) => { override.patch.textKey = next; },\r\n });\r\n });\r\n (node.locallyAddedNodes ?? []).forEach((local, index) => visitNode(local, `${path}/locallyAddedNodes/${index}`, owner));\r\n };\r\n document.scenes.forEach((scene, sceneIndex) => scene.nodes.forEach((node, nodeIndex) => visitNode(node, `/scenes/${sceneIndex}/nodes/${nodeIndex}`, { kind: \"scene\", id: scene.id })));\r\n document.prefabs.forEach((prefab, prefabIndex) => prefab.nodes.forEach((node, nodeIndex) => visitNode(node, `/prefabs/${prefabIndex}/nodes/${nodeIndex}`, { kind: \"prefab\", id: prefab.id })));\r\n}\r\n\r\nexport function collectTextKeyReferences(document: ProjectDocument): LocalizationKeyReference[] {\r\n const references: LocalizationKeyReference[] = [];\r\n forEachTextKeyReference(document, ({ key, path, owner, nodeId }) => references.push({ key, path, owner, nodeId }));\r\n return references;\r\n}\r\n\r\nexport type LocalizationLocaleCoverage = { id: string; label: string; isBase: boolean; translated: number; missingKeys: string[] };\r\nexport type LocalizationCoverage = {\r\n baseLocale: string;\r\n /** Все ключи каталога — покрытие считается по каталогу, а не по текущему usage. */\r\n keys: string[];\r\n keyCount: number;\r\n locales: LocalizationLocaleCoverage[];\r\n usedKeys: string[];\r\n unusedKeys: string[];\r\n /** Ключи, на которые ссылается `Text`, но которых нет в каталоге. */\r\n missingKeys: string[];\r\n};\r\n\r\n/** Детерминированное покрытие: и ключи, и локали, и списки отсортированы. */\r\nexport function computeLocalizationCoverage(document: ProjectDocument): LocalizationCoverage {\r\n const catalog = document.localization;\r\n const keys = Object.keys(catalog.entries).sort();\r\n const referenced = new Set(collectTextKeyReferences(document).map((reference) => reference.key.trim()).filter((key) => key !== \"\"));\r\n const usedKeys = keys.filter((key) => referenced.has(key));\r\n return {\r\n baseLocale: catalog.baseLocale,\r\n keys,\r\n keyCount: keys.length,\r\n locales: catalog.locales.map((locale) => {\r\n const missingKeys = keys.filter((key) => !Object.hasOwn(catalog.entries[key]!, locale.id));\r\n return { id: locale.id, label: locale.label, isBase: locale.id === catalog.baseLocale, translated: keys.length - missingKeys.length, missingKeys };\r\n }),\r\n usedKeys,\r\n unusedKeys: keys.filter((key) => !referenced.has(key)),\r\n missingKeys: [...referenced].filter((key) => !Object.hasOwn(catalog.entries, key)).sort(),\r\n };\r\n}\r\n\r\nconst issue = (code: string, path: string, message: string, severity: ValidationIssue[\"severity\"]): ValidationIssue => ({ code, path, message, severity });\r\n\r\n/**\r\n * Structural/semantic ошибки каталога: они делают документ невалидным.\r\n *\r\n * Здесь только то, что нельзя доставить ни при каком заполнении переводов: неканоничный или\r\n * дублирующийся locale ID, неизвестная base locale и пустая ссылка на ключ.\r\n */\r\nexport function collectLocalizationErrors(document: ProjectDocument): ValidationIssue[] {\r\n const issues: ValidationIssue[] = [];\r\n const catalog = document.localization;\r\n const seen = new Set<string>();\r\n catalog.locales.forEach((locale, index) => {\r\n const path = `/localization/locales/${index}/id`;\r\n if (!isCanonicalLocaleId(locale.id)) issues.push(issue(\"INVALID_LOCALE_ID\", path, `Locale '${locale.id}' is not a canonical BCP-47 identifier.`, \"error\"));\r\n if (seen.has(locale.id)) issues.push(issue(\"DUPLICATE_LOCALE\", path, `Locale '${locale.id}' is declared more than once.`, \"error\"));\r\n seen.add(locale.id);\r\n });\r\n if (!seen.has(catalog.baseLocale)) issues.push(issue(\"UNKNOWN_BASE_LOCALE\", \"/localization/baseLocale\", `Base locale '${catalog.baseLocale}' is not declared.`, \"error\"));\r\n for (const key of Object.keys(catalog.entries)) {\r\n if (key.trim() === \"\") issues.push(issue(\"EMPTY_LOCALIZATION_KEY\", `/localization/entries/${key}`, \"A localization key must not be blank.\", \"error\"));\r\n }\r\n for (const reference of collectTextKeyReferences(document)) {\r\n if (reference.key.trim() === \"\") issues.push(issue(\"EMPTY_LOCALIZATION_KEY\", reference.path, \"A textKey reference must not be blank.\", \"error\"));\r\n }\r\n return issues;\r\n}\r\n\r\n/**\r\n * Authoring diagnostics: каталог заполняется постепенно, поэтому всё это — warnings, и документ с\r\n * ними остаётся валидным и сохраняемым.\r\n */\r\nexport function collectLocalizationWarnings(document: ProjectDocument): ValidationIssue[] {\r\n const issues: ValidationIssue[] = [];\r\n const catalog = document.localization;\r\n const coverage = computeLocalizationCoverage(document);\r\n const declared = new Set(catalog.locales.map((locale) => locale.id));\r\n for (const reference of collectTextKeyReferences(document)) {\r\n const key = reference.key.trim();\r\n if (key !== \"\" && !Object.hasOwn(catalog.entries, key)) issues.push(issue(\"MISSING_LOCALIZATION_ENTRY\", reference.path, `Localization key '${key}' is not in the catalog.`, \"warning\"));\r\n }\r\n for (const key of coverage.keys) {\r\n const entry = catalog.entries[key]!;\r\n if (!Object.hasOwn(entry, catalog.baseLocale)) issues.push(issue(\"MISSING_BASE_TRANSLATION\", `/localization/entries/${key}`, `Key '${key}' has no '${catalog.baseLocale}' translation.`, \"warning\"));\r\n const baseParams = Object.hasOwn(entry, catalog.baseLocale) ? collectLocalizationParams(entry[catalog.baseLocale]!).join(\",\") : undefined;\r\n for (const localeId of Object.keys(entry).sort()) {\r\n if (!declared.has(localeId)) { issues.push(issue(\"UNKNOWN_TRANSLATION_LOCALE\", `/localization/entries/${key}/${localeId}`, `Locale '${localeId}' is not declared and will not be exported.`, \"warning\")); continue; }\r\n if (baseParams === undefined || localeId === catalog.baseLocale) continue;\r\n if (collectLocalizationParams(entry[localeId]!).join(\",\") !== baseParams) issues.push(issue(\"PARAM_MISMATCH\", `/localization/entries/${key}/${localeId}`, `Translation '${key}' for '${localeId}' uses different runtime parameters than the base locale.`, \"warning\"));\r\n }\r\n }\r\n for (const locale of coverage.locales) {\r\n if (locale.isBase || locale.missingKeys.length === 0) continue;\r\n issues.push(issue(\"INCOMPLETE_LOCALE\", `/localization/locales/${catalog.locales.findIndex((candidate) => candidate.id === locale.id)}`, `Locale '${locale.id}' is missing ${locale.missingKeys.length} translation(s).`, \"warning\"));\r\n }\r\n for (const key of coverage.unusedKeys) {\r\n issues.push(issue(\"UNUSED_LOCALIZATION_KEY\", `/localization/entries/${key}`, `Key '${key}' is not referenced by any delivered Text node.`, \"warning\"));\r\n }\r\n return issues;\r\n}\r\n\r\nexport function collectLocalizationIssues(document: ProjectDocument): ValidationIssue[] {\r\n return [...collectLocalizationErrors(document), ...collectLocalizationWarnings(document)];\r\n}\r\n\r\n/**\r\n * Строгая export-проверка: то же состояние, что в авторинге является warning, для пакета является\r\n * блокирующей ошибкой, если ключ каталога вообще нельзя доставить — у него нет base translation.\r\n * Неполные secondary locales и unused keys экспорт не блокируют и живут в coverage-отчёте.\r\n */\r\nexport function collectLocalizationExportErrors(document: ProjectDocument): ValidationIssue[] {\r\n const catalog = document.localization;\r\n const issues = collectLocalizationErrors(document);\r\n for (const key of Object.keys(catalog.entries).sort()) {\r\n if (!Object.hasOwn(catalog.entries[key]!, catalog.baseLocale)) issues.push(issue(\"MISSING_BASE_TRANSLATION\", `/localization/entries/${key}`, `Key '${key}' cannot be delivered: it has no '${catalog.baseLocale}' translation.`, \"error\"));\r\n }\r\n return issues;\r\n}\r\n\r\n/**\r\n * Словарь одной локали: плоский `Record<string, string>` без metadata wrapper, готовый любому\r\n * внешнему i18n. Ключ попадает в файл только если у него есть значение именно этой локали;\r\n * отсутствующий перевод не превращается в `\"\"`, а остаётся отмеченным в coverage.\r\n */\r\nexport function buildLocaleDictionary(catalog: LocalizationCatalog, localeId: string): Record<string, string> {\r\n const dictionary: Record<string, string> = {};\r\n for (const key of Object.keys(catalog.entries).sort()) {\r\n const entry = catalog.entries[key]!;\r\n if (Object.hasOwn(entry, localeId)) dictionary[key] = entry[localeId]!;\r\n }\r\n return dictionary;\r\n}\r\n\r\nexport function buildLocaleDictionaries(catalog: LocalizationCatalog): Record<string, Record<string, string>> {\r\n return Object.fromEntries(catalog.locales.map((locale) => [locale.id, buildLocaleDictionary(catalog, locale.id)]));\r\n}\r\n\r\nexport type LocalizationCoverageReport = LocalizationCoverage & { warnings: ValidationIssue[] };\r\n/** Отчёт покрытия пакета: он дополняет словари, а не заменяет их. */\r\nexport function buildLocalizationCoverageReport(document: ProjectDocument): LocalizationCoverageReport {\r\n return { ...computeLocalizationCoverage(document), warnings: collectLocalizationWarnings(document) };\r\n}\r\n\r\n/**\r\n * Localization-часть пакета: по одному плоскому словарю на каждую объявленную локаль плюс отчёт\r\n * покрытия. Каталог экспортируется целиком: unused-ключ может быть контрактом игрового кода, а\r\n * usage текущей иерархии не доказывает, что он не нужен.\r\n *\r\n * Раскладка описана здесь и только здесь: и ZIP-экспорт редактора, и фикстура демо обязаны звать\r\n * эту функцию, иначе демо проверяло бы не тот контракт. Документ ожидается уже подготовленным к\r\n * доставке (без `editorOnly` поддеревьев), потому что coverage говорит о доставляемых `Text`.\r\n */\r\nexport function collectPackageLocaleEntries(document: ProjectDocument): Record<string, string> {\r\n const entries: Record<string, string> = {};\r\n for (const locale of document.localization.locales) {\r\n entries[localeFilePath(locale.id)] = `${JSON.stringify(buildLocaleDictionary(document.localization, locale.id), null, 2)}\\n`;\r\n }\r\n entries[LOCALIZATION_COVERAGE_FILE] = `${JSON.stringify(buildLocalizationCoverageReport(document), null, 2)}\\n`;\r\n return entries;\r\n}\r\n\r\n/**\r\n * Блокировка экспорта каталогом. Сообщение формируется ровно здесь, чтобы UI показывал ту же\r\n * диагностику, что попадает в консоль, а не собственную формулировку.\r\n */\r\nexport class LocalizationExportError extends Error {\r\n readonly issues: ValidationIssue[];\r\n\r\n constructor(issues: ValidationIssue[]) {\r\n super(`The localization catalog cannot be packaged:\\n${issues.map((item) => `• ${item.message} (${item.code} at ${item.path})`).join(\"\\n\")}`);\r\n this.name = \"LocalizationExportError\";\r\n this.issues = issues;\r\n }\r\n}\r\n\r\n/**\r\n * Строгий pre-export gate. То, что в авторинге остаётся warning, здесь блокирует пакет, если ключ\r\n * невозможно доставить вообще: у него нет перевода базовой локали. Неполные secondary locales и\r\n * unused keys экспорт не останавливают и попадают только в `locales/coverage.json`.\r\n */\r\nexport function assertExportableLocalization(document: ProjectDocument): void {\r\n const errors = collectLocalizationExportErrors(document);\r\n if (errors.length > 0) throw new LocalizationExportError(errors);\r\n}\r\n"]}
@@ -0,0 +1,18 @@
1
+ import type { PrefabInstanceNode } from "./prefabs.js";
2
+ import type { UINode } from "./index.js";
3
+ /** A reference can be rewritten, or removed when its target no longer belongs to the operation. */
4
+ export type NodeReferenceRewriter = (address: string) => string | undefined;
5
+ /**
6
+ * The sole inventory of semantic node-to-node reference fields.
7
+ *
8
+ * Structural hierarchy links (`parentId` and `children`) intentionally do not participate: their
9
+ * remapping has different ownership rules. Every operation which copies, deletes, materializes or
10
+ * unpacks semantic node references must call this helper instead of switching on node types itself.
11
+ */
12
+ export declare function rewriteNodeReferences(node: UINode, rewrite: NodeReferenceRewriter): void;
13
+ /**
14
+ * Applies the same inventory to sparse prefab patches. Patches are intentionally untyped records,
15
+ * so this is the only permitted place to inspect their reference-shaped fields.
16
+ */
17
+ export declare function rewritePrefabInstanceReferencePatches(instance: PrefabInstanceNode, rewrite: NodeReferenceRewriter): void;
18
+ //# sourceMappingURL=nodeReferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeReferences.d.ts","sourceRoot":"","sources":["../src/nodeReferences.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAkB,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzD,mGAAmG;AACnG,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAe5E;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAiCxF;AAED;;;GAGG;AACH,wBAAgB,qCAAqC,CAAC,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CA6BxH"}
@@ -0,0 +1,109 @@
1
+ function rewriteAddress(value, rewrite) {
2
+ return value === undefined ? undefined : rewrite(value);
3
+ }
4
+ function rewriteConnectorArray(value, rewrite) {
5
+ if (value === undefined)
6
+ return undefined;
7
+ const connectors = value.flatMap((connector) => {
8
+ const targetNodeId = rewrite(connector.targetNodeId);
9
+ return targetNodeId === undefined ? [] : [{ ...connector, targetNodeId }];
10
+ });
11
+ return connectors.length === 0 ? undefined : connectors;
12
+ }
13
+ /**
14
+ * The sole inventory of semantic node-to-node reference fields.
15
+ *
16
+ * Structural hierarchy links (`parentId` and `children`) intentionally do not participate: their
17
+ * remapping has different ownership rules. Every operation which copies, deletes, materializes or
18
+ * unpacks semantic node references must call this helper instead of switching on node types itself.
19
+ */
20
+ export function rewriteNodeReferences(node, rewrite) {
21
+ if (node.type === "spine") {
22
+ const connectors = rewriteConnectorArray(node.connectors, rewrite);
23
+ if (connectors === undefined)
24
+ delete node.connectors;
25
+ else
26
+ node.connectors = connectors;
27
+ return;
28
+ }
29
+ if (node.type === "pagination") {
30
+ const prevButtonNodeId = rewriteAddress(node.prevButtonNodeId, rewrite);
31
+ const nextButtonNodeId = rewriteAddress(node.nextButtonNodeId, rewrite);
32
+ if (prevButtonNodeId === undefined)
33
+ delete node.prevButtonNodeId;
34
+ else
35
+ node.prevButtonNodeId = prevButtonNodeId;
36
+ if (nextButtonNodeId === undefined)
37
+ delete node.nextButtonNodeId;
38
+ else
39
+ node.nextButtonNodeId = nextButtonNodeId;
40
+ return;
41
+ }
42
+ if (node.type === "page-group") {
43
+ const pageUpButtonNodeId = rewriteAddress(node.pageUpButtonNodeId, rewrite);
44
+ const pageDownButtonNodeId = rewriteAddress(node.pageDownButtonNodeId, rewrite);
45
+ if (pageUpButtonNodeId === undefined)
46
+ delete node.pageUpButtonNodeId;
47
+ else
48
+ node.pageUpButtonNodeId = pageUpButtonNodeId;
49
+ if (pageDownButtonNodeId === undefined)
50
+ delete node.pageDownButtonNodeId;
51
+ else
52
+ node.pageDownButtonNodeId = pageDownButtonNodeId;
53
+ return;
54
+ }
55
+ if (node.type === "item-table" && node.items !== undefined) {
56
+ const items = node.items.flatMap((itemId) => {
57
+ const mapped = rewrite(itemId);
58
+ return mapped === undefined ? [] : [mapped];
59
+ });
60
+ if (items.length === 0)
61
+ delete node.items;
62
+ else
63
+ node.items = items;
64
+ }
65
+ }
66
+ /**
67
+ * Applies the same inventory to sparse prefab patches. Patches are intentionally untyped records,
68
+ * so this is the only permitted place to inspect their reference-shaped fields.
69
+ */
70
+ export function rewritePrefabInstanceReferencePatches(instance, rewrite) {
71
+ for (const override of instance.propertyOverrides ?? []) {
72
+ const patch = override.patch;
73
+ if (Array.isArray(patch.connectors)) {
74
+ const connectors = patch.connectors.flatMap((value) => {
75
+ if (typeof value !== "object" || value === null)
76
+ return [];
77
+ const connector = value;
78
+ if ((connector.partType !== "bone" && connector.partType !== "slot") || typeof connector.partName !== "string" || typeof connector.targetNodeId !== "string")
79
+ return [];
80
+ const targetNodeId = rewrite(connector.targetNodeId);
81
+ return targetNodeId === undefined ? [] : [{ ...connector, targetNodeId }];
82
+ });
83
+ if (connectors.length === 0)
84
+ delete patch.connectors;
85
+ else
86
+ patch.connectors = connectors;
87
+ }
88
+ for (const field of ["prevButtonNodeId", "nextButtonNodeId", "pageUpButtonNodeId", "pageDownButtonNodeId"]) {
89
+ if (typeof patch[field] !== "string")
90
+ continue;
91
+ const mapped = rewrite(patch[field]);
92
+ if (mapped === undefined)
93
+ delete patch[field];
94
+ else
95
+ patch[field] = mapped;
96
+ }
97
+ if (Array.isArray(patch.items)) {
98
+ const items = patch.items.flatMap((item) => typeof item === "string" ? (() => {
99
+ const mapped = rewrite(item);
100
+ return mapped === undefined ? [] : [mapped];
101
+ })() : []);
102
+ if (items.length === 0)
103
+ delete patch.items;
104
+ else
105
+ patch.items = items;
106
+ }
107
+ }
108
+ }
109
+ //# sourceMappingURL=nodeReferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeReferences.js","sourceRoot":"","sources":["../src/nodeReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrefabInstanceNode } from \"./prefabs.js\";\nimport type { SpineConnector, UINode } from \"./index.js\";\n\n/** A reference can be rewritten, or removed when its target no longer belongs to the operation. */\nexport type NodeReferenceRewriter = (address: string) => string | undefined;\n\nfunction rewriteAddress(value: string | undefined, rewrite: NodeReferenceRewriter): string | undefined {\n return value === undefined ? undefined : rewrite(value);\n}\n\nfunction rewriteConnectorArray(value: SpineConnector[] | undefined, rewrite: NodeReferenceRewriter): SpineConnector[] | undefined {\n if (value === undefined) return undefined;\n const connectors = value.flatMap((connector) => {\n const targetNodeId = rewrite(connector.targetNodeId);\n return targetNodeId === undefined ? [] : [{ ...connector, targetNodeId }];\n });\n return connectors.length === 0 ? undefined : connectors;\n}\n\n/**\n * The sole inventory of semantic node-to-node reference fields.\n *\n * Structural hierarchy links (`parentId` and `children`) intentionally do not participate: their\n * remapping has different ownership rules. Every operation which copies, deletes, materializes or\n * unpacks semantic node references must call this helper instead of switching on node types itself.\n */\nexport function rewriteNodeReferences(node: UINode, rewrite: NodeReferenceRewriter): void {\n if (node.type === \"spine\") {\n const connectors = rewriteConnectorArray(node.connectors, rewrite);\n if (connectors === undefined) delete node.connectors;\n else node.connectors = connectors;\n return;\n }\n if (node.type === \"pagination\") {\n const prevButtonNodeId = rewriteAddress(node.prevButtonNodeId, rewrite);\n const nextButtonNodeId = rewriteAddress(node.nextButtonNodeId, rewrite);\n if (prevButtonNodeId === undefined) delete node.prevButtonNodeId;\n else node.prevButtonNodeId = prevButtonNodeId;\n if (nextButtonNodeId === undefined) delete node.nextButtonNodeId;\n else node.nextButtonNodeId = nextButtonNodeId;\n return;\n }\n if (node.type === \"page-group\") {\n const pageUpButtonNodeId = rewriteAddress(node.pageUpButtonNodeId, rewrite);\n const pageDownButtonNodeId = rewriteAddress(node.pageDownButtonNodeId, rewrite);\n if (pageUpButtonNodeId === undefined) delete node.pageUpButtonNodeId;\n else node.pageUpButtonNodeId = pageUpButtonNodeId;\n if (pageDownButtonNodeId === undefined) delete node.pageDownButtonNodeId;\n else node.pageDownButtonNodeId = pageDownButtonNodeId;\n return;\n }\n if (node.type === \"item-table\" && node.items !== undefined) {\n const items = node.items.flatMap((itemId) => {\n const mapped = rewrite(itemId);\n return mapped === undefined ? [] : [mapped];\n });\n if (items.length === 0) delete node.items;\n else node.items = items;\n }\n}\n\n/**\n * Applies the same inventory to sparse prefab patches. Patches are intentionally untyped records,\n * so this is the only permitted place to inspect their reference-shaped fields.\n */\nexport function rewritePrefabInstanceReferencePatches(instance: PrefabInstanceNode, rewrite: NodeReferenceRewriter): void {\n for (const override of instance.propertyOverrides ?? []) {\n const patch = override.patch as Record<string, unknown>;\n if (Array.isArray(patch.connectors)) {\n const connectors = patch.connectors.flatMap((value) => {\n if (typeof value !== \"object\" || value === null) return [];\n const connector = value as Partial<SpineConnector>;\n if ((connector.partType !== \"bone\" && connector.partType !== \"slot\") || typeof connector.partName !== \"string\" || typeof connector.targetNodeId !== \"string\") return [];\n const targetNodeId = rewrite(connector.targetNodeId);\n return targetNodeId === undefined ? [] : [{ ...connector, targetNodeId }];\n });\n if (connectors.length === 0) delete patch.connectors;\n else patch.connectors = connectors;\n }\n for (const field of [\"prevButtonNodeId\", \"nextButtonNodeId\", \"pageUpButtonNodeId\", \"pageDownButtonNodeId\"] as const) {\n if (typeof patch[field] !== \"string\") continue;\n const mapped = rewrite(patch[field]);\n if (mapped === undefined) delete patch[field];\n else patch[field] = mapped;\n }\n if (Array.isArray(patch.items)) {\n const items = patch.items.flatMap((item) => typeof item === \"string\" ? (() => {\n const mapped = rewrite(item);\n return mapped === undefined ? [] : [mapped];\n })() : []);\n if (items.length === 0) delete patch.items;\n else patch.items = items;\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"prefabs.d.ts","sourceRoot":"","sources":["../src/prefabs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefabs.d.ts","sourceRoot":"","sources":["../src/prefabs.ts"],"names":[],"mappings":"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"}
package/dist/prefabs.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { collectBindingKeys, collectBindingKeyScopes } from "./bindingKeys.js";
2
+ import { rewriteNodeReferences, rewritePrefabInstanceReferencePatches } from "./nodeReferences.js";
2
3
  const STRUCTURAL_OVERRIDE_KEYS = new Set(["id", "type", "parentId", "children", "editorOnly", "locked", "prefabId", "propertyOverrides", "locallyAddedNodes"]);
3
4
  /**
4
5
  * Разделитель сегментов адреса внутри инстанса пресета.
@@ -188,26 +189,21 @@ function materializeInstance(document, instance, expandingPrefabIds, applyInstan
188
189
  if (parent !== undefined && !parent.children.includes(node.id))
189
190
  parent.children.push(node.id);
190
191
  }
191
- // Connector references authored inside a reusable definition are relative to that definition.
192
- // Materialization gives their targets the same instance-scoped IDs as the hierarchy itself.
192
+ // Semantic references authored inside a reusable definition are relative to that definition.
193
+ // Materialization gives all their targets the same instance-scoped IDs as the hierarchy itself.
193
194
  const idByAddress = new Map();
194
195
  origins.forEach((origin, id) => {
195
196
  if (origin.kind === "inherited" && origin.instanceId === ownerId)
196
197
  idByAddress.set(origin.nodePath, id);
197
198
  });
198
199
  for (const node of nodes) {
199
- if (node.type !== "spine" || node.connectors === undefined)
200
- continue;
201
200
  const origin = origins.get(node.id);
202
201
  const ownPath = origin?.kind === "inherited" ? origin.nodePath : "";
203
202
  const ownSegments = ownPath === "" ? [] : splitNodePath(ownPath);
204
203
  const prefix = ownSegments.slice(0, -1).join(PREFAB_NODE_PATH_SEPARATOR);
205
- node.connectors = node.connectors.map((connector) => {
206
- if (nodesById.has(connector.targetNodeId))
207
- return connector;
208
- const relative = composePrefabNodePath(prefix, connector.targetNodeId);
209
- return { ...connector, targetNodeId: idByAddress.get(relative) ?? idByAddress.get(connector.targetNodeId) ?? connector.targetNodeId };
210
- });
204
+ rewriteNodeReferences(node, (targetNodeId) => nodesById.has(targetNodeId)
205
+ ? targetNodeId
206
+ : idByAddress.get(composePrefabNodePath(prefix, targetNodeId)) ?? idByAddress.get(targetNodeId) ?? targetNodeId);
211
207
  }
212
208
  return {
213
209
  rootNodeIds: [
@@ -482,9 +478,7 @@ function unpackInstance(document, location, createId) {
482
478
  node.id = remap(node.id);
483
479
  node.children = node.children.map(remap);
484
480
  node.parentId = node.parentId === null ? instance.id : remap(node.parentId);
485
- if (node.type === "spine" && node.connectors !== undefined) {
486
- node.connectors = node.connectors.map((connector) => ({ ...connector, targetNodeId: remap(connector.targetNodeId) }));
487
- }
481
+ rewriteNodeReferences(node, remap);
488
482
  }
489
483
  const { prefabId: _prefabId, propertyOverrides: _overrides, locallyAddedNodes: _locals, ...base } = instance;
490
484
  const container = { ...structuredClone(base), type: "container", children: draftPrefab.rootNodeIds.map(remap) };
@@ -509,23 +503,14 @@ function rewriteUnpackedAddresses(document, instanceId, idByAddress) {
509
503
  return [...segments.slice(0, index), mapped, ...segments.slice(index + 2)].join(PREFAB_NODE_PATH_SEPARATOR);
510
504
  };
511
505
  forEachPrefabInstance(document, (instance) => {
512
- for (const override of instance.propertyOverrides ?? []) {
506
+ for (const override of instance.propertyOverrides ?? [])
513
507
  override.nodeId = rewrite(override.nodeId);
514
- if (Array.isArray(override.patch.connectors)) {
515
- override.patch.connectors = override.patch.connectors.map((value) => {
516
- if (typeof value !== "object" || value === null || !("targetNodeId" in value) || typeof value.targetNodeId !== "string")
517
- return value;
518
- return { ...value, targetNodeId: rewrite(value.targetNodeId) };
519
- });
520
- }
521
- }
508
+ rewritePrefabInstanceReferencePatches(instance, rewrite);
522
509
  for (const local of instance.locallyAddedNodes ?? [])
523
510
  if (local.parentId !== null)
524
511
  local.parentId = rewrite(local.parentId);
525
- for (const local of instance.locallyAddedNodes ?? []) {
526
- if (local.type === "spine" && local.connectors !== undefined)
527
- local.connectors = local.connectors.map((connector) => ({ ...connector, targetNodeId: rewrite(connector.targetNodeId) }));
528
- }
512
+ for (const local of instance.locallyAddedNodes ?? [])
513
+ rewriteNodeReferences(local, rewrite);
529
514
  });
530
515
  }
531
516
  /**