mirror of
https://github.com/voson-wang/toon.git
synced 2026-01-29 15:24:10 +08:00
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import type { DecodeOptions, Delimiter, EncodeOptions } from '../../toon/src'
|
|
import type { InputSource } from './types'
|
|
import * as fsp from 'node:fs/promises'
|
|
import * as path from 'node:path'
|
|
import process from 'node:process'
|
|
import { consola } from 'consola'
|
|
import { estimateTokenCount } from 'tokenx'
|
|
import { decode, encode } from '../../toon/src'
|
|
import { formatInputLabel, readInput } from './utils'
|
|
|
|
export async function encodeToToon(config: {
|
|
input: InputSource
|
|
output?: string
|
|
delimiter: Delimiter
|
|
indent: number
|
|
lengthMarker: NonNullable<EncodeOptions['lengthMarker']>
|
|
printStats: boolean
|
|
}): Promise<void> {
|
|
const jsonContent = await readInput(config.input)
|
|
|
|
let data: unknown
|
|
try {
|
|
data = JSON.parse(jsonContent)
|
|
}
|
|
catch (error) {
|
|
throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`)
|
|
}
|
|
|
|
const encodeOptions: EncodeOptions = {
|
|
delimiter: config.delimiter,
|
|
indent: config.indent,
|
|
lengthMarker: config.lengthMarker,
|
|
}
|
|
|
|
const toonOutput = encode(data, encodeOptions)
|
|
|
|
if (config.output) {
|
|
await fsp.writeFile(config.output, toonOutput, 'utf-8')
|
|
const relativeInputPath = formatInputLabel(config.input)
|
|
const relativeOutputPath = path.relative(process.cwd(), config.output)
|
|
consola.success(`Encoded \`${relativeInputPath}\` → \`${relativeOutputPath}\``)
|
|
}
|
|
else {
|
|
console.log(toonOutput)
|
|
}
|
|
|
|
if (config.printStats) {
|
|
const jsonTokens = estimateTokenCount(jsonContent)
|
|
const toonTokens = estimateTokenCount(toonOutput)
|
|
const diff = jsonTokens - toonTokens
|
|
const percent = ((diff / jsonTokens) * 100).toFixed(1)
|
|
|
|
console.log()
|
|
consola.info(`Token estimates: ~${jsonTokens} (JSON) → ~${toonTokens} (TOON)`)
|
|
consola.success(`Saved ~${diff} tokens (-${percent}%)`)
|
|
}
|
|
}
|
|
|
|
export async function decodeToJson(config: {
|
|
input: InputSource
|
|
output?: string
|
|
indent: number
|
|
strict: boolean
|
|
}): Promise<void> {
|
|
const toonContent = await readInput(config.input)
|
|
|
|
let data: unknown
|
|
try {
|
|
const decodeOptions: DecodeOptions = {
|
|
indent: config.indent,
|
|
strict: config.strict,
|
|
}
|
|
data = decode(toonContent, decodeOptions)
|
|
}
|
|
catch (error) {
|
|
throw new Error(`Failed to decode TOON: ${error instanceof Error ? error.message : String(error)}`)
|
|
}
|
|
|
|
const jsonOutput = JSON.stringify(data, undefined, config.indent)
|
|
|
|
if (config.output) {
|
|
await fsp.writeFile(config.output, jsonOutput, 'utf-8')
|
|
const relativeInputPath = formatInputLabel(config.input)
|
|
const relativeOutputPath = path.relative(process.cwd(), config.output)
|
|
consola.success(`Decoded \`${relativeInputPath}\` → \`${relativeOutputPath}\``)
|
|
}
|
|
else {
|
|
console.log(jsonOutput)
|
|
}
|
|
}
|