UNPKG

extwee

Version:

A story compiler tool using Twine-compatible formats

197 lines (157 loc) 6.49 kB
// Import functions we need. import { parseTwine2HTML, parseTwee, parseStoryFormat, parseTwine1HTML, compileTwine2HTML, compileTwine1HTML } from '../../index.js'; // Import fs. import { readFileSync, writeFileSync } from 'node:fs'; // Import Commander. import { Command, InvalidArgumentError } from 'commander'; // Import package.json. import Package from '../../package.json' with { type: 'json' }; // Import isFile function. import { isFile } from './isFile.js'; /** * Process command line arguments. * @function CommandLineProcessing * @description This function processes the command line arguments passed to the Extwee CLI. * @module CLI/commandLineProcessing * @param {Array} argv - The command line arguments passed to the CLI. */ export function CommandLineProcessing(argv) { // This is the main function for processing the command line arguments. // It uses the Commander library to parse the arguments and then calls the appropriate functions. // The function is called when the script is run from the command line. // Create a new Command. const program = new Command(); program .name('extwee') .description('CLI for Extwee') .option('-v, --version', 'Show version number', () => { // Show the version number. console.log(`Extwee v${Package.version}`); // Exit the process. process.exit(0); }) .option('-c, --compile', 'Compile input into output') .option('-d, --decompile', 'De-compile input into output') .option('--twine1', 'Enable Twine 1 processing') .option('--name <storyFormatName>', 'Name of the Twine 1 story format (needed for `code.js` inclusion)') .option('--codejs <codeJSFile>', 'Twine 1 code.js file for use with Twine 1 HTML', (value) => { // Does the input file exist? if (isFile(value) === false) { // We cannot do anything without valid input. throw new InvalidArgumentError(`Twine 1 code.js ${value} does not exist.`); } return value; }) .option('--engine <engineFile>', 'Twine 1 engine.js file for use with Twine 1 HTML', (value) => { // Does the input file exist? if (isFile(value) === false) { // We cannot do anything without valid input. throw new InvalidArgumentError(`Twine 1 engine.js ${value} does not exist.`); } return value; }) .option('--header <headerFile>', 'Twine 1 header.html file for use with Twine 1 HTML', (value) => { // Does the input file exist? if (isFile(value) === false) { // We cannot do anything without valid input. throw new InvalidArgumentError(`Twine 1 header.html ${value} does not exist.`); } return value; }) .option('-s <storyformat>, --storyformat <storyformat>', 'Path to story format file for Twine 2', (value) => { // Does the input file exist? if (isFile(value) === false) { // We cannot do anything without valid input. throw new InvalidArgumentError(`Story format ${value} does not exist.`); } return value; }) .option('-i <inputFile>, --input <inputFile>', 'Path to input file', (value) => { // Does the input file exist? if (isFile(value) === false) { // We cannot do anything without valid input. throw new InvalidArgumentError(`Input file ${value} does not exist.`); } return value; }) .option('-o <outputFile>, --output <outputFile>', 'Path to output file'); // Parse the passed arguments. program.parse(argv); // Create object of passed arguments parsed by Commander. const options = program.opts(); /* * Prepare some (soon to be) global variables. */ // Check if Twine 1 is enabled. const isTwine1Mode = (options.twine1 === true); // Check if Twine 2 is enabled. const isTwine2Mode = (isTwine1Mode === false); // Check if de-compile mode is enabled. const isDecompileMode = (options.decompile === true); // Check if compile mode is enabled. const isCompileMode = (options.compile === true); // De-compile Twine 2 HTML into Twee 3 branch. // If -d is passed, -i and -o are required. if (isTwine2Mode === true && isDecompileMode === true) { // Read the input HTML file. const inputHTML = readFileSync(options.i, 'utf-8'); // Parse the input HTML file into Story object. const storyObject = parseTwine2HTML(inputHTML); // Write the output file from Story as Twee 3. writeFileSync(options.o, storyObject.toTwee()); return; } // Compile Twee 3 into Twine 2 HTML branch. // If -c is passed, -i, -o, and -s are required. if (isTwine2Mode === true && isCompileMode === true) { // Read the input file. const inputTwee = readFileSync(options.i, 'utf-8'); // Parse the input file. const story = parseTwee(inputTwee); // Read the story format file. const inputStoryFormat = readFileSync(options.s, 'utf-8'); // Parse the story format file. const parsedStoryFormat = parseStoryFormat(inputStoryFormat); // Compile the story. const Twine2HTML = compileTwine2HTML(story, parsedStoryFormat); // Write the output file. writeFileSync(options.o, Twine2HTML); // Exit the process. return; } // Compile Twee 3 into Twine 1 HTML branch. // Twine 1 compilation is complicated, so we have to check for all the required options. // * options.engine (from Twine 1 itself) // * options.header (from Twine 1 story format) // * options.name (from Twine 1 story format) // * options.codejs (from Twine 1 story format) if (isTwine1Mode === true && isCompileMode === true) { // Read the input file. const inputTwee = readFileSync(options.i, 'utf-8'); // Parse the input file. const story = parseTwee(inputTwee); // Does the engine file exist? const Twine1HTML = compileTwine1HTML(story, options.engine, options.header, options.name, options.codejs); // Write the output file. writeFileSync(options.o, Twine1HTML); // Exit the process. return; } // De-compile Twine 1 HTML into Twee 3 branch. if (isTwine1Mode === true && isDecompileMode === true) { // Read the input HTML file. const inputHTML = readFileSync(options.i, 'utf-8'); // Parse the input HTML file into Story object. const storyObject = parseTwine1HTML(inputHTML); // Write the output file from Story as Twee 3. writeFileSync(options.o, storyObject.toTwee()); return; } }