json-to-table-format
Version:
A module for converting JSON data into a tabular format.
206 lines (175 loc) • 6.81 kB
text/typescript
import { WS, ES, FORMAT } from "./constant";
// Add new type for table style
export type TableStyle = 'simple' | 'ascii';
export function addSpaces(string: string, spaceCount: number): string {
for (let index = 0; index < spaceCount; index++) {
string += WS;
}
return string;
}
export function removeDoubleQuotes(value: string): string {
return value.replace(/"/g, ' ');
}
// Fixed ASCII border creation
function createAsciiBorder(startPoints: number[]): string {
const border = startPoints.map((point, index) => {
if (index === 0) return '-'.repeat(startPoints[1] - startPoints[0]);
if (index === startPoints.length - 1) return '';
return '-'.repeat(startPoints[index + 1] - startPoints[index]);
}).filter(Boolean).join('+');
return '+' + border + '+';
}
// Format complex values for better display
function formatComplexValue(value: any): string {
if (value === null || value === undefined) return 'null';
if (typeof value !== 'object') return String(value);
if (Array.isArray(value)) {
if (value.length === 0) return '[]';
return value.map(item => {
if (typeof item === 'object' && item !== null) {
return formatComplexValue(item);
}
return String(item);
}).join('\n');
}
const entries = Object.entries(value)
.map(([k, v]) => {
if (typeof v === 'object' && v !== null) {
return `${k}: ${formatComplexValue(v)}`;
}
return `${k}: ${v}`;
})
.join('\n');
return `{${entries}}`;
}
function wrapText(text: string, maxWidth: number): string[] {
if (!text || text.length <= maxWidth) return [text || ''];
// Split by newlines first to preserve array/object structure
const lines = text.split('\n');
const wrappedLines: string[] = [];
lines.forEach(line => {
if (line.length <= maxWidth) {
wrappedLines.push(line);
} else {
const words = line.split(' ');
let currentLine = '';
words.forEach(word => {
if ((currentLine + word).length <= maxWidth) {
currentLine += (currentLine ? ' ' : '') + word;
} else {
if (currentLine) wrappedLines.push(currentLine);
currentLine = word;
}
});
if (currentLine) wrappedLines.push(currentLine);
}
});
return wrappedLines;
}
export function getRow(headers: string[], startPoints: number[], isHeaderRow: boolean, obj?: any): string[] {
const maxWidth = 25;
const rows: string[] = [];
let maxLines = 1;
// First pass: calculate max lines needed
headers.forEach((header, index) => {
const value = isHeaderRow ? header : obj[header];
const formattedValue = typeof value === 'object' ? formatComplexValue(value) : String(value);
const wrappedLines = wrapText(formattedValue, maxWidth);
maxLines = Math.max(maxLines, wrappedLines.length);
});
// Generate all lines for the row
for (let lineIndex = 0; lineIndex < maxLines; lineIndex++) {
let row = ES;
headers.forEach((header, index) => {
const value = isHeaderRow ? header : obj[header];
const formattedValue = typeof value === 'object' ? formatComplexValue(value) : String(value);
const wrappedLines = wrapText(formattedValue, maxWidth);
const lineContent = wrappedLines[lineIndex] || '';
row += lineContent;
const spaceCount = startPoints[index + 1] - row.length;
row = addSpaces(row, spaceCount);
});
rows.push(row);
}
return rows;
}
export function getRows(data: any[], headers: string[], startPoints: number[], style: TableStyle = 'simple'): string[] {
let rows: string[] = [];
if (style === 'ascii') {
// Add top border
rows.push(createAsciiBorder(startPoints));
// Add header row with borders
const headerRows = getRow(headers, startPoints, true);
headerRows.forEach(row => {
rows.push('|' + row + '|');
});
// Add separator
rows.push(createAsciiBorder(startPoints));
// Add data rows with borders
data.forEach(obj => {
const dataRows = getRow(headers, startPoints, false, obj);
dataRows.forEach(row => {
rows.push('|' + row + '|');
});
});
// Add bottom border
rows.push(createAsciiBorder(startPoints));
} else {
// Original simple style
const headerRows = getRow(headers, startPoints, true);
rows.push(...headerRows);
data.forEach(obj => {
const dataRows = getRow(headers, startPoints, false, obj);
rows.push(...dataRows);
});
}
return rows;
}
export function getStartPoint(header: string, data: any[], startPoint: number): number {
let lengths = [header.length];
data.forEach(obj => {
if (obj[header] === null) {
lengths.push(4);
} else {
const value = obj[header];
const formattedValue = typeof value === 'object' ? formatComplexValue(value) : value;
lengths.push(String(formattedValue).length);
}
});
startPoint += Math.max(...lengths) + 5;
return startPoint;
}
export function getStartPoints(data: any[], headers: string[]): number[] {
let startPoints = [0];
let startPoint = 0;
headers.forEach(header => {
let lengths = [header.length];
data.forEach(obj => {
if (obj[header] === null) {
lengths.push(4);
} else {
const value = obj[header];
const formattedValue = typeof value === 'object' ? formatComplexValue(value) : String(value);
// Calculate width based on wrapped lines
const wrappedLines = wrapText(formattedValue, 25);
const maxLineLength = Math.max(...wrappedLines.map(line => line.length));
lengths.push(maxLineLength);
}
});
// Add padding for better readability
startPoint += Math.max(...lengths) + 4;
startPoints.push(startPoint);
});
return startPoints;
}
export function getData(params: any): any {
try {
if (!Array.isArray(params)) {
params = [params];
}
return params.map((param: any) => JSON.parse(JSON.stringify(param)));
} catch (error) {
console.error("Error parsing data:", error);
return null;
}
}