UNPKG

nbtify

Version:

A library to read and write NBT files on the web!

105 lines 4.7 kB
import { NBTData } from "./format.js"; import { TAG, isTag, getTagType } from "./tag.js"; export function stringify(data, { space = "" } = {}) { if (data instanceof NBTData) { data = data.data; } if (typeof data !== "object" || data === null) { data; throw new TypeError("First parameter must be an object or array"); } if (typeof space !== "string" && typeof space !== "number") { space; throw new TypeError("Space option must be a string or number"); } space = typeof space === "number" ? " ".repeat(space) : space; const level = 1; return stringifyRoot(data, space, level); } function stringifyRoot(value, space, level) { const type = getTagType(value); if (type !== TAG.LIST && type !== TAG.COMPOUND) { throw new TypeError("Encountered unexpected Root tag type, must be either a List or Compound tag"); } return stringifyTag(value, space, level); } function stringifyTag(value, space, level) { const type = getTagType(value); switch (type) { case TAG.BYTE: return stringifyByte(value); case TAG.SHORT: return stringifyShort(value); case TAG.INT: return stringifyInt(value); case TAG.LONG: return stringifyLong(value); case TAG.FLOAT: return stringifyFloat(value); case TAG.DOUBLE: return stringifyDouble(value); case TAG.BYTE_ARRAY: return stringifyByteArray(value); case TAG.STRING: return stringifyString(value); case TAG.LIST: return stringifyList(value, space, level); case TAG.COMPOUND: return stringifyCompound(value, space, level); case TAG.INT_ARRAY: return stringifyIntArray(value); case TAG.LONG_ARRAY: return stringifyLongArray(value); default: throw new Error(`Encountered unsupported tag type '${type}'`); } } function stringifyByte(value) { return (typeof value === "boolean") ? `${value}` : `${value.valueOf()}b`; } function stringifyShort(value) { return `${value.valueOf()}s`; } function stringifyInt(value) { return `${value.valueOf()}`; } function stringifyLong(value) { return `${value}l`; } function stringifyFloat(value) { return `${value.valueOf()}${Number.isInteger(value.valueOf()) ? ".0" : ""}f`; } function stringifyDouble(value) { return `${value}${!Number.isInteger(value) || value.toExponential() === value.toString() ? "" : ".0"}d`; } function stringifyByteArray(value) { return `[B;${[...value].map(entry => stringifyByte(entry)).join()}]`; } function stringifyString(value) { const singleQuoteString = escapeString(value.replace(/['\\]/g, character => `\\${character}`)); const doubleQuoteString = escapeString(value.replace(/["\\]/g, character => `\\${character}`)); return (singleQuoteString.length < doubleQuoteString.length) ? `'${singleQuoteString}'` : `"${doubleQuoteString}"`; } function escapeString(value) { return value .replaceAll("\0", "\\0") .replaceAll("\b", "\\b") .replaceAll("\f", "\\f") .replaceAll("\n", "\\n") .replaceAll("\r", "\\r") .replaceAll("\t", "\\t"); } function stringifyList(value, space, level) { value = value.filter(isTag); const fancy = (space !== ""); const type = (value[0] !== undefined) ? getTagType(value[0]) : TAG.END; const isIndentedList = fancy && new Set([TAG.BYTE_ARRAY, TAG.LIST, TAG.COMPOUND, TAG.INT_ARRAY, TAG.LONG_ARRAY]).has(type); return `[${value.map(entry => `${isIndentedList ? `\n${space.repeat(level)}` : ""}${(() => { if (getTagType(entry) !== type) { throw new TypeError("Encountered unexpected item type in array, all tags in a List tag must be of the same type"); } const result = stringifyTag(entry, space, level + 1); return result; })()}`).join(`,${fancy && !isIndentedList ? " " : ""}`)}${isIndentedList ? `\n${space.repeat(level - 1)}` : ""}]`; } function stringifyCompound(value, space, level) { const fancy = (space !== ""); return `{${Object.entries(value).filter((entry) => isTag(entry[1])).map(([key, value]) => `${fancy ? `\n${space.repeat(level)}` : ""}${/^[0-9a-z_\-.+]+$/i.test(key) ? key : stringifyString(key)}:${fancy ? " " : ""}${(() => { const result = stringifyTag(value, space, level + 1); return result; })()}`).join(",")}${fancy && Object.keys(value).length !== 0 ? `\n${space.repeat(level - 1)}` : ""}}`; } function stringifyIntArray(value) { return `[I;${[...value].map(entry => stringifyInt(entry)).join()}]`; } function stringifyLongArray(value) { return `[L;${[...value].map(entry => stringifyLong(entry)).join()}]`; } //# sourceMappingURL=stringify.js.map