(portable: AppConfigPortable)
| 380 | * the map tables with format examples, so the file documents itself. |
| 381 | */ |
| 382 | export function serializeConfig(portable: AppConfigPortable): string { |
| 383 | const lines: string[] = [`config_version = ${CONFIG_VERSION}`] |
| 384 | const scalarKeys = Object.keys(SCALAR_FIELDS) as PortablePrefKey[] |
| 385 | |
| 386 | for (const section of SECTION_ORDER) { |
| 387 | const keys = scalarKeys.filter((key) => SCALAR_FIELDS[key]?.section === section) |
| 388 | if (keys.length === 0) continue |
| 389 | lines.push('', `[${section}]`) |
| 390 | for (const key of keys) { |
| 391 | const map = SCALAR_FIELDS[key] |
| 392 | if (!map) continue |
| 393 | let value = Object.prototype.hasOwnProperty.call(portable, key) |
| 394 | ? portable[key] |
| 395 | : PORTABLE_DEFAULTS[key] |
| 396 | if (value === undefined) value = PORTABLE_DEFAULTS[key] |
| 397 | // TOML has no null — nullable fields persist as "". |
| 398 | if (value === null) value = NULLABLE_FIELDS.has(key) ? '' : PORTABLE_DEFAULTS[key] |
| 399 | lines.push(`${map.tomlKey} = ${tomlValue(value)} # ${map.comment}`) |
| 400 | } |
| 401 | } |
| 402 | |
| 403 | lines.push(...keymapSectionLines(portable.keymapOverrides)) |
| 404 | |
| 405 | for (const key of Object.keys(MAP_TABLE_FIELDS) as PortablePrefKey[]) { |
| 406 | if (key === 'keymapOverrides') continue // emitted with its full reference above |
| 407 | const def = MAP_TABLE_FIELDS[key] |
| 408 | if (!def) continue |
| 409 | lines.push('') |
| 410 | for (const line of def.comment) lines.push(`# ${line}`) |
| 411 | lines.push(`# Example: ${def.example}`) |
| 412 | lines.push(`[${def.table}]`) |
| 413 | const value = portable[key] |
| 414 | if (value && typeof value === 'object' && !Array.isArray(value)) { |
| 415 | for (const [entryKey, entryValue] of Object.entries(value as Record<string, unknown>)) { |
| 416 | if (typeof entryValue === 'string') { |
| 417 | lines.push(`${tomlKey(entryKey)} = ${tomlValue(entryValue)}`) |
| 418 | } |
| 419 | } |
| 420 | } |
| 421 | } |
| 422 | |
| 423 | return FILE_HEADER + lines.join('\n') + '\n' |
| 424 | } |
| 425 | |
| 426 | /** Build the `[keymaps]` block: active overrides followed by every action's |
| 427 | * default binding as a commented, grouped reference so users can discover and |
no test coverage detected