mirror of
https://github.com/voson-wang/toon.git
synced 2026-01-29 15:24:10 +08:00
89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
/**
|
|
* Format converters for TOON benchmarks
|
|
*
|
|
* Converts data to different formats for comparison:
|
|
* - JSON
|
|
* - TOON
|
|
* - CSV
|
|
* - XML
|
|
* - YAML
|
|
*
|
|
* ## Semantic Equivalence
|
|
*
|
|
* All formatters attempt to preserve semantic equivalence with the source data,
|
|
* meaning the converted data should represent the same information. However,
|
|
* CSV has inherent limitations with nested structures (see `toCSV` docs).
|
|
*/
|
|
|
|
import { stringify as stringifyCSV } from 'csv-stringify/sync'
|
|
import { XMLBuilder } from 'fast-xml-parser'
|
|
import { stringify as stringifyYAML } from 'yaml'
|
|
import { encode as encodeToon } from '../../src/index'
|
|
|
|
/**
|
|
* Format converters registry
|
|
*
|
|
* Each formatter takes unknown data and returns a string representation
|
|
*/
|
|
export const formatters: Record<string, (data: unknown) => string> = {
|
|
json: data => JSON.stringify(data, undefined, 2),
|
|
toon: data => encodeToon(data),
|
|
csv: data => toCSV(data),
|
|
xml: data => toXML(data),
|
|
yaml: data => stringifyYAML(data),
|
|
}
|
|
|
|
/**
|
|
* Convert data to CSV format
|
|
*
|
|
* @remarks
|
|
* **Limitations**: CSV is designed for flat tabular data only. This formatter:
|
|
* - Only handles top-level objects with arrays of flat objects
|
|
* - Cannot properly represent deeply nested structures (nested arrays/objects within rows)
|
|
* - Loses nested structure information during conversion
|
|
* - May produce misleading results for datasets with complex nesting (e.g., e-commerce orders with nested items)
|
|
*
|
|
* For datasets with nested structures, CSV comparisons may not be fair or representative
|
|
* of how CSV would typically be used in practice.
|
|
*/
|
|
function toCSV(data: unknown): string {
|
|
const sections: string[] = []
|
|
|
|
// Handle top-level object with arrays
|
|
if (typeof data === 'object' && data !== null && !Array.isArray(data)) {
|
|
for (const [key, value] of Object.entries(data)) {
|
|
if (Array.isArray(value) && value.length > 0) {
|
|
sections.push(`# ${key}`)
|
|
sections.push(stringifyCSV(value, { header: true }))
|
|
}
|
|
}
|
|
return sections.join('\n').trim()
|
|
}
|
|
|
|
// Root-level array
|
|
if (Array.isArray(data) && data.length > 0) {
|
|
return stringifyCSV(data, { header: true }).trim()
|
|
}
|
|
|
|
return ''
|
|
}
|
|
|
|
/**
|
|
* Convert data to XML format
|
|
*
|
|
* @remarks
|
|
* Uses fast-xml-parser to generate well-formatted XML with:
|
|
* - 2-space indentation for readability
|
|
* - Empty nodes suppressed
|
|
* - Proper escaping of special characters
|
|
*/
|
|
function toXML(data: unknown): string {
|
|
const builder = new XMLBuilder({
|
|
format: true,
|
|
indentBy: ' ',
|
|
suppressEmptyNode: true,
|
|
})
|
|
|
|
return builder.build(data)
|
|
}
|