jhm-ciberman/docs_gm

View on GitHub
src/gm_project/gms1/GMS1ProjectLoader.ts

Summary

Maintainability
A
0 mins
Test Coverage
import * as fse from "fs-extra";
import * as path from "path";
import * as xml2js from "xml2js";

import GMFolder from "../GMFolder";
import GMProject from "../GMProject";
import IGMProject from "../IGMProject";
import IGMProjectLoader from "../IGMProjectLoader";
import GMS1Script from "./GMS1Script";
import { IGMS1DescriptorFolder, IGMS1DescriptorRoot } from "./IGMS1Descriptor";

/**
 * Loads a GMS1 project file and creates a GMS1Project
 */
export default class GMS1ProjectLoader implements IGMProjectLoader {

    /**
     * Loads the specified GMS1 project
     * @param file The file path of the project to load
     * @returns A Promise with the GMS1Project
     */
    public async load(file: string): Promise<IGMProject> {
        file = path.normalize(file);
        const project = new GMProject(path.dirname(file));

        const str = await fse.readFile(file, "utf8");
        // "assets" is the root XML node of the document, but we call Root at the content of that node
        const data: IGMS1DescriptorRoot = await this._xmlParse(str);

        const assets = data.assets;
        // Creates the root folder
        if (assets.scripts) {
            const scriptsFolder = this._createFolder(assets.scripts[0]);
            project.addChild(scriptsFolder);
        }

        return project;
    }

    /**
     * Creates a folder and recursively builds all the
     * folder subtree. (only implemented for Scripts and Scripts folders)
     * @param root The root folder of the subtree
     * @param folderData The folder data
     */
    private _createFolder(folderData: IGMS1DescriptorFolder): GMFolder {
        const root = new GMFolder(folderData.$.name);
        for (const folder of folderData.scripts || []) {
            const resource = this._createFolder(folder); // Recursivity, baby! 8)
            root.addChild(resource);
        }

        for (const script of folderData.script || []) {
            const resource = new GMS1Script(script.replace(/\\/g, "/"));
            root.addChild(resource);
        }
        return root;
    }

    /**
     * Parses an XML string and returns the parsed data
     * @param string The XML string to parse
     * @return A promise with the data parsed
     */
    private _xmlParse(str: string): Promise<any> {
        return new Promise((accept) => {
            xml2js.parseString(str, (err, result) => {
                if (err) { throw err; }
                accept(result);
            });
        });
    }
}