UNPKG

vegan-ipsum

Version:

Generates passages of vegan-themed placeholder text suitable for use in web pages, graphics, and more. Works in the browser, NodeJS, and React Native.

717 lines (716 loc) 18 kB
#!/usr/bin/env node let commander = require("commander"); let child_process = require("child_process"); //#region src/constants/index.ts var FORMAT_HTML = "html"; var FORMAT_PLAIN = "plain"; var FORMATS = [FORMAT_HTML, FORMAT_PLAIN]; /** * An object representing line endings for different platforms. * * - `POSIX`: Line ending for POSIX-compliant systems (`\n`). * - `WIN32`: Line ending for Windows systems (`\r\n`). */ var LINE_ENDINGS = { POSIX: "\n", WIN32: "\r\n" }; /** * An object representing supported platforms. * * - `DARWIN`: macOS platform identifier. * - `LINUX`: Linux platform identifier. * - `WIN32`: Windows platform identifier. */ var SUPPORTED_PLATFORMS = { DARWIN: "darwin", LINUX: "linux", WIN32: "win32" }; /** * An object containing regular expressions for validating formats and units. * * - `FORMATS`: Matches supported text formats (`plain` or `html`), case-insensitive. * - `UNITS`: Matches supported unit types (`paragraphs`, `sentences`, `words`), case-insensitive. */ var REGEX = { FORMATS: /^(plain|html)$/i, UNITS: /^(paragraphs|sentences|words)$/i }; var UNIT_WORDS = "words"; var UNIT_SENTENCES = "sentences"; var UNIT_PARAGRAPHS = "paragraphs"; //#endregion //#region src/constants/words.ts /** * An array of default lorem ipsum words. */ var DEFAULT_WORDS = [ "ad", "adipisicing", "aliqua", "aliquip", "amet", "anim", "aute", "cillum", "commodo", "consectetur", "consequat", "culpa", "cupidatat", "deserunt", "do", "dolor", "dolore", "duis", "ea", "eiusmod", "elit", "enim", "esse", "est", "et", "eu", "ex", "excepteur", "exercitation", "fugiat", "id", "in", "incididunt", "ipsum", "irure", "labore", "laboris", "laborum", "Lorem", "magna", "minim", "mollit", "nisi", "non", "nostrud", "nulla", "occaecat", "officia", "pariatur", "proident", "qui", "quis", "reprehenderit", "sint", "sit", "sunt", "tempor", "ullamco", "ut", "velit", "veniam", "voluptate" ]; /** * An array of vegan-related words to accompany the default ones. */ var VEGAN_WORDS = [ "plant", "vegan", "kindness", "crueltyfree", "herbivore", "compassion", "earth", "dairyfree", "justice", "respect", "peace", "love", "greens", "fruit", "vegetable", "freedom", "life", "rights", "sanctuary", "nonviolence", "care", "conscious", "ethics", "climate", "truth", "plants", "health", "wholefood", "clean", "veggie", "legumes", "fiber", "avocado", "soy", "tofu", "tempeh", "lentils", "coconut", "nutrients", "plantpower", "choices", "saving", "sustain", "grain", "beans", "peas", "quinoa", "broccoli", "kale", "lettuce", "radish", "basil", "mint", "ginger", "turmeric", "natural", "organic", "kind" ]; /** * An array of kindness-related words to accompany the default ones. */ var KINDNESS_WORDS = [ "kindness", "compassion", "empathy", "mercy", "respect", "gentleness", "care", "love", "peace", "justice", "fairness", "awareness", "forgiveness", "integrity", "nonviolence", "harmony", "mindfulness", "humility", "patience", "sincerity", "tolerance", "understanding", "altruism", "grace", "generosity", "helpfulness", "selflessness", "support", "comfort", "sympathy", "warmth", "charity", "unity", "positivity" ]; /** * An array of vegan food-related words to accompany the default ones. */ var VEGAN_FOOD_WORDS = [ "tofu", "tempeh", "soymilk", "almondmilk", "oatmilk", "vegan-burger", "vegan-cheese", "jackfruit", "quinoa", "bowl", "lentil", "soup", "smoothie", "nut", "chia", "pudding", "granola", "plant-based", "vegan-yogurt", "vegan-pizza", "coconut", "chickpea", "curry", "soba", "noodles", "pancake", "avocado", "toast", "vegetable" ]; /** * An array of vegetable-related words to accompany the default ones. */ var VEGGIE_WORDS = [ "broccoli", "kale", "spinach", "lettuce", "cabbage", "beetroot", "carrot", "radish", "turnip", "cauliflower", "zucchini", "bell", "pepper", "cucumber", "eggplant", "okra", "tomato", "green", "beans", "peas", "sweet", "potato", "pumpkin", "asparagus", "artichoke", "brussels", "sprouts", "chard", "fennel", "leek", "parsnip", "celery", "shallot", "corn", "bamboo", "shoots", "beet", "greens", "mustard", "scallions", "radicchio", "snow", "onion", "squash" ]; /** * Final array combining default lorem ipsum and vegan-themed words. */ var WORDS = Array.from(new Set([ ...DEFAULT_WORDS, ...VEGAN_WORDS, ...KINDNESS_WORDS, ...VEGAN_FOOD_WORDS, ...VEGGIE_WORDS ])); //#endregion //#region src/util/env.ts /** * Determines if the current runtime environment is Node.js. * * @returns {boolean} `true` if the runtime is Node.js, otherwise `false`. */ var isNode = () => { return typeof module !== "undefined" && !!module.exports; }; /** * Determines if the current runtime environment is React Native. * * @returns {boolean} `true` if the runtime is React Native, otherwise `false`. */ var isReactNative = () => { try { return navigator.product === "ReactNative"; } catch (e) { return false; } }; /** * Determines if the current runtime environment is Windows. * * @returns {boolean} `true` if the process is running on a Windows platform, otherwise `false`. */ var isWindows = () => { try { return process.platform === SUPPORTED_PLATFORMS.WIN32; } catch (e) { return false; } }; //#endregion //#region src/util/strings.ts /** * Capitalizes the first character of a given string after trimming whitespace. * * @param {string} str - The input string to capitalize. * * @returns {string} The input string with the first character capitalized. */ var capitalize = (str) => { const trimmed = str.trim(); return trimmed.charAt(0).toUpperCase() + trimmed.slice(1); }; /** * Creates an array of a specified length, where each element is its index. * * @param {number} length - The desired length of the array. Defaults to 0. * * @returns {number[]} An array of indexes from 0 to `length - 1`. */ var rangeArray = (length = 0) => { return [...Array(length)].map((_, index) => index); }; /** * Creates an array of strings of a specified length, using a provided string generator function. * * @param {number} length - The desired length of the array. * @param {() => string} makeString - A function that generates a string for each element. * * @returns {string[]} An array of strings of the specified length. */ var fillArrayWith = (length, makeString) => { return rangeArray(length).map(() => makeString()); }; //#endregion //#region src/lib/generator.ts /** * A class for generating random text (words, sentences, paragraphs). */ var Generator = class { sentencesPerParagraph; wordsPerSentence; random; words; /** * Creates an instance of the `Generator` class. * * @param {GeneratorOptions} options - Configuration options for the generator. * * @throws {Error} If the minimum exceeds the maximum in the provided bounds. */ constructor({ sentencesPerParagraph = { max: 7, min: 3 }, wordsPerSentence = { max: 15, min: 5 }, random, words = WORDS } = {}) { if (sentencesPerParagraph.min > sentencesPerParagraph.max) throw new Error(`Minimum number of sentences per paragraph (${sentencesPerParagraph.min}) cannot exceed maximum (${sentencesPerParagraph.max}).`); if (wordsPerSentence.min > wordsPerSentence.max) throw new Error(`Minimum number of words per sentence (${wordsPerSentence.min}) cannot exceed maximum (${wordsPerSentence.max}).`); this.sentencesPerParagraph = sentencesPerParagraph; this.words = words; this.wordsPerSentence = wordsPerSentence; this.random = random || Math.random; } /** * Generates a random integer between the specified minimum and maximum values. * * @param {number} min - The minimum value (inclusive). * @param {number} max - The maximum value (inclusive). * * @returns {number} A random integer between `min` and `max`. */ generateRandomInteger(min, max) { return Math.floor(this.random() * (max - min + 1) + min); } /** * Generates a random sequence of words. * * @param {number} [num] - The number of words to generate. If not provided, a random number is used. * * @returns {string} A string of randomly generated words. */ generateRandomWords(num) { const { min, max } = this.wordsPerSentence; return rangeArray(num || this.generateRandomInteger(min, max)).reduce((accumulator) => { return `${this.pluckRandomWord()} ${accumulator}`; }, "").trim(); } /** * Generates a random sentence. * * @param {number} [num] - The number of words in the sentence. If not provided, a random number is used. * * @returns {string} A randomly generated sentence. */ generateRandomSentence(num) { return `${capitalize(this.generateRandomWords(num))}.`; } /** * Generates a random paragraph. * * @param {number} [num] - The number of sentences in the paragraph. If not provided, a random number is used. * * @returns {string} A randomly generated paragraph. */ generateRandomParagraph(num) { const { min, max } = this.sentencesPerParagraph; return rangeArray(num || this.generateRandomInteger(min, max)).reduce((accumulator) => { return `${this.generateRandomSentence()} ${accumulator}`; }, "").trim(); } /** * Selects a random word from the word list. * * @returns {string} A randomly selected word. */ pluckRandomWord() { const min = 0; const max = this.words.length - 1; const index = this.generateRandomInteger(min, max); return this.words[index]; } }; //#endregion //#region src/lib/VeganIpsum.ts /** * A class for generating vegan ipsum text in various formats and units. */ var VeganIpsum = class { format; suffix; generator; /** * Creates an instance of the `VeganIpsum` class. * * @param {GeneratorOptions} options - Configuration options for the text generator. * @param {LoremFormat} format - The format of the generated text (e.g., plain or HTML). * @param {string} [suffix] - A custom line ending or suffix for the generated text. * * @throws {Error} If the provided format is invalid. */ constructor(options = {}, format = FORMAT_PLAIN, suffix) { this.format = format; this.suffix = suffix; if (FORMATS.indexOf(format.toLowerCase()) === -1) throw new Error(`${format} is an invalid format. Please use ${FORMATS.join(" or ")}.`); this.generator = new Generator(options); this.suffix = suffix; } /** * Determines the appropriate line ending based on the environment and suffix. * * @returns {string} The line ending to use. */ getLineEnding() { if (this.suffix) return this.suffix; if (!isReactNative() && isNode() && isWindows()) return LINE_ENDINGS.WIN32; return LINE_ENDINGS.POSIX; } /** * Formats a single string based on the specified format (e.g., wraps in HTML tags if needed). * * @param {string} str - The string to format. * * @returns {string} The formatted string. */ formatString(str) { if (this.format === "html") return `<p>${str}</p>`; return str; } /** * Formats an array of strings based on the specified format. * * @param {string[]} strings - The array of strings to format. * * @returns {string[]} The array of formatted strings. */ formatStrings(strings) { return strings.map((str) => this.formatString(str)); } /** * Generates a specified number of words and formats them. * * @param {number} [num] - The number of words to generate. If not provided, a random number is used. * * @returns {string} A formatted string of generated words. */ generateWords(num) { return this.formatString(this.generator.generateRandomWords(num)); } /** * Generates a specified number of sentences and formats them. * * @param {number} [num] - The number of sentences to generate. If not provided, a random number is used. * * @returns {string} A formatted string of generated sentences. */ generateSentences(num) { return this.formatString(this.generator.generateRandomParagraph(num)); } /** * Generates a specified number of paragraphs and formats them. * * @param {number} num - The number of paragraphs to generate. * * @returns {string} A formatted string of generated paragraphs. */ generateParagraphs(num) { const makeString = this.generator.generateRandomParagraph.bind(this.generator); return this.formatStrings(fillArrayWith(num, makeString)).join(this.getLineEnding()); } }; //#endregion //#region src/index.ts /** * Generates vegan ipsum text based on the provided parameters. * * @param {VeganIpsumParams} params - Configuration options for generating vegan ipsum text. * * @returns {string} Generated vegan ipsum text as a string. */ var veganIpsum = ({ count = 1, random, format = FORMAT_PLAIN, paragraphLowerBound = 3, paragraphUpperBound = 7, sentenceLowerBound = 5, sentenceUpperBound = 15, units = UNIT_SENTENCES, words = WORDS, suffix = "" } = {}) => { const lorem = new VeganIpsum({ random, sentencesPerParagraph: { max: paragraphUpperBound, min: paragraphLowerBound }, words, wordsPerSentence: { max: sentenceUpperBound, min: sentenceLowerBound } }, format, suffix); switch (units) { case UNIT_PARAGRAPHS: return lorem.generateParagraphs(count); case UNIT_SENTENCES: return lorem.generateSentences(count); case UNIT_WORDS: return lorem.generateWords(count); default: return ""; } }; //#endregion //#region src/bin/lib/constants.ts var DESCRIPTION = "Generates one or more words|sentences|paragraphs"; var USAGE = "3 words [options]"; /** * An object containing the clipboard copy commands for different platforms. * * - `DARWIN`: Command for macOS (`pbcopy`). * - `LINUX`: Command for Linux (`xclip -selection clipboard`). * - `WIN32`: Command for Windows (`clip`). */ var COPY = { DARWIN: "pbcopy", LINUX: "xclip -selection clipboard", WIN32: "clip" }; var CANNOT_DETERMINE_PLATFORM = "Could not determine host operating system."; //#endregion //#region package.json var version = "2.0.1"; //#endregion //#region src/bin/lib/utils.ts /** * Retrieves the current process platform. * * @returns {string} The process platform (e.g., "darwin", "win32", "linux"). * * @throws {Error} If the platform cannot be determined. */ var getPlatform = () => { if (!process || typeof process.platform !== "string") throw new Error(CANNOT_DETERMINE_PLATFORM); return process.platform; }; /** * Checks if the given platform is supported. * * @param {string} platform - The process platform (e.g., "darwin", "win32", "linux"). * * @returns {boolean} `true` if the platform is supported, otherwise `false`. */ var isSupportedPlatform = (platform) => { return Object.values(SUPPORTED_PLATFORMS).indexOf(platform.toLowerCase()) !== -1; }; /** * Retrieves the appropriate copy command for the specified platform. * * @param {string} platform - The process platform (e.g., "darwin", "win32", "linux"). * * @returns {string} The copy command for the specified platform. */ var getCopyCommand = (platform = "") => { switch (platform.toLowerCase()) { case SUPPORTED_PLATFORMS.DARWIN: return COPY.DARWIN; case SUPPORTED_PLATFORMS.WIN32: return COPY.WIN32; case SUPPORTED_PLATFORMS.LINUX: default: return COPY.LINUX; } }; /** * Copies the provided text to the clipboard using the platform's native command. * * @param {string} text - The text to copy to the clipboard. * * @returns {Promise<string>} A promise that resolves with the copied text, or rejects with an error. * * @throws {Error} If the platform is not supported or if the copy command fails. */ var copyToClipboard = (text) => { return new Promise((resolve, reject) => { try { const platform = getPlatform(); if (isSupportedPlatform(platform) === false) throw new Error(`Copy is not supported for ${platform}`); (0, child_process.exec)(`echo "${text}" | ${getCopyCommand(platform)}`, (error, _stdout, stderr) => { if (error) return reject(error); if (stderr) return reject(new Error(stderr)); return resolve(text); }); } catch (error) { return reject(error); } }); }; /** * Retrieves the current version of the package. * * @returns {string} The version of the package as defined in `package.json`. */ var getVersion = () => version; //#endregion //#region src/bin/vegan-ipsum.bin.ts /** * CLI program for generating vegan ipsum text. * * - Arguments: * - `count`: The number of units to generate (e.g., words, sentences, or paragraphs). * - `units`: The type of units to generate (e.g., "words", "sentences", or "paragraphs"). * * - Options: * - `-c, --copy`: Copies the generated text to the clipboard. * - `-f, --format <format>`: Specifies the format of the output (e.g., "plain" or "html"). */ commander.program.version(getVersion()).usage(USAGE).description(DESCRIPTION).argument("count", "The number of units").argument("units", "Words, sentences, or paragraphs").option("-c --copy", "Copy").addOption(new commander.Option("-f --format <format>", "Format").choices(FORMATS).default(FORMAT_PLAIN)).action( /** * Action handler for the CLI program. * * @param {string} num - The number of units to generate (default: "1"). * @param {"words" | "word" | "sentences" | "sentence" | "paragraphs" | "paragraph" | undefined} units - The type of units to generate (default: "sentence"). */ (num = "1", units = "sentences") => { if (REGEX.UNITS.test(units) === false) { console.error(`${units} is not valid. Choose from paragraph(s), sentence(s), or word(s).`); process.exit(1); } const count = parseInt(num, 10); if (!count || count < 1) { console.error(`${count} is not valid. Choose a number greater than 1.`); process.exit(1); } const output = veganIpsum({ count, format: commander.program.getOptionValue("format"), units }); console.log(output); if (commander.program.getOptionValue("copy") === true) copyToClipboard(output).then(() => { console.log(""); console.log("✓ copied"); }).catch((err) => { console.log(err.message); }); } ); commander.program.parse(process.argv); //#endregion //# sourceMappingURL=vegan-ipsum.bin.js.map