| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- // reference:
- // http://zh.esotericsoftware.com/spine-atlas-format
- const { extname } = require('path');
- const { existsSync, createReadStream } = require('fs');
- const { createInterface } = require('readline');
- function isNumber(value) {
- return !isNaN(Number(value));
- }
- function isBoolean(value) {
- return /^(true)|(false)$/.test(value);
- }
- function formatValue(value) {
- const _value = String(value).trim();
- if (/^(undefined)|(null)|(NaN)$/.test(_value)) {
- return _value;
- }
- if (_value === '') {
- return null;
- }
- const list = _value.split(',').map(v => {
- v = v.trim();
- if (v === '') {
- return null;
- }
- if (isNumber(v)) {
- return Number(v);
- }
- if (isBoolean(v)) {
- return Boolean(v);
- }
- return v;
- });
- if (list.length === 1) {
- return list[0];
- }
- return list;
- }
- const imageExt = ['.png', '.jpg', '.jpeg', '.webp', '.gif'];
- const pageAttr = ['name', 'size', 'format', 'filter', 'repeat', 'pma'];
- class ParseAtlasFile {
- constructor() { }
- #json = {};
- #lockPage = false;
- #currentPage = '';
- #currentRegin = '';
- reset() {
- this.#json = {};
- this.#lockPage = false;
- this.#currentPage = '';
- this.#currentRegin = '';
- }
- #push(line) {
- const string = line.trim();
- const isEmptyLine = string.length === 0;
- const isPage = imageExt.includes(extname(line)); // the begin of page
- if (isEmptyLine) {
- // if is a empty line,we need create a new page.
- this.#lockPage = false;
- return;
- }
- if (isPage && !this.#lockPage) {
- this.#json[line] = {};
- this.#lockPage = true;
- this.#currentPage = line;
- this.#currentRegin = '';
- } else {
- const keyValue = line.split(':');
- const key = keyValue[0].trim();
- const value = formatValue(keyValue[1]);
- // Check if it's region
- const isRegion = keyValue.length === 1;
- if (isRegion) {
- this.#currentRegin = key;
- this.#json[this.#currentPage][this.#currentRegin] = {};
- } else {
- if (this.#currentRegin) {
- this.#json[this.#currentPage][this.#currentRegin][key] = value;
- } else {
- if (!pageAttr.includes(key)) {
- console.error(`${key} is not a valid attribute, Please check!`);
- }
- this.#json[this.#currentPage][key] = value;
- }
- }
- }
- }
- parse(atlasFile) {
- this.reset();
- return new Promise((resolve, reject) => {
- if (typeof atlasFile !== 'string') {
- reject(new Error('File path must be a string'));
- }
- if (extname(atlasFile) !== '.atlas') {
- reject(new Error('The file does not a .atlas'));
- }
- if (!existsSync(atlasFile)) {
- reject(new Error('The file does not exist'));
- }
- const readStream = createReadStream(atlasFile, {
- encoding: 'utf-8',
- });
- const readLineStream = createInterface({
- input: readStream,
- setEncoding: 'utf-8',
- });
- readLineStream.on('line', (line) => {
- this.#push(line);
- });
- readLineStream.on('close', (err) => {
- if (err) {
- reject(err);
- }
- resolve(this.#json);
- });
- });
- }
- }
- exports.ParseAtlasFile = ParseAtlasFile;
|