mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 22:21:22 -07:00
148 lines
4.0 KiB
TypeScript
148 lines
4.0 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* Converts a camelCase string to a Space Case string.
|
|
* e.g., "camelCaseString" -> "Camel Case String"
|
|
*/
|
|
function camelToSpace(text: string): string {
|
|
const result = text.replace(/([A-Z])/g, ' $1');
|
|
return result.charAt(0).toUpperCase() + result.slice(1).trim();
|
|
}
|
|
|
|
/**
|
|
* Converts a JSON-compatible value into a readable Markdown representation.
|
|
*
|
|
* @param data The data to convert.
|
|
* @param indent The current indentation level (for internal recursion).
|
|
* @returns A Markdown string representing the data.
|
|
*/
|
|
export function jsonToMarkdown(data: unknown, indent = 0): string {
|
|
const spacing = ' '.repeat(indent);
|
|
|
|
if (data === null) {
|
|
return 'null';
|
|
}
|
|
|
|
if (data === undefined) {
|
|
return 'undefined';
|
|
}
|
|
|
|
if (Array.isArray(data)) {
|
|
if (data.length === 0) {
|
|
return '[]';
|
|
}
|
|
|
|
if (isArrayOfSimilarObjects(data)) {
|
|
return renderTable(data, indent);
|
|
}
|
|
|
|
return data
|
|
.map((item) => {
|
|
if (
|
|
typeof item === 'object' &&
|
|
item !== null &&
|
|
Object.keys(item).length > 0
|
|
) {
|
|
const rendered = jsonToMarkdown(item, indent + 1);
|
|
return `${spacing}-\n${rendered}`;
|
|
}
|
|
const rendered = jsonToMarkdown(item, indent + 1).trimStart();
|
|
return `${spacing}- ${rendered}`;
|
|
})
|
|
.join('\n');
|
|
}
|
|
|
|
if (typeof data === 'object') {
|
|
const entries = Object.entries(data);
|
|
if (entries.length === 0) {
|
|
return '{}';
|
|
}
|
|
|
|
return entries
|
|
.map(([key, value]) => {
|
|
const displayKey = camelToSpace(key);
|
|
if (
|
|
typeof value === 'object' &&
|
|
value !== null &&
|
|
Object.keys(value).length > 0
|
|
) {
|
|
const renderedValue = jsonToMarkdown(value, indent + 1);
|
|
return `${spacing}- **${displayKey}**:\n${renderedValue}`;
|
|
}
|
|
const renderedValue = jsonToMarkdown(value, indent + 1).trimStart();
|
|
return `${spacing}- **${displayKey}**: ${renderedValue}`;
|
|
})
|
|
.join('\n');
|
|
}
|
|
|
|
if (typeof data === 'string') {
|
|
return data
|
|
.split('\n')
|
|
.map((line, i) => (i === 0 ? line : spacing + line))
|
|
.join('\n');
|
|
}
|
|
|
|
return String(data);
|
|
}
|
|
|
|
/**
|
|
* Safely attempts to parse a string as JSON and convert it to Markdown.
|
|
* If parsing fails, returns the original string.
|
|
*
|
|
* @param text The text to potentially convert.
|
|
* @returns The Markdown representation or the original text.
|
|
*/
|
|
export function safeJsonToMarkdown(text: string): string {
|
|
try {
|
|
const parsed: unknown = JSON.parse(text);
|
|
return jsonToMarkdown(parsed);
|
|
} catch {
|
|
return text;
|
|
}
|
|
}
|
|
|
|
export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
}
|
|
|
|
function isArrayOfSimilarObjects(
|
|
data: unknown[],
|
|
): data is Array<Record<string, unknown>> {
|
|
if (data.length === 0) {
|
|
return false;
|
|
}
|
|
if (!data.every(isRecord)) return false;
|
|
const firstKeys = Object.keys(data[0]).sort().join(',');
|
|
return data.every((item) => Object.keys(item).sort().join(',') === firstKeys);
|
|
}
|
|
|
|
function renderTable(data: Array<Record<string, unknown>>, indent = 0): string {
|
|
const spacing = ' '.repeat(indent);
|
|
const keys = Object.keys(data[0]);
|
|
const displayKeys = keys.map(camelToSpace);
|
|
const header = `${spacing}| ${displayKeys.join(' | ')} |`;
|
|
const separator = `${spacing}| ${keys.map(() => '---').join(' | ')} |`;
|
|
const rows = data.map(
|
|
(item) =>
|
|
`${spacing}| ${keys
|
|
.map((key) => {
|
|
const val = item[key];
|
|
if (typeof val === 'object' && val !== null) {
|
|
return JSON.stringify(val)
|
|
.replace(/\\/g, '\\\\')
|
|
.replace(/\|/g, '\\|');
|
|
}
|
|
return String(val)
|
|
.replace(/\\/g, '\\\\')
|
|
.replace(/\|/g, '\\|')
|
|
.replace(/\n/g, ' ');
|
|
})
|
|
.join(' | ')} |`,
|
|
);
|
|
return [header, separator, ...rows].join('\n');
|
|
}
|