UNPKG

pollen-css

Version:

Utility-first CSS for the future

1,843 lines (1,670 loc) • 1.48 MB
#!/usr/bin/env node import require$$0 from 'node:events'; import require$$1 from 'node:child_process'; import require$$2 from 'node:path'; import require$$3 from 'node:fs'; import require$$4 from 'node:process'; import fs6, { realpathSync, statSync, promises } from 'fs'; import * as path9 from 'path'; import path9__default, { dirname } from 'path'; import require$$2$1 from 'os'; import { createRequire, builtinModules } from 'module'; import url, { fileURLToPath, pathToFileURL, URL as URL$1 } from 'url'; import process3 from 'process'; import tty from 'tty'; import fs$2 from 'fs/promises'; import assert2 from 'assert'; import v8 from 'v8'; import { format as format$1, inspect } from 'util'; const isObject$2 = value => typeof value === 'object' && value !== null; // Customized for this use-case const isObjectCustom = value => isObject$2(value) && !(value instanceof RegExp) && !(value instanceof Error) && !(value instanceof Date) && !(globalThis.Blob && value instanceof globalThis.Blob); const mapObjectSkip = Symbol('mapObjectSkip'); const _mapObject = (object, mapper, options, isSeen = new WeakMap()) => { options = { deep: false, target: {}, ...options, }; if (isSeen.has(object)) { return isSeen.get(object); } isSeen.set(object, options.target); const {target} = options; delete options.target; const mapArray = array => array.map(element => isObjectCustom(element) ? _mapObject(element, mapper, options, isSeen) : element); if (Array.isArray(object)) { return mapArray(object); } for (const [key, value] of Object.entries(object)) { const mapResult = mapper(key, value, object); if (mapResult === mapObjectSkip) { continue; } let [newKey, newValue, {shouldRecurse = true} = {}] = mapResult; // Drop `__proto__` keys. if (newKey === '__proto__') { continue; } if (options.deep && shouldRecurse && isObjectCustom(newValue)) { newValue = Array.isArray(newValue) ? mapArray(newValue) : _mapObject(newValue, mapper, options, isSeen); } target[newKey] = newValue; } return target; }; function mapObject(object, mapper, options) { if (!isObject$2(object)) { throw new TypeError(`Expected an object, got \`${object}\` (${typeof object})`); } if (Array.isArray(object)) { throw new TypeError('Expected an object, got an array'); } return _mapObject(object, mapper, options); } /** * Colors * For rapid visual prototyping */ var colors = { color: { black: "#000", white: "#fff", /* Grey */ "grey-50": "#f9fafb", "grey-100": "#f3f4f6", "grey-200": "#e5e7eb", "grey-300": "#d1d5db", "grey-400": "#9ca3af", "grey-500": "#6b7280", "grey-600": "#4b5563", "grey-700": "#374151", "grey-800": "#1f2937", "grey-900": "#111827", "grey-950": "#030712", grey: "var(--color-gray-500)", /* Slate */ "slate-50": "#f8fafc", "slate-100": "#f1f5f9", "slate-200": "#e2e8f0", "slate-300": "#cbd5e1", "slate-400": "#94a3b8", "slate-500": "#64748b", "slate-600": "#475569", "slate-700": "#334155", "slate-800": "#1e293b", "slate-900": "#0f172a", "slate-950": "#020617", slate: "var(--color-slate-500)", /* Zinc */ "zinc-50": "#fafafa", "zinc-100": "#f4f4f5", "zinc-200": "#e4e4e7", "zinc-300": "#d4d4d8", "zinc-400": "#a1a1aa", "zinc-500": "#71717a", "zinc-600": "#52525b", "zinc-700": "#3f3f46", "zinc-800": "#27272a", "zinc-900": "#18181b", "zinc-950": "#09090b", zinc: "var(--color-zinc-500)", /* Stone */ "stone-50": "#fafaf9", "stone-100": "#f5f5f4", "stone-200": "#e7e5e4", "stone-300": "#d6d3d1", "stone-400": "#a8a29e", "stone-500": "#78716c", "stone-600": "#57534e", "stone-700": "#44403c", "stone-800": "#292524", "stone-900": "#1c1917", "stone-950": "#0c0a09", stone: "var(--color-stone-500)", /* Red */ "red-50": "#fef2f2", "red-100": "#fee2e2", "red-200": "#fecaca", "red-300": "#fca5a5", "red-400": "#f87171", "red-500": "#ef4444", "red-600": "#dc2626", "red-700": "#b91c1c", "red-800": "#991b1b", "red-900": "#7f1d1d", "red-950": "#450a0a", red: "var(--color-red-500)", /* Orange */ "orange-50": "#fff7ed", "orange-100": "#ffedd5", "orange-200": "#fed7aa", "orange-300": "#fdba74", "orange-400": "#fb923c", "orange-500": "#f97316", "orange-600": "#ea580c", "orange-700": "#c2410c", "orange-800": "#9a3412", "orange-900": "#7c2d12", "orange-950": "#431407", orange: "var(--color-orange-500)", /* Amber */ "amber-50": "#fffbeb", "amber-100": "#fef3c7", "amber-200": "#fde68a", "amber-300": "#fcd34d", "amber-400": "#fbbf24", "amber-500": "#f59e0b", "amber-600": "#d97706", "amber-700": "#b45309", "amber-800": "#92400e", "amber-900": "#78350f", "amber-950": "#451a03", amber: "var(--color-amber-500)", /* Yellow */ "yellow-50": "#fefce8", "yellow-100": "#fef9c3", "yellow-200": "#fef08a", "yellow-300": "#fde047", "yellow-400": "#facc15", "yellow-500": "#eab308", "yellow-600": "#ca8a04", "yellow-700": "#a16207", "yellow-800": "#854d0e", "yellow-900": "#713f12", "yellow-950": "#422006", yellow: "var(--color-yellow-500)", /* Lime */ "lime-50": "#f7fee7", "lime-100": "#ecfccb", "lime-200": "#d9f99d", "lime-300": "#bef264", "lime-400": "#a3e635", "lime-500": "#84cc16", "lime-600": "#65a30d", "lime-700": "#4d7c0f", "lime-800": "#3f6212", "lime-900": "#365314", "lime-950": "#1a2e05", lime: "var(--color-lime-500)", /* Green */ "green-50": "#f0fdf4", "green-100": "#dcfce7", "green-200": "#bbf7d0", "green-300": "#86efac", "green-400": "#4ade80", "green-500": "#22c55e", "green-600": "#16a34a", "green-700": "#15803d", "green-800": "#166534", "green-900": "#14532d", "green-950": "#052e16", green: "var(--color-green-500)", /* Teal */ "teal-50": "#f0fdfa", "teal-100": "#ccfbf1", "teal-200": "#99f6e4", "teal-300": "#5eead4", "teal-400": "#2dd4bf", "teal-500": "#14b8a6", "teal-600": "#0d9488", "teal-700": "#0f766e", "teal-800": "#115e59", "teal-900": "#134e4a", "teal-950": "#042f2e", teal: "var(--color-teal-500)", /* Cyan */ "cyan-50": "#ecfeff", "cyan-100": "#cffafe", "cyan-200": "#a5f3fc", "cyan-300": "#67e8f9", "cyan-400": "#22d3ee", "cyan-500": "#06b6d4", "cyan-600": "#0891b2", "cyan-700": "#0e7490", "cyan-800": "#155e75", "cyan-900": "#164e63", "cyan-950": "#083344", cyan: "var(--color-cyan-500)", /* Sky */ "sky-50": "#f0f9ff", "sky-100": "#e0f2fe", "sky-200": "#bae6fd", "sky-300": "#7dd3fc", "sky-400": "#38bdf8", "sky-500": "#0ea5e9", "sky-600": "#0284c7", "sky-700": "#0369a1", "sky-800": "#075985", "sky-900": "#0c4a6e", "sky-950": "#082f49", sky: "var(--color-sky-500)", /* Blue */ "blue-50": "#eff6ff", "blue-100": "#dbeafe", "blue-200": "#bfdbfe", "blue-300": "#93c5fd", "blue-400": "#60a5fa", "blue-500": "#3b82f6", "blue-600": "#2563eb", "blue-700": "#1d4ed8", "blue-800": "#1e40af", "blue-900": "#1e3a8a", "blue-950": "#172554", blue: "var(--color-blue-500)", /* Indigo */ "indigo-50": "#eef2ff", "indigo-100": "#e0e7ff", "indigo-200": "#c7d2fe", "indigo-300": "#a5b4fc", "indigo-400": "#818cf8", "indigo-500": "#6366f1", "indigo-600": "#4f46e5", "indigo-700": "#4338ca", "indigo-800": "#3730a3", "indigo-900": "#312e81", "indigo-950": "#1e1b4b", indigo: "var(--color-indigo-500)", /* Violet */ "violet-50": "#f5f3ff", "violet-100": "#ede9fe", "violet-200": "#ddd6fe", "violet-300": "#c4b5fd", "violet-400": "#a78bfa", "violet-500": "#8b5cf6", "violet-600": "#7c3aed", "violet-700": "#6d28d9", "violet-800": "#5b21b6", "violet-900": "#4c1d95", "violet-950": "#2e1065", violet: "var(--color-violet-500)", /* Purple */ "purple-50": "#faf5ff", "purple-100": "#f3e8ff", "purple-200": "#e9d5ff", "purple-300": "#d8b4fe", "purple-400": "#c084fc", "purple-500": "#a855f7", "purple-600": "#9333ea", "purple-700": "#7e22ce", "purple-800": "#6b21a8", "purple-900": "#581c87", "purple-950": "#3b0764", purple: "var(--color-purple-500)", /* Fuchsia */ "fuchsia-50": "#fdf4ff", "fuchsia-100": "#fae8ff", "fuchsia-200": "#f5d0fe", "fuchsia-300": "#f0abfc", "fuchsia-400": "#e879f9", "fuchsia-500": "#d946ef", "fuchsia-600": "#c026d3", "fuchsia-700": "#a21caf", "fuchsia-800": "#86198f", "fuchsia-900": "#701a75", "fuchsia-950": "#4a044e", fuchsia: "var(--color-fuchsia-500)", /* Pink */ "pink-50": "#fdf2f8", "pink-100": "#fce7f3", "pink-200": "#fbcfe8", "pink-300": "#f9a8d4", "pink-400": "#f472b6", "pink-500": "#ec4899", "pink-600": "#db2777", "pink-700": "#be185d", "pink-800": "#9d174d", "pink-900": "#831843", "pink-950": "#500724", pink: "var(--color-pink-500)", /* Rose */ "rose-50": "#fff1f2", "rose-100": "#ffe4e6", "rose-200": "#fecdd3", "rose-300": "#fda4af", "rose-400": "#fb7185", "rose-500": "#f43f5e", "rose-600": "#e11d48", "rose-700": "#be123c", "rose-800": "#9f1239", "rose-900": "#881337", "rose-950": "#4c0519", rose: "var(--color-rose-500)", }, }; /** * Grid * Grid system helpers */ var grid = { grid: { /** * Page Grid * Applied to grid-template-columns */ "page-width": "var(--width-xl)", "page-gutter": "5vw", "page-main": "2 / 3", page: "minmax(var(--grid-page-gutter), 1fr) minmax(0, var(--grid-page-width)) minmax(var(--grid-page-gutter), 1fr)", /** * Template Shorthands * Applied to grid-template-[columns/rows] */ 2: "repeat(2, minmax(0, 1fr))", 3: "repeat(3, minmax(0, 1fr))", 4: "repeat(4, minmax(0, 1fr))", 5: "repeat(5, minmax(0, 1fr))", 6: "repeat(6, minmax(0, 1fr))", 7: "repeat(7, minmax(0, 1fr))", 8: "repeat(8, minmax(0, 1fr))", 9: "repeat(9, minmax(0, 1fr))", 10: "repeat(10, minmax(0, 1fr))", 11: "repeat(11, minmax(0, 1fr))", 12: "repeat(12, minmax(0, 1fr))", }, }; var layout = { /** * Size scale * Applied to sizing properties * Eg: margin, padding, width, height */ size: { px: "1px", 1: "4px", 2: "8px", 3: "12px", 4: "16px", 5: "20px", 6: "24px", 7: "28px", 8: "32px", 9: "36px", 10: "40px", 11: "44px", 12: "48px", 14: "56px", 16: "64px", 20: "80px", 24: "96px", 28: "112px", 32: "128px", 36: "144px", 40: "160px", 44: "176px", 48: "192px", 52: "208px", 56: "224px", 60: "240px", 64: "256px", 72: "288px", 80: "320px", 96: "384px", full: "100%", screen: "100vw", min: "min-content", max: "max-content", }, /** * Container widths * Applied as max-width */ width: { xs: "480px", sm: "640px", md: "768px", lg: "1024px", xl: "1280px", }, /** * Aspect ratios * Applied as aspect-ratio */ ratio: { square: "1/1", portrait: "3/4", landscape: "4/3", tall: "2/3", wide: "3/2", widescreen: "16/9", golden: "1.618/1", }, }; /** * Fluid size utility */ function fluid(minSize, maxSize, minWidth = 480, maxWidth = 1280) { const slope = (maxSize - minSize) / (maxWidth - minWidth); const yAxisIntersection = -minWidth * slope + minSize; return `clamp(${minSize / 16}rem, ${yAxisIntersection / 16}rem + ${slope * 100}vw, ${maxSize / 16}rem)`; } /** * Typography * For a foundation in type */ var typography = { /** * Modular scale * Applied as font-size */ scale: { "000": "0.75rem" /* 12px */, "00": "0.875rem" /* 14px */, "0": "1rem" /* 16px */, "1": "1.125rem" /* 18px */, "2": "1.25rem" /* 20px */, "3": "1.5rem" /* 24px */, "4": "1.875rem" /* 30px */, "5": "2.25rem" /* 36px */, "6": "3rem" /* 48px */, "7": "3.75rem" /* 60px */, "8": "4.5rem" /* 72px */, "9": "6rem" /* 96px */, "10": "8rem" /* 128px */, }, /** * Fluid type scale using generated clamp() * Applied as font-size */ "scale-fluid": { "000": fluid(10, 12), "00": fluid(12, 14), "0": fluid(14, 16), "1": fluid(16, 18), "2": fluid(18, 20), "3": fluid(20, 24), "4": fluid(24, 30), "5": fluid(30, 36), "6": fluid(36, 48), "7": fluid(48, 60), "8": fluid(60, 72), "9": fluid(72, 96), "10": fluid(96, 128), }, /** * Fonts * Applied as font-family and font-weight */ font: { sans: `ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"`, serif: `ui-serif, Georgia, Cambria, "Times New Roman", Times, serif`, mono: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace', }, weight: { light: "300", regular: "400", medium: "500", semibold: "600", bold: "700", extrabold: "800", black: "900", }, /** * Line Heights */ line: { none: 1, xs: 1.125, sm: 1.275, md: 1.5, lg: 1.625, xl: 2, }, /** * Letter spacing */ letter: { xs: "-0.05em", sm: "-0.025em", none: "0em", lg: "0.025em", xl: "0.05em", }, /** * Prose measure * Applied as max-width */ prose: { xs: "45ch", sm: "55ch", md: "65ch", lg: "75ch", xl: "85ch", }, }; /** * UI library * For consistency across UI and motion */ var ui = { /** * Radiuses * Applied as border-radius */ radius: { xs: "3px", sm: "6px", md: "8px", lg: "12px", xl: "16px", 100: "100%", full: "9999px", }, /** * Blurs * Applied as backdrop-filter */ blur: { xs: "blur(4px)", sm: "blur(8px)", md: "blur(16px)", lg: "blur(24px)", xl: "blur(40px)", }, /** * Layers * Applied as z-index */ layer: { below: -1, 1: 10, 2: 20, 3: 30, 4: 40, 5: 50, top: 2147483647, }, /** * Shadow * Applied as box-shadow */ shadow: { xs: "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)", sm: "0 4px 6px -2px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.06)", md: "0 12px 16px -4px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)", lg: "0 20px 24px -4px rgba(0, 0, 0, 0.1), 0 8px 8px -4px rgba(0, 0, 0, 0.04)", xl: "0 24px 48px -12px rgba(0, 0, 0, 0.25)", }, /** * Motion easing curves * Appplied in transitions and animations */ ease: { "in-sine": "cubic-bezier(0.47, 0, 0.745, 0.715)", "out-sine": "cubic-bezier(0.39, 0.575, 0.565, 1)", "in-out-sine": "cubic-bezier(0.445, 0.05, 0.55, 0.95)", "in-quad": "cubic-bezier(0.55, 0.085, 0.68, 0.53)", "out-quad": "cubic-bezier(0.25, 0.46, 0.45, 0.94)", "in-out-quad": "cubic-bezier(0.455, 0.03, 0.515, 0.955)", "in-cubic": "cubic-bezier(0.55, 0.055, 0.675, 0.19)", "out-cubic": "cubic-bezier(0.215, 0.61, 0.355, 1)", "in-out-cubic": "cubic-bezier(0.645, 0.045, 0.355, 1)", "in-quart": "cubic-bezier(0.895, 0.03, 0.685, 0.22)", "out-quart": "cubic-bezier(0.165, 0.84, 0.44, 1)", "in-out-quart": "cubic-bezier(0.77, 0, 0.175, 1)", "in-quint": "cubic-bezier(0.755, 0.05, 0.855, 0.06)", "out-quint": "cubic-bezier(0.23, 1, 0.32, 1)", "in-out-quint": "cubic-bezier(0.86, 0, 0.07, 1)", "in-expo": "cubic-bezier(0.95, 0.05, 0.795, 0.035)", "out-expo": "cubic-bezier(0.19, 1, 0.22, 1)", "in-out-expo": "cubic-bezier(1, 0, 0, 1)", "in-circ": "cubic-bezier(0.6, 0.04, 0.98, 0.335)", "out-circ": "cubic-bezier(0.075, 0.82, 0.165, 1)", "in-out-circ": "cubic-bezier(0.785, 0.135, 0.15, 0.86)", "in-back": "cubic-bezier(0.6, -0.28, 0.735, 0.045)", "out-back": "cubic-bezier(0.175, 0.885, 0.32, 1.275)", "in-out-back": "cubic-bezier(0.68, -0.55, 0.265, 1.55)", }, }; var modules = { ...typography, ...layout, ...ui, ...colors, ...grid, }; var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; var commander = {}; var argument = {}; var error = {}; /** * CommanderError class */ let CommanderError$3 = class CommanderError extends Error { /** * Constructs the CommanderError class * @param {number} exitCode suggested exit code which could be used with process.exit * @param {string} code an id string representing the error * @param {string} message human-readable description of the error */ constructor(exitCode, code, message) { super(message); // properly capture stack trace in Node.js Error.captureStackTrace(this, this.constructor); this.name = this.constructor.name; this.code = code; this.exitCode = exitCode; this.nestedError = undefined; } }; /** * InvalidArgumentError class */ let InvalidArgumentError$4 = class InvalidArgumentError extends CommanderError$3 { /** * Constructs the InvalidArgumentError class * @param {string} [message] explanation of why argument is invalid */ constructor(message) { super(1, 'commander.invalidArgument', message); // properly capture stack trace in Node.js Error.captureStackTrace(this, this.constructor); this.name = this.constructor.name; } }; error.CommanderError = CommanderError$3; error.InvalidArgumentError = InvalidArgumentError$4; const { InvalidArgumentError: InvalidArgumentError$3 } = error; let Argument$3 = class Argument { /** * Initialize a new command argument with the given name and description. * The default is that the argument is required, and you can explicitly * indicate this with <> around the name. Put [] around the name for an optional argument. * * @param {string} name * @param {string} [description] */ constructor(name, description) { this.description = description || ''; this.variadic = false; this.parseArg = undefined; this.defaultValue = undefined; this.defaultValueDescription = undefined; this.argChoices = undefined; switch (name[0]) { case '<': // e.g. <required> this.required = true; this._name = name.slice(1, -1); break; case '[': // e.g. [optional] this.required = false; this._name = name.slice(1, -1); break; default: this.required = true; this._name = name; break; } if (this._name.length > 3 && this._name.slice(-3) === '...') { this.variadic = true; this._name = this._name.slice(0, -3); } } /** * Return argument name. * * @return {string} */ name() { return this._name; } /** * @package */ _concatValue(value, previous) { if (previous === this.defaultValue || !Array.isArray(previous)) { return [value]; } return previous.concat(value); } /** * Set the default value, and optionally supply the description to be displayed in the help. * * @param {*} value * @param {string} [description] * @return {Argument} */ default(value, description) { this.defaultValue = value; this.defaultValueDescription = description; return this; } /** * Set the custom handler for processing CLI command arguments into argument values. * * @param {Function} [fn] * @return {Argument} */ argParser(fn) { this.parseArg = fn; return this; } /** * Only allow argument value to be one of choices. * * @param {string[]} values * @return {Argument} */ choices(values) { this.argChoices = values.slice(); this.parseArg = (arg, previous) => { if (!this.argChoices.includes(arg)) { throw new InvalidArgumentError$3( `Allowed choices are ${this.argChoices.join(', ')}.`, ); } if (this.variadic) { return this._concatValue(arg, previous); } return arg; }; return this; } /** * Make argument required. * * @returns {Argument} */ argRequired() { this.required = true; return this; } /** * Make argument optional. * * @returns {Argument} */ argOptional() { this.required = false; return this; } }; /** * Takes an argument and returns its human readable equivalent for help usage. * * @param {Argument} arg * @return {string} * @private */ function humanReadableArgName$2(arg) { const nameOutput = arg.name() + (arg.variadic === true ? '...' : ''); return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']'; } argument.Argument = Argument$3; argument.humanReadableArgName = humanReadableArgName$2; var command = {}; var help = {}; const { humanReadableArgName: humanReadableArgName$1 } = argument; /** * TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS` * https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#import-types * @typedef { import("./argument.js").Argument } Argument * @typedef { import("./command.js").Command } Command * @typedef { import("./option.js").Option } Option */ // Although this is a class, methods are static in style to allow override using subclass or just functions. let Help$3 = class Help { constructor() { this.helpWidth = undefined; this.sortSubcommands = false; this.sortOptions = false; this.showGlobalOptions = false; } /** * Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one. * * @param {Command} cmd * @returns {Command[]} */ visibleCommands(cmd) { const visibleCommands = cmd.commands.filter((cmd) => !cmd._hidden); const helpCommand = cmd._getHelpCommand(); if (helpCommand && !helpCommand._hidden) { visibleCommands.push(helpCommand); } if (this.sortSubcommands) { visibleCommands.sort((a, b) => { // @ts-ignore: because overloaded return type return a.name().localeCompare(b.name()); }); } return visibleCommands; } /** * Compare options for sort. * * @param {Option} a * @param {Option} b * @returns {number} */ compareOptions(a, b) { const getSortKey = (option) => { // WYSIWYG for order displayed in help. Short used for comparison if present. No special handling for negated. return option.short ? option.short.replace(/^-/, '') : option.long.replace(/^--/, ''); }; return getSortKey(a).localeCompare(getSortKey(b)); } /** * Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one. * * @param {Command} cmd * @returns {Option[]} */ visibleOptions(cmd) { const visibleOptions = cmd.options.filter((option) => !option.hidden); // Built-in help option. const helpOption = cmd._getHelpOption(); if (helpOption && !helpOption.hidden) { // Automatically hide conflicting flags. Bit dubious but a historical behaviour that is convenient for single-command programs. const removeShort = helpOption.short && cmd._findOption(helpOption.short); const removeLong = helpOption.long && cmd._findOption(helpOption.long); if (!removeShort && !removeLong) { visibleOptions.push(helpOption); // no changes needed } else if (helpOption.long && !removeLong) { visibleOptions.push( cmd.createOption(helpOption.long, helpOption.description), ); } else if (helpOption.short && !removeShort) { visibleOptions.push( cmd.createOption(helpOption.short, helpOption.description), ); } } if (this.sortOptions) { visibleOptions.sort(this.compareOptions); } return visibleOptions; } /** * Get an array of the visible global options. (Not including help.) * * @param {Command} cmd * @returns {Option[]} */ visibleGlobalOptions(cmd) { if (!this.showGlobalOptions) return []; const globalOptions = []; for ( let ancestorCmd = cmd.parent; ancestorCmd; ancestorCmd = ancestorCmd.parent ) { const visibleOptions = ancestorCmd.options.filter( (option) => !option.hidden, ); globalOptions.push(...visibleOptions); } if (this.sortOptions) { globalOptions.sort(this.compareOptions); } return globalOptions; } /** * Get an array of the arguments if any have a description. * * @param {Command} cmd * @returns {Argument[]} */ visibleArguments(cmd) { // Side effect! Apply the legacy descriptions before the arguments are displayed. if (cmd._argsDescription) { cmd.registeredArguments.forEach((argument) => { argument.description = argument.description || cmd._argsDescription[argument.name()] || ''; }); } // If there are any arguments with a description then return all the arguments. if (cmd.registeredArguments.find((argument) => argument.description)) { return cmd.registeredArguments; } return []; } /** * Get the command term to show in the list of subcommands. * * @param {Command} cmd * @returns {string} */ subcommandTerm(cmd) { // Legacy. Ignores custom usage string, and nested commands. const args = cmd.registeredArguments .map((arg) => humanReadableArgName$1(arg)) .join(' '); return ( cmd._name + (cmd._aliases[0] ? '|' + cmd._aliases[0] : '') + (cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option (args ? ' ' + args : '') ); } /** * Get the option term to show in the list of options. * * @param {Option} option * @returns {string} */ optionTerm(option) { return option.flags; } /** * Get the argument term to show in the list of arguments. * * @param {Argument} argument * @returns {string} */ argumentTerm(argument) { return argument.name(); } /** * Get the longest command term length. * * @param {Command} cmd * @param {Help} helper * @returns {number} */ longestSubcommandTermLength(cmd, helper) { return helper.visibleCommands(cmd).reduce((max, command) => { return Math.max(max, helper.subcommandTerm(command).length); }, 0); } /** * Get the longest option term length. * * @param {Command} cmd * @param {Help} helper * @returns {number} */ longestOptionTermLength(cmd, helper) { return helper.visibleOptions(cmd).reduce((max, option) => { return Math.max(max, helper.optionTerm(option).length); }, 0); } /** * Get the longest global option term length. * * @param {Command} cmd * @param {Help} helper * @returns {number} */ longestGlobalOptionTermLength(cmd, helper) { return helper.visibleGlobalOptions(cmd).reduce((max, option) => { return Math.max(max, helper.optionTerm(option).length); }, 0); } /** * Get the longest argument term length. * * @param {Command} cmd * @param {Help} helper * @returns {number} */ longestArgumentTermLength(cmd, helper) { return helper.visibleArguments(cmd).reduce((max, argument) => { return Math.max(max, helper.argumentTerm(argument).length); }, 0); } /** * Get the command usage to be displayed at the top of the built-in help. * * @param {Command} cmd * @returns {string} */ commandUsage(cmd) { // Usage let cmdName = cmd._name; if (cmd._aliases[0]) { cmdName = cmdName + '|' + cmd._aliases[0]; } let ancestorCmdNames = ''; for ( let ancestorCmd = cmd.parent; ancestorCmd; ancestorCmd = ancestorCmd.parent ) { ancestorCmdNames = ancestorCmd.name() + ' ' + ancestorCmdNames; } return ancestorCmdNames + cmdName + ' ' + cmd.usage(); } /** * Get the description for the command. * * @param {Command} cmd * @returns {string} */ commandDescription(cmd) { // @ts-ignore: because overloaded return type return cmd.description(); } /** * Get the subcommand summary to show in the list of subcommands. * (Fallback to description for backwards compatibility.) * * @param {Command} cmd * @returns {string} */ subcommandDescription(cmd) { // @ts-ignore: because overloaded return type return cmd.summary() || cmd.description(); } /** * Get the option description to show in the list of options. * * @param {Option} option * @return {string} */ optionDescription(option) { const extraInfo = []; if (option.argChoices) { extraInfo.push( // use stringify to match the display of the default value `choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`, ); } if (option.defaultValue !== undefined) { // default for boolean and negated more for programmer than end user, // but show true/false for boolean option as may be for hand-rolled env or config processing. const showDefault = option.required || option.optional || (option.isBoolean() && typeof option.defaultValue === 'boolean'); if (showDefault) { extraInfo.push( `default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`, ); } } // preset for boolean and negated are more for programmer than end user if (option.presetArg !== undefined && option.optional) { extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`); } if (option.envVar !== undefined) { extraInfo.push(`env: ${option.envVar}`); } if (extraInfo.length > 0) { return `${option.description} (${extraInfo.join(', ')})`; } return option.description; } /** * Get the argument description to show in the list of arguments. * * @param {Argument} argument * @return {string} */ argumentDescription(argument) { const extraInfo = []; if (argument.argChoices) { extraInfo.push( // use stringify to match the display of the default value `choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`, ); } if (argument.defaultValue !== undefined) { extraInfo.push( `default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`, ); } if (extraInfo.length > 0) { const extraDescripton = `(${extraInfo.join(', ')})`; if (argument.description) { return `${argument.description} ${extraDescripton}`; } return extraDescripton; } return argument.description; } /** * Generate the built-in help text. * * @param {Command} cmd * @param {Help} helper * @returns {string} */ formatHelp(cmd, helper) { const termWidth = helper.padWidth(cmd, helper); const helpWidth = helper.helpWidth || 80; const itemIndentWidth = 2; const itemSeparatorWidth = 2; // between term and description function formatItem(term, description) { if (description) { const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`; return helper.wrap( fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth, ); } return term; } function formatList(textArray) { return textArray.join('\n').replace(/^/gm, ' '.repeat(itemIndentWidth)); } // Usage let output = [`Usage: ${helper.commandUsage(cmd)}`, '']; // Description const commandDescription = helper.commandDescription(cmd); if (commandDescription.length > 0) { output = output.concat([ helper.wrap(commandDescription, helpWidth, 0), '', ]); } // Arguments const argumentList = helper.visibleArguments(cmd).map((argument) => { return formatItem( helper.argumentTerm(argument), helper.argumentDescription(argument), ); }); if (argumentList.length > 0) { output = output.concat(['Arguments:', formatList(argumentList), '']); } // Options const optionList = helper.visibleOptions(cmd).map((option) => { return formatItem( helper.optionTerm(option), helper.optionDescription(option), ); }); if (optionList.length > 0) { output = output.concat(['Options:', formatList(optionList), '']); } if (this.showGlobalOptions) { const globalOptionList = helper .visibleGlobalOptions(cmd) .map((option) => { return formatItem( helper.optionTerm(option), helper.optionDescription(option), ); }); if (globalOptionList.length > 0) { output = output.concat([ 'Global Options:', formatList(globalOptionList), '', ]); } } // Commands const commandList = helper.visibleCommands(cmd).map((cmd) => { return formatItem( helper.subcommandTerm(cmd), helper.subcommandDescription(cmd), ); }); if (commandList.length > 0) { output = output.concat(['Commands:', formatList(commandList), '']); } return output.join('\n'); } /** * Calculate the pad width from the maximum term length. * * @param {Command} cmd * @param {Help} helper * @returns {number} */ padWidth(cmd, helper) { return Math.max( helper.longestOptionTermLength(cmd, helper), helper.longestGlobalOptionTermLength(cmd, helper), helper.longestSubcommandTermLength(cmd, helper), helper.longestArgumentTermLength(cmd, helper), ); } /** * Wrap the given string to width characters per line, with lines after the first indented. * Do not wrap if insufficient room for wrapping (minColumnWidth), or string is manually formatted. * * @param {string} str * @param {number} width * @param {number} indent * @param {number} [minColumnWidth=40] * @return {string} * */ wrap(str, width, indent, minColumnWidth = 40) { // Full \s characters, minus the linefeeds. const indents = ' \\f\\t\\v\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff'; // Detect manually wrapped and indented strings by searching for line break followed by spaces. const manualIndent = new RegExp(`[\\n][${indents}]+`); if (str.match(manualIndent)) return str; // Do not wrap if not enough room for a wrapped column of text (as could end up with a word per line). const columnWidth = width - indent; if (columnWidth < minColumnWidth) return str; const leadingStr = str.slice(0, indent); const columnText = str.slice(indent).replace('\r\n', '\n'); const indentString = ' '.repeat(indent); const zeroWidthSpace = '\u200B'; const breaks = `\\s${zeroWidthSpace}`; // Match line end (so empty lines don't collapse), // or as much text as will fit in column, or excess text up to first break. const regex = new RegExp( `\n|.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`, 'g', ); const lines = columnText.match(regex) || []; return ( leadingStr + lines .map((line, i) => { if (line === '\n') return ''; // preserve empty lines return (i > 0 ? indentString : '') + line.trimEnd(); }) .join('\n') ); } }; help.Help = Help$3; var option = {}; const { InvalidArgumentError: InvalidArgumentError$2 } = error; let Option$3 = class Option { /** * Initialize a new `Option` with the given `flags` and `description`. * * @param {string} flags * @param {string} [description] */ constructor(flags, description) { this.flags = flags; this.description = description || ''; this.required = flags.includes('<'); // A value must be supplied when the option is specified. this.optional = flags.includes('['); // A value is optional when the option is specified. // variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values. this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line. const optionFlags = splitOptionFlags(flags); this.short = optionFlags.shortFlag; this.long = optionFlags.longFlag; this.negate = false; if (this.long) { this.negate = this.long.startsWith('--no-'); } this.defaultValue = undefined; this.defaultValueDescription = undefined; this.presetArg = undefined; this.envVar = undefined; this.parseArg = undefined; this.hidden = false; this.argChoices = undefined; this.conflictsWith = []; this.implied = undefined; } /** * Set the default value, and optionally supply the description to be displayed in the help. * * @param {*} value * @param {string} [description] * @return {Option} */ default(value, description) { this.defaultValue = value; this.defaultValueDescription = description; return this; } /** * Preset to use when option used without option-argument, especially optional but also boolean and negated. * The custom processing (parseArg) is called. * * @example * new Option('--color').default('GREYSCALE').preset('RGB'); * new Option('--donate [amount]').preset('20').argParser(parseFloat); * * @param {*} arg * @return {Option} */ preset(arg) { this.presetArg = arg; return this; } /** * Add option name(s) that conflict with this option. * An error will be displayed if conflicting options are found during parsing. * * @example * new Option('--rgb').conflicts('cmyk'); * new Option('--js').conflicts(['ts', 'jsx']); * * @param {(string | string[])} names * @return {Option} */ conflicts(names) { this.conflictsWith = this.conflictsWith.concat(names); return this; } /** * Specify implied option values for when this option is set and the implied options are not. * * The custom processing (parseArg) is not called on the implied values. * * @example * program * .addOption(new Option('--log', 'write logging information to file')) * .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' })); * * @param {object} impliedOptionValues * @return {Option} */ implies(impliedOptionValues) { let newImplied = impliedOptionValues; if (typeof impliedOptionValues === 'string') { // string is not documented, but easy mistake and we can do what user probably intended. newImplied = { [impliedOptionValues]: true }; } this.implied = Object.assign(this.implied || {}, newImplied); return this; } /** * Set environment variable to check for option value. * * An environment variable is only used if when processed the current option value is * undefined, or the source of the current value is 'default' or 'config' or 'env'. * * @param {string} name * @return {Option} */ env(name) { this.envVar = name; return this; } /** * Set the custom handler for processing CLI option arguments into option values. * * @param {Function} [fn] * @return {Option} */ argParser(fn) { this.parseArg = fn; return this; } /** * Whether the option is mandatory and must have a value after parsing. * * @param {boolean} [mandatory=true] * @return {Option} */ makeOptionMandatory(mandatory = true) { this.mandatory = !!mandatory; return this; } /** * Hide option in help. * * @param {boolean} [hide=true] * @return {Option} */ hideHelp(hide = true) { this.hidden = !!hide; return this; } /** * @package */ _concatValue(value, previous) { if (previous === this.defaultValue || !Array.isArray(previous)) { return [value]; } return previous.concat(value); } /** * Only allow option value to be one of choices. * * @param {string[]} values * @return {Option} */ choices(values) { this.argChoices = values.slice(); this.parseArg = (arg, previous) => { if (!this.argChoices.includes(arg)) { throw new InvalidArgumentError$2( `Allowed choices are ${this.argChoices.join(', ')}.`, ); } if (this.variadic) { return this._concatValue(arg, previous); } return arg; }; return this; } /** * Return option name. * * @return {string} */ name() { if (this.long) { return this.long.replace(/^--/, ''); } return this.short.replace(/^-/, ''); } /** * Return option name, in a camelcase format that can be used * as a object attribute key. * * @return {string} */ attributeName() { return camelcase(this.name().replace(/^no-/, '')); } /** * Check if `arg` matches the short or long flag. * * @param {string} arg * @return {boolean} * @package */ is(arg) { return this.short === arg || this.long === arg; } /** * Return whether a boolean option. * * Options are one of boolean, negated, required argument, or optional argument. * * @return {boolean} * @package */ isBoolean() { return !this.required && !this.optional && !this.negate; } }; /** * This class is to make it easier to work with dual options, without changing the existing * implementation. We support separate dual options for separate positive and negative options, * like `--build` and `--no-build`, which share a single option value. This works nicely for some * use cases, but is tricky for others where we want separate behaviours despite * the single shared option value. */ let DualOptions$1 = class DualOptions { /** * @param {Option[]} options */ constructor(options) { this.positiveOptions = new Map(); this.negativeOptions = new Map(); this.dualOptions = new Set(); options.forEach((option) => { if (option.negate) { this.negativeOptions.set(option.attributeName(), option); } else { this.positiveOptions.set(option.attributeName(), option); } }); this.negativeOptions.forEach((value, key) => { if (this.positiveOptions.has(key)) { this.dualOptions.add(key); } }); } /** * Did the value come from the option, and not from possible matching dual option? * * @param {*} value * @param {Option} option * @returns {boolean} */ valueFromOption(value, option) { const optionKey = option.attributeName(); if (!this.dualOptions.has(optionKey)) return true; // Use the value to deduce if (probably) came from the option. const preset = this.negativeOptions.get(optionKey).presetArg; const negativeValue = preset !== undefined ? preset : false; return option.negate === (negativeValue === value); } }; /** * Convert string from kebab-case to camelCase. * * @param {string} str * @return {string} * @private */ function camelcase(str) { return str.split('-').reduce((str, word) => { return str + word[0].toUpperCase() + word.slice(1); }); } /** * Split the short and long flag out of something like '-m,--mixed <value>' * * @private */ function splitOptionFlags(flags) { let shortFlag; let longFlag; // Use original very loose parsing to maintain backwards compatibility for now, // which allowed for example unintended `-sw, --short-word` [sic]. const flagParts = flags.split(/[ |,]+/); if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1])) shortFlag = flagParts.shift(); longFlag = flagParts.shift(); // Add support for lone short flag without significantly changing parsing! if (!shortFlag && /^-[^-]$/.test(longFlag)) { shortFlag = longFlag; longFlag = undefined; } return { shortFlag, longFlag }; } option.Option = Option$3; option.DualOptions = DualOptions$1; var suggestSimilar$2 = {}; const maxDistance = 3; function editDistance(a, b) { // https://en.wikipedia.org/wiki/Damerau–Levenshtein_distance // Calculating optimal string alignment distance, no substring is edited more than once. // (Simple implementation.) // Quick early exit, return worst case. if (Math.abs(a.length - b.length) > maxDistance) return Math.max(a.length, b.length); // distance between prefix substrings of a and b const d = []; // pure deletions turn a into empty string for (let i = 0; i <= a.length; i++) { d[i] = [i]; } // pure insertions turn empty string into b for (let j = 0; j <= b.length; j++) { d[0][j] = j; } // fill matrix for (let j = 1; j <= b.length; j++) { for (let i = 1; i <= a.length; i++) { let cost = 1; if (a[i - 1] === b[j - 1]) { cost = 0; } else { cost = 1; } d[i][j] = Math.min( d[i - 1][j] + 1, // deletion d[i][j - 1] + 1, // insertion d[i - 1][j - 1] + cost, // substitution ); // transposition if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) { d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1); } } } return d[a.length][b.length]; } /** * Find close matches, restricted to same number of edits. * * @param {string} word * @param {string[]} candidates * @returns {string} */ function suggestSimilar$1(word, candidates) { if (!candidates || candidates.length === 0) return ''; // remove possible duplicates candidates = Array.from(new Set(candidates)); const searchingOptions = word.startsWith('--'); if (searchingOptions) { word = word.slice(2); candidates = candidates.map((candidate) => candidate.slice(2)); } let similar = []; let bestDistance = maxDistance; const minSimilarity = 0.4; candidates.forEach((candidate) => { if (candidate.length <= 1) return; // no one character guesses const distance = editDistance(word, candidate); const length = Math.max(word.length, candidate.length); const similarity = (length - distance) / length; if (similarity > minSimilarity) { if (distance < bestDistance) { // better edit distance, throw away previous worse matches bestDistance = distance; similar = [candidate]; } else if (distance === bestDistance) { similar.push(candidate); } } }); similar.sort((a, b) => a.localeCompare(b)); if (searchingOptions) { similar = similar.map((candidate) => `--${candidate}`); } if (similar.length > 1) { return `\n(Did you mean one of ${similar.join(', ')}?)`; } if (similar.length === 1) { return `\n(Did you mean ${similar[0]}?)`; } return ''; } suggestSimilar$2.suggestSimilar = suggestSimilar$1; const EventEmitter = require$$0.EventEmitter; const childProcess = require$$1; const path$1 = require$$2; const fs$1 = require$$3; const process$1 = require$$4; const { Argument: Argument$2, humanReadableArgName } = argument; const { CommanderError: CommanderError$2 } = error; const { Help: Help$2 } = help; const { Option: Option$2, DualOptions } = option; const { suggestSimilar } = suggestSimilar$2; let Command$2 = class Command extends EventEmitter { /** * Initialize a new `Command`. * * @param {string} [name] */ constructor(name) { super(); /** @type {Command[]} */ this.commands = []; /** @type {Option[]} *