cli.js 7.36 KB
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
const _path = /*#__PURE__*/ _interopRequireDefault(require("path"));
const _arg = /*#__PURE__*/ _interopRequireDefault(require("arg"));
const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
const _build = require("./cli/build");
const _help = require("./cli/help");
const _init = require("./cli/init");
function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
function isESM() {
    const pkgPath = _path.default.resolve("./package.json");
    try {
        let pkg = JSON.parse(_fs.default.readFileSync(pkgPath, "utf8"));
        return pkg.type && pkg.type === "module";
    } catch (err) {
        return false;
    }
}
let configs = isESM() ? {
    tailwind: "tailwind.config.cjs",
    postcss: "postcss.config.cjs"
} : {
    tailwind: "tailwind.config.js",
    postcss: "postcss.config.js"
};
// ---
function oneOf(...options) {
    return Object.assign((value = true)=>{
        for (let option of options){
            let parsed = option(value);
            if (parsed === value) {
                return parsed;
            }
        }
        throw new Error("...");
    }, {
        manualParsing: true
    });
}
let commands = {
    init: {
        run: _init.init,
        args: {
            "--full": {
                type: Boolean,
                description: `Initialize a full \`${configs.tailwind}\` file`
            },
            "--postcss": {
                type: Boolean,
                description: `Initialize a \`${configs.postcss}\` file`
            },
            "-f": "--full",
            "-p": "--postcss"
        }
    },
    build: {
        run: _build.build,
        args: {
            "--input": {
                type: String,
                description: "Input file"
            },
            "--output": {
                type: String,
                description: "Output file"
            },
            "--watch": {
                type: Boolean,
                description: "Watch for changes and rebuild as needed"
            },
            "--poll": {
                type: Boolean,
                description: "Use polling instead of filesystem events when watching"
            },
            "--content": {
                type: String,
                description: "Content paths to use for removing unused classes"
            },
            "--purge": {
                type: String,
                deprecated: true
            },
            "--postcss": {
                type: oneOf(String, Boolean),
                description: "Load custom PostCSS configuration"
            },
            "--minify": {
                type: Boolean,
                description: "Minify the output"
            },
            "--config": {
                type: String,
                description: "Path to a custom config file"
            },
            "--no-autoprefixer": {
                type: Boolean,
                description: "Disable autoprefixer"
            },
            "-c": "--config",
            "-i": "--input",
            "-o": "--output",
            "-m": "--minify",
            "-w": "--watch",
            "-p": "--poll"
        }
    }
};
let sharedFlags = {
    "--help": {
        type: Boolean,
        description: "Display usage information"
    },
    "-h": "--help"
};
if (process.stdout.isTTY /* Detect redirecting output to a file */  && (process.argv[2] === undefined || process.argv.slice(2).every((flag)=>sharedFlags[flag] !== undefined))) {
    (0, _help.help)({
        usage: [
            "tailwindcss [--input input.css] [--output output.css] [--watch] [options...]",
            "tailwindcss init [--full] [--postcss] [options...]"
        ],
        commands: Object.keys(commands).filter((command)=>command !== "build").map((command)=>`${command} [options]`),
        options: {
            ...commands.build.args,
            ...sharedFlags
        }
    });
    process.exit(0);
}
let command = ((arg = "")=>arg.startsWith("-") ? undefined : arg)(process.argv[2]) || "build";
if (commands[command] === undefined) {
    if (_fs.default.existsSync(_path.default.resolve(command))) {
        // TODO: Deprecate this in future versions
        // Check if non-existing command, might be a file.
        command = "build";
    } else {
        (0, _help.help)({
            message: `Invalid command: ${command}`,
            usage: [
                "tailwindcss <command> [options]"
            ],
            commands: Object.keys(commands).filter((command)=>command !== "build").map((command)=>`${command} [options]`),
            options: sharedFlags
        });
        process.exit(1);
    }
}
// Execute command
let { args: flags , run  } = commands[command];
let args = (()=>{
    try {
        let result = (0, _arg.default)(Object.fromEntries(Object.entries({
            ...flags,
            ...sharedFlags
        }).filter(([_key, value])=>{
            var ref;
            return !(value === null || value === void 0 ? void 0 : (ref = value.type) === null || ref === void 0 ? void 0 : ref.manualParsing);
        }).map(([key, value])=>[
                key,
                typeof value === "object" ? value.type : value
            ])), {
            permissive: true
        });
        // Manual parsing of flags to allow for special flags like oneOf(Boolean, String)
        for(let i = result["_"].length - 1; i >= 0; --i){
            let flag = result["_"][i];
            if (!flag.startsWith("-")) continue;
            let flagName = flag;
            let handler = flags[flag];
            // Resolve flagName & handler
            while(typeof handler === "string"){
                flagName = handler;
                handler = flags[handler];
            }
            if (!handler) continue;
            let args = [];
            let offset = i + 1;
            // Parse args for current flag
            while(result["_"][offset] && !result["_"][offset].startsWith("-")){
                args.push(result["_"][offset++]);
            }
            // Cleanup manually parsed flags + args
            result["_"].splice(i, 1 + args.length);
            // Set the resolved value in the `result` object
            result[flagName] = handler.type(args.length === 0 ? undefined : args.length === 1 ? args[0] : args, flagName);
        }
        // Ensure that the `command` is always the first argument in the `args`.
        // This is important so that we don't have to check if a default command
        // (build) was used or not from within each plugin.
        //
        // E.g.: tailwindcss input.css -> _: ['build', 'input.css']
        // E.g.: tailwindcss build input.css -> _: ['build', 'input.css']
        if (result["_"][0] !== command) {
            result["_"].unshift(command);
        }
        return result;
    } catch (err) {
        if (err.code === "ARG_UNKNOWN_OPTION") {
            (0, _help.help)({
                message: err.message,
                usage: [
                    "tailwindcss <command> [options]"
                ],
                options: sharedFlags
            });
            process.exit(1);
        }
        throw err;
    }
})();
if (args["--help"]) {
    (0, _help.help)({
        options: {
            ...flags,
            ...sharedFlags
        },
        usage: [
            `tailwindcss ${command} [options]`
        ]
    });
    process.exit(0);
}
run(args, configs);