@gulujs/toml
Version:
TOML parser and serializer
121 lines (120 loc) • 4.53 kB
JavaScript
import { ObjectPath, QuoteStyleKeyPath } from '@gulujs/object-path';
import { tryStringifyKeyValue } from './types/index.js';
import { SchemaType } from './schema.js';
import { DatetimeConverter, FloatConverter, IntegerConverter } from '../converter/index.js';
export class SimpleModeSerializer {
constructor(obj, options) {
this.obj = obj;
this.lines = [];
this.objectPath = new ObjectPath({
keyPath: new QuoteStyleKeyPath(options)
});
this.newline = options?.newline || '\n';
this.treatFunctionAsObject = options?.treatFunctionAsObject;
this.integerConverter = options?.integerConverter || new IntegerConverter();
this.floatConverter = options?.floatConverter || new FloatConverter();
this.datetimeConverter = options?.datetimeConverter || new DatetimeConverter();
this.options = {
simpleMode: true,
topLevel: true,
objectPath: this.objectPath,
newline: this.newline,
treatFunctionAsObject: this.treatFunctionAsObject,
preferQuote: options?.preferQuote || "'",
preferOneLineString: options?.preferOneLineString,
escapeTabChar: options?.escapeTabChar,
globalStringSplitter: options?.globalStringSplitter,
integerConverter: this.integerConverter,
floatConverter: this.floatConverter,
datetimeConverter: this.datetimeConverter
};
}
serialize() {
this.serializeInSimpleMode(this.obj, []);
return this.lines.join(this.newline);
}
serializeInSimpleMode(obj, path, isArrayOfTables = false) {
if (path.length > 0) {
if (this.lines.length > 0) {
this.lines.push('');
}
this.lines.push(`${isArrayOfTables ? '[[' : '['}${this.objectPath.keyPath.stringify(path)}${isArrayOfTables ? ']]' : ']'}`);
}
const numOfLines = this.lines.length;
const keys = Object.keys(obj);
const restKeys = [];
for (const key of keys) {
const value = obj[key];
const valuePath = [key];
const schema = {
type: SchemaType.Any,
key: valuePath
};
if (tryStringifyKeyValue(value, schema, this.options, [valuePath], this.lines)) {
continue;
}
if (Array.isArray(value) && !this.isArrayOfTables(value)) {
tryStringifyKeyValue(value, {
type: SchemaType.Array,
key: valuePath,
items: SchemaType.Any
}, this.options, [valuePath], this.lines);
continue;
}
restKeys.push(key);
}
if (numOfLines === this.lines.length && numOfLines > 0 && restKeys.length > 0 && !isArrayOfTables) {
this.lines.pop();
this.lines.pop();
}
for (const key of restKeys) {
const value = obj[key];
const valuePath = [...path, key];
if (!Array.isArray(value)) {
this.serializeInSimpleMode(value, valuePath);
continue;
}
for (let i = 0; i < value.length; i++) {
this.serializeInSimpleMode(value[i], valuePath, true);
}
}
}
isArrayOfTables(value) {
if (value.length === 0) {
return false;
}
for (let i = 0; i < value.length; i++) {
switch (typeof value[i]) {
case 'string':
case 'number':
case 'bigint':
case 'boolean':
case 'symbol':
case 'undefined':
return false;
case 'function':
if (this.treatFunctionAsObject) {
continue;
}
return false;
default:
}
if (this.integerConverter.isJsValue(value[i])) {
return false;
}
if (this.floatConverter.isJsValue(value[i])) {
return false;
}
if (value[i] === null) {
return false;
}
if (this.datetimeConverter.isJsValue(value[i])) {
return false;
}
if (Array.isArray(value[i])) {
return false;
}
}
return true;
}
}