web-utility
Version:
Web front-end toolkit based on TypeScript
89 lines (68 loc) • 2.2 kB
text/typescript
import { isUnsafeNumeric } from './data';
export function parseJSON(raw: string) {
function parseItem(value: any) {
if (typeof value === 'string' && /^\d+(-\d{1,2}){1,2}/.test(value)) {
const date = new Date(value);
if (!Number.isNaN(+date)) return date;
}
return value;
}
const value = parseItem(raw);
if (typeof value !== 'string' || isUnsafeNumeric(value)) return value;
try {
return JSON.parse(raw, (key, value) => parseItem(value));
} catch {
return raw;
}
}
export function toJSValue(raw: string) {
const parsed = parseJSON(raw);
if (typeof parsed !== 'string') return parsed;
const number = +parsed;
return Number.isNaN(number) || number + '' !== parsed ? parsed : number;
}
function readQuoteValue(raw: string) {
const quote = raw[0];
const index = raw.indexOf(quote, 1);
if (index < 0) throw SyntaxError(`A ${quote} is missing`);
return raw.slice(1, index);
}
export function parseTextTable<T = {}>(
raw: string,
header?: boolean,
separator = ','
) {
const data = raw
.trim()
.split(/[\r\n]+/)
.map(row => {
const list = [];
do {
let value: string;
if (row[0] === '"' || row[0] === "'") {
value = readQuoteValue(row);
row = row.slice(value.length + 3);
} else {
const index = row.indexOf(separator);
if (index > -1) {
value = row.slice(0, index);
row = row.slice(index + 1);
} else {
value = row;
row = '';
}
}
list.push(toJSValue(value.trim()));
} while (row);
return list;
});
return !header
? data
: data.slice(1).map(
row =>
row.reduce((object, item, index) => {
object[data[0][index]] = item;
return object;
}, {}) as T
);
}