All files / bin args.ts

94.74% Statements 36/38
94.44% Branches 17/18
100% Functions 7/7
94.12% Lines 32/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158                                                                                  2x   9x           9x 2x     7x 7x     9x                 2x   30x   11x 6x                             2x   20x     20x 28x   4x 4x   8x 7x 7x   7x 6x 6x   8x 7x 7x         1x                     2x 30x 53x   42x 42x                                                          
/**
 * Stores CLI options.
 * Only contains the raw data, no validation is applied.
 */
export interface CliArgs {
    /**
     * Value of the --outpath parameter
     */
    outPath?: string;
 
    /**
     * Value of the --inpath parameter
     */
    inPath?: string;
 
    /**
     * If true, then --help was set
     */
    isHelp?: boolean;
 
    /**
     * Value of --formatter parameter
     */
    formatter?: string;
 
    /**
     * List of all non-option parameters identified
     */
    pages: string[];
 
    /**
     * If true, then --watch was set
     */
    watch?: boolean;
}
 
/**
 * Parse an array of string CLI arguments into a CliArgs structure.
 * @param args Array of string arguments to parse
 * @returns a CliArgs structure containing the parsed arguments
 */
export function parseArgs(args: string[]): CliArgs {
    // create parsing data object
    const parseData: CliArgs = {
        pages: [],
        formatter: 'pretty'
    };
 
    // print help if no args specified
    if (args.length === 0) {
        parseData.isHelp = true;
    } else {
        // parse args
        parsePages(args, parseData);
        parseOptions(args, parseData);
    }
 
    return parseData;
}
 
/**
 * Extracts all page paths from a list of CLI arguments.
 * A page path is any "non-option" argument - aka any argument that does not start with "--"
 * @param args Array of args to parse
 * @param parseData CliArgs to receive parsed pages
 */
export function parsePages(args: string[], parseData: CliArgs): void {
    // get page args
    const pages = args.filter(arg => !arg.startsWith('--'));
 
    if (pages.length > 0) {
        parseData.pages = pages;
    }
}
 
/**
 * Parses known options from an array of arguments.
 * Basic validation is performed:
 * 1. If an argument requires a value but none is provided, then an exception will be thrown.
 * 2. If an argument is not recognised, then an exception will be thrown.
 *
 * @param args Array of args to parse
 * @param parseData CliArgs to receive parsed options
 * @throws if invalid arguments are encountered
 * @throws if unknown arguments are encountered
 */
export function parseOptions(args: string[], parseData: CliArgs): void {
    // get option args
    const options = extractOptions(args);
 
    // process each option
    for (const option of options) {
        switch (option.name) {
            case 'help':
                parseData.isHelp = true;
                break;
            case 'inpath':
                if (!option.value) throw new Error('inPath requires a value');
                parseData.inPath = option.value;
                break;
            case 'outpath':
                if (!option.value) throw new Error('outPath requires a value');
                parseData.outPath = option.value;
                break;
            case 'formatter':
                if (!option.value) throw new Error('formatter requires a value');
                parseData.formatter = option.value;
                break;
            case 'watch':
                parseData.watch = true;
                break;
            default:
                throw new Error(`Unknown option: ${ option.label }`);
        }
    }
}
 
/**
 * Extracts all known options from a list of CLI arguments.
 * An option is any argument that starts with "--".
 * @param args string arguments to parse
 * @returns Array of CLIOptions objects parsed from input
 */
export function extractOptions(args: string[]): CliOption[] {
    return args
        .filter(arg => arg.startsWith('--'))
        .map((arg): CliOption => {
            const parts = arg.split('=');
            return {
                label: parts[0],
                name: parts[0].substring(2).toLowerCase(),
                value: parts.length > 1 ? parts[1] : undefined
            };
        });
}
 
/**
 * Stores an option parsed from the CLI
 */
export interface CliOption {
    /**
     * Human-readable display label of the option.
     * This is the exact string that was identified as an option.
     */
    label: string;
 
    /**
     * Computer-processable name / ID of the option.
     * In most cases, this is the same as {@link label} but trimmed and set to lower case.
     */
    name: string;
 
    /**
     * Value of the option, if present.
     */
    value?: string;
}