UNPKG

purify-objects

Version:

A powerful TypeScript library for cleaning objects by removing empty values, with support for YAML and CSV formats

135 lines (116 loc) 4.32 kB
import { YAMLNode, CSVOptions, AnyObject } from './types'; export function parseYAML(content: string): AnyObject { const lines = content.split('\n'); const root: AnyObject = {}; let currentNode: AnyObject = root; let stack: [AnyObject, number][] = [[root, -1]]; for (const line of lines) { if (!line.trim() || line.trim().startsWith('#')) continue; const indent = line.search(/\S/); const [key, ...valueParts] = line.trim().split(':'); let value = valueParts.join(':').trim(); while (stack.length > 1 && stack[stack.length - 1][1] >= indent) { stack.pop(); } currentNode = stack[stack.length - 1][0]; if (value) { if (value.startsWith('[') && value.endsWith(']')) { currentNode[key] = value.slice(1, -1).split(',').map(v => v.trim()); } else if (value.toLowerCase() === 'true') { currentNode[key] = true; } else if (value.toLowerCase() === 'false') { currentNode[key] = false; } else if (value === 'null') { currentNode[key] = null; } else if (!isNaN(Number(value))) { currentNode[key] = Number(value); } else { currentNode[key] = value.replace(/^["']|["']$/g, ''); } } else { currentNode[key] = {}; stack.push([currentNode[key] as AnyObject, indent]); } } return root; } export function parseCSV(content: string, options: CSVOptions): AnyObject[] { const lines = content.split('\n').filter(line => line.trim()); const delimiter = options.delimiter || ','; const result: AnyObject[] = []; const headers = options.headers ? lines[0].split(delimiter).map(header => header.trim()) : Array.from({ length: lines[0].split(delimiter).length }, (_, i) => `column${i + 1}`); const dataLines = options.headers ? lines.slice(1) : lines; for (const line of dataLines) { const values = line.split(delimiter).map(value => { value = value.trim(); if (value.startsWith('"') && value.endsWith('"')) { return value.slice(1, -1); } if (value === 'null') { return null; } if (value === '') { return value; } if (!isNaN(Number(value))) { return Number(value); } if (value.toLowerCase() === 'true') { return true; } if (value.toLowerCase() === 'false') { return false; } return value; }); const row: AnyObject = {}; headers.forEach((header, index) => { row[header] = values[index]; }); result.push(row); } return result; } export function stringifyYAML(obj: AnyObject, indent = 0): string { let result = ''; const spaces = ' '.repeat(indent); for (const [key, value] of Object.entries(obj)) { if (value === null || value === undefined) { result += `${spaces}${key}:\n`; } else if (value === '') { result += `${spaces}${key}: ""\n`; } else if (Array.isArray(value)) { result += `${spaces}${key}: [${value.join(', ')}]\n`; } else if (typeof value === 'object') { result += `${spaces}${key}:\n${stringifyYAML(value as AnyObject, indent + 2)}`; } else if (typeof value === 'string' && value.includes('\n')) { result += `${spaces}${key}: |\n${value.split('\n').map(line => `${spaces} ${line}`).join('\n')}\n`; } else { result += `${spaces}${key}: ${value}\n`; } } return result; } export function stringifyCSV(objects: AnyObject[], options: CSVOptions): string { const delimiter = options.delimiter || ','; const headers = options.headers ? Object.keys(objects[0]) : Array.from({ length: Object.keys(objects[0]).length }, (_, i) => `column${i + 1}`); let result = options.headers ? headers.join(delimiter) + '\n' : ''; for (const obj of objects) { const values = headers.map(header => { const value = obj[header]; if (value === null || value === undefined) { return ''; } if (typeof value === 'string' && (value.includes(delimiter) || value.includes('"'))) { return `"${value.replace(/"/g, '""')}"`; } return String(value); }); result += values.join(delimiter) + '\n'; } return result; }