patorjk / figlet.js

A FIG Driver written in JavaScript which aims to fully implement the FIGfont spec.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can this library be used in ES without webpack?

elgs opened this issue · comments

I don't see any export keyword in the figlet.js. I wonder if you can make a change so we can use it in native ES code? Thanks.

There is in node-figlet (https://github.com/patorjk/figlet.js/blob/master/lib/node-figlet.js). That's what package.json points to (for the "main" prop). Also, at the bottom of the figlet file, there is an export statement.

What kind of changes are you thinking of? What would be the use case? I'm all for updating the package if it makes it easier for something, as long as it maintains its backward compatibility.

@patorjk close, but it's an exports statement, as opposed to export.

The story is like this, when nodejs was born, the browsers did not have a module system yet. And suddenly npm created a big ecosystem that potentially could benefit the web dev 10 years ago. However, at the time, in order for browsers to use a 3rd party library, the library has to inject itself into the window scope. Because of this need, webpack and rollup were born. This duo was great 10 years ago, but is bad today. Because back then they enabled npm packages for web devs. But today they allowed fake ES syntax for many npm packages and effectively they hindered the modern browsers from natively loading 3rd party modules, like your package. The root cause is ES doesn't support module.exports syntax, and even worse, webpack allowed to use ES import syntax to load npm packages. This is effectively making webpack a dependency of most of today's web apps, which shouldn't be necessary at all.

The good part of webpack is help to bundle a web app, but the evil part webpack is to hinder the incentive of migrating the old node package system to ES module system, like yours. So that's why you could see lodash and lodash-es co-exist. Good thing is node has started to support ES syntax so that's the start of the death of the require syntax.

So I think it may make sense to create a new file called figlet-es.js which will be usable in modern browsers natively.

commented

Is there a workaround for this? I can't seem to import figlet in my es project

Yes. The work around is stop using Node and start using Deno. You can reverse engineer this entire library with ChatGPT in 4 hours and somehow, people are still using God Forsaken Webpack.

Allow me to illustrate:

types.ts

// types.ts
export type AsciiFont = {
  height: number;
  chars: Record<string, string[]>;
}

languages.ts

// Define code languages and script languages that will have specific comment styles
export const codeLanguages: string[] = [
  "js",
  "ts",
  "go",
  "rust",
  "c",
  "java",
  "css",
  "php",
  "sql"
];

Object.freeze(codeLanguages);

// Define script languages that will have specific comment styles
export const scriptLanguages: string[] = [
  "bash",
  "python",
  "ruby",
  "perl",
  "tcl",
  "r",
  "lua",
  "swift",
  "applescript",
  "powershell",
  "groovy",
  "coffeescript",
  "nginx"
];

Object.freeze(scriptLanguages);

fonts.ts

import { AsciiFont } from './types.ts';

/**
 *  ######   ####   ##  ##  ######  
 *  ##      ##  ##  ### ##    ##    
 *  ####    ##  ##  ## ###    ##    
 *  ##      ##  ##  ##  ##    ##    
 *  ##       ####   ##  ##    ##    
 * 
 *  FIGlet font Bright.flf
 *  Modified to exclude background. Character spacing normalized.
 *  
 */
export const fBright: AsciiFont = {
  height: 6,
  chars: {
    " ": [
      "    ",
      "    ",
      "    ",
      "    ",
      "    ",
      "    ",
    ],
    "!": [
      "##  ",
      "##  ",
      "##  ",
      "    ",
      "##  ",
      "    ",
    ],
    "\"": [
      "##  ##  ",
      "##  ##  ",
      " #  #   ",
      "        ",
      "        ",
      "        ",
    ],
    "#": [
      " #  #   ",
      "######  ",
      " #  #   ",
      "######  ",
      " #  #   ",
      "        ",
    ],
    "$": [
      " #####  ",
      "## #    ",
      " ####   ",
      "  # ##  ",
      "#####   ",
      "        ",
    ],
    "%": [
      "##  ##  ",
      "#  ##   ",
      "  ##    ",
      " ##  #  ",
      "##  ##  ",
      "        ",
    ],
    "&": [
      " #####   ",
      "##   ##  ",
      " ## ##   ",
      "## ## #  ",
      " #####   ",
      "         ",
    ],
    "'": [
      "##  ",
      "##  ",
      " #  ",
      "    ",
      "    ",
      "    ",
    ],
    "(": [
      "   ###  ",
      " ##     ",
      "#       ",
      " ##     ",
      "   ###  ",
      "        ",
    ],
    ")": [
      "###     ",
      "   ##   ",
      "     #  ",
      "   ##   ",
      "###     ",
      "        ",
    ],
    "*": [
      "#  #  #  ",
      " # # #   ",
      "#######  ",
      " # # #   ",
      "#  #  #  ",
      "         ",
    ],
    "+": [
      "  ##    ",
      "  ##    ",
      "######  ",
      "  ##    ",
      "  ##    ",
      "        ",
    ],
    ",": [
      "    ",
      "    ",
      "##  ",
      "##  ",
      " #  ",
      "    ",
    ],
    "-": [
      "        ",
      "        ",
      "######  ",
      "        ",
      "        ",
      "        ",
    ],
    ".": [
      "    ",
      "    ",
      "    ",
      "##  ",
      "##  ",
      "    ",
    ],
    "/": [
      "    ##  ",
      "   ##   ",
      "  ##    ",
      " ##     ",
      "##      ",
      "        ",
    ],
    "0": [
      " ####   ",
      "##  ##  ",
      "######  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "1": [
      "  ##    ",
      " ###    ",
      "  ##    ",
      "  ##    ",
      "######  ",
      "        ",
    ],
    "2": [
      " ####   ",
      "    ##  ",
      " ####   ",
      "##      ",
      "######  ",
      "        ",
    ],
    "3": [
      "######  ",
      "   ##   ",
      "  ###   ",
      "    ##  ",
      "#####   ",
      "        ",
    ],
    "4": [
      "    ##  ",
      "##  ##  ",
      "######  ",
      "    ##  ",
      "    ##  ",
      "        ",
    ],
    "5": [
      "######  ",
      "##      ",
      " ####   ",
      "    ##  ",
      "#####   ",
      "        ",
    ],
    "6": [
      "  ##    ",
      " ##     ",
      "#####   ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "7": [
      "######  ",
      "   ##   ",
      "  ##    ",
      " ##     ",
      "##      ",
      "        ",
    ],
    "8": [
      " ####   ",
      "##  ##  ",
      " ####   ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "9": [
      " ####   ",
      "##  ##  ",
      " ####   ",
      "  ##    ",
      " ##     ",
      "        ",
    ],
    ":": [
      "    ",
      "##  ",
      "    ",
      "##  ",
      "    ",
      "    ",
    ],
    ";": [
      "    ",
      "##  ",
      "    ",
      "##  ",
      " #  ",
      "    ",
    ],
    "<": [
      "    ##  ",
      "  ##    ",
      "##      ",
      "  ##    ",
      "    ##  ",
      "        ",
    ],
    "=": [
      "        ",
      "######  ",
      "        ",
      "######  ",
      "        ",
      "        ",
    ],
    ">": [
      "##      ",
      "  ##    ",
      "    ##  ",
      "  ##    ",
      "##      ",
      "        ",
    ],
    "?": [
      " ####   ",
      "##  ##  ",
      "   ##   ",
      "  ##    ",
      "  ##    ",
      "        ",
    ],
    "@": [
      " ####   ",
      "# ## #  ",
      "# ## #  ",
      "#  # #  ",
      " ####   ",
      "        ",
    ],
    "A": [
      " ####   ",
      "##  ##  ",
      "######  ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "B": [
      "#####   ",
      "##  ##  ",
      "#####   ",
      "##  ##  ",
      "#####   ",
      "        ",
    ],
    "C": [
      " ####   ",
      "##  ##  ",
      "##      ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "D": [
      "#####   ",
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      "#####   ",
      "        ",
    ],
    "E": [
      "######  ",
      "##      ",
      "####    ",
      "##      ",
      "######  ",
      "        ",
    ],
    "F": [
      "######  ",
      "##      ",
      "####    ",
      "##      ",
      "##      ",
      "        ",
    ],
    "G": [
      " ####   ",
      "##      ",
      "## ###  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "H": [
      "##  ##  ",
      "##  ##  ",
      "######  ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "I": [
      "######  ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "######  ",
      "        ",
    ],
    "J": [
      "######  ",
      "    ##  ",
      "    ##  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "K": [
      "##  ##  ",
      "## ##   ",
      "####    ",
      "## ##   ",
      "##  ##  ",
      "        ",
    ],
    "L": [
      "##      ",
      "##      ",
      "##      ",
      "##      ",
      "######  ",
      "        ",
    ],
    "M": [
      "##   ##  ",
      "### ###  ",
      "## # ##  ",
      "##   ##  ",
      "##   ##  ",
      "         ",
    ],
    "N": [
      "##  ##  ",
      "### ##  ",
      "## ###  ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "O": [
      " ####   ",
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "P": [
      "#####   ",
      "##  ##  ",
      "#####   ",
      "##      ",
      "##      ",
      "        ",
    ],
    "Q": [
      " ####   ",
      "##  ##  ",
      "## ###  ",
      "##  ##  ",
      " #####  ",
      "        ",
    ],
    "R": [
      "#####   ",
      "##  ##  ",
      "#####   ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "S": [
      " ####   ",
      "##      ",
      " ####   ",
      "    ##  ",
      " ####   ",
      "        ",
    ],
    "T": [
      "######  ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "        ",
    ],
    "U": [
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "V": [
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      " ####   ",
      "  ##    ",
      "        ",
    ],
    "W": [
      "##   ##  ",
      "##   ##  ",
      "## # ##  ",
      "#######  ",
      " ## ##   ",
      "         ",
    ],
    "X": [
      "##  ##  ",
      " ####   ",
      "  ##    ",
      " ####   ",
      "##  ##  ",
      "        ",
    ],
    "Y": [
      "##  ##  ",
      " ####   ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "        ",
    ],
    "Z": [
      "######  ",
      "   ##   ",
      "  ##    ",
      " ##     ",
      "######  ",
      "        ",
    ],
    "[": [
      "######  ",
      "##      ",
      "##      ",
      "##      ",
      "######  ",
      "        ",
    ],
    "\\": [
      "##      ",
      " ##     ",
      "  ##    ",
      "   ##   ",
      "    ##  ",
      "        ",
    ],
    "]": [
      "######  ",
      "    ##  ",
      "    ##  ",
      "    ##  ",
      "######  ",
      "        ",
    ],
    "^": [
      "  ##    ",
      " ####   ",
      "##  ##  ",
      "        ",
      "        ",
      "        ",
    ],
    "_": [
      "        ",
      "        ",
      "        ",
      "        ",
      "######  ",
      "        ",
    ],
    "`": [
      "##  ",
      "##  ",
      "#   ",
      "    ",
      "    ",
      "    ",
    ],
    "a": [
      " ####   ",
      "##  ##  ",
      "######  ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "b": [
      "#####   ",
      "##  ##  ",
      "#####   ",
      "##  ##  ",
      "#####   ",
      "        ",
    ],
    "c": [
      " ####   ",
      "##  ##  ",
      "##      ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "d": [
      "#####   ",
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      "#####   ",
      "        ",
    ],
    "e": [
      "######  ",
      "##      ",
      "####    ",
      "##      ",
      "######  ",
      "        ",
    ],
    "f": [
      "######  ",
      "##      ",
      "####    ",
      "##      ",
      "##      ",
      "        ",
    ],
    "g": [
      " ####   ",
      "##      ",
      "## ###  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "h": [
      "##  ##  ",
      "##  ##  ",
      "######  ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "i": [
      "######  ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "######  ",
      "        ",
    ],
    "j": [
      "######  ",
      "    ##  ",
      "    ##  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "k": [
      "##  ##  ",
      "## ##   ",
      "####    ",
      "## ##   ",
      "##  ##  ",
      "        ",
    ],
    "l": [
      "##      ",
      "##      ",
      "##      ",
      "##      ",
      "######  ",
      "        ",
    ],
    "m": [
      "##   ##  ",
      "### ###  ",
      "## # ##  ",
      "##   ##  ",
      "##   ##  ",
      "         ",
    ],
    "n": [
      "##  ##  ",
      "### ##  ",
      "## ###  ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "o": [
      " ####   ",
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "p": [
      "#####   ",
      "##  ##  ",
      "#####   ",
      "##      ",
      "##      ",
      "        ",
    ],
    "q": [
      " ####   ",
      "##  ##  ",
      "## ###  ",
      "##  ##  ",
      " #####  ",
      "        ",
    ],
    "r": [
      "#####   ",
      "##  ##  ",
      "#####   ",
      "##  ##  ",
      "##  ##  ",
      "        ",
    ],
    "s": [
      " ####   ",
      "##      ",
      " ####   ",
      "    ##  ",
      " ####   ",
      "        ",
    ],
    "t": [
      "######  ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "        ",
    ],
    "u": [
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      " ####   ",
      "        ",
    ],
    "v": [
      "##  ##  ",
      "##  ##  ",
      "##  ##  ",
      " ####   ",
      "  ##    ",
      "        ",
    ],
    "w": [
      "##   ##  ",
      "##   ##  ",
      "## # ##  ",
      "#######  ",
      " ## ##   ",
      "         ",
    ],
    "x": [
      "##  ##  ",
      " ####   ",
      "  ##    ",
      " ####   ",
      "##  ##  ",
      "        ",
    ],
    "y": [
      "##  ##  ",
      " ####   ",
      "  ##    ",
      "  ##    ",
      "  ##    ",
      "        ",
    ],
    "z": [
      "######  ",
      "   ##   ",
      "  ##    ",
      " ##     ",
      "######  ",
      "        ",
    ],



    "{": [
      "  ####  ",
      "  ##    ",
      "###     ",
      "  ##    ",
      "  ####  ",
      "        ",
    ],
    "|": [
      "##  ",
      "##  ",
      "##  ",
      "##  ",
      "##  ",
      "##  ",
    ],
    "}": [
      "####    ",
      "  ##    ",
      "   ###  ",
      "  ##    ",
      "####    ",
      "        ",
    ],
    "~": [
      " ### #  ",
      "# ###   ",
      "        ",
      "        ",
      "        ",
      "        ",
    ],
  }
};

Object.freeze(fBright);
// Define code languages and script languages that will have specific comment styles
export const codeLanguages: string[] = [
  "js",
  "ts",
  "go",
  "rust",
  "c",
  "java",
  "css",
  "php",
  "sql"
];

Object.freeze(codeLanguages);

// Define script languages that will have specific comment styles
export const scriptLanguages: string[] = [
  "bash",
  "python",
  "ruby",
  "perl",
  "tcl",
  "r",
  "lua",
  "swift",
  "applescript",
  "powershell",
  "groovy",
  "coffeescript",
  "nginx"
];

Object.freeze(scriptLanguages);

engine.ts

import { AsciiFont } from "./types.ts";
import { codeLanguages, scriptLanguages } from "./languages.ts";

/**
 * Constructs an ASCII art representation of the input string using the provided font.
 *
 * @param {AsciiFont} font - The font object containing ASCII character representations.
 * @param {string} input - The input string to be converted to ASCII art.
 * @returns {Promise<string[]>} A Promise that resolves to an array of strings representing the ASCII art.
 *
 */
async function construct(font: AsciiFont, input: string): Promise<string[]> {
  // Initialize the output array with the same number of elements as the font height
  const outputArray: string[] = new Array(font.height).fill("");

  /**
   *   ####    ####    ####   ######  ######
   *  ##  ##  ##      ##  ##    ##      ##
   *  ######   ####   ##        ##      ##
   *  ##  ##      ##  ##  ##    ##      ##
   *  ##  ##   ####    ####   ######  ######
   *
   * @dev Example of ASCII full printable character set.
   * 
   * const inputASCII = " !\"#$%&'()*+,-./";
   * const inputASCII = "0123456789";
   * const inputASCII = ":;<=>?@";
   * const inputASCII = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   * const inputASCII = "[\\]^_`";
   * const inputASCII = "abcdefghijklmnopqrstuvwxyz";
   * const inputASCII = "{|}~";
   * 
   */
  
  // Define the list of printable ASCII characters
  const printableAscii = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

  // Check if input contains only printable ASCII characters
  if (!input.split("").every(char => printableAscii.includes(char))) {
    // If the input contains a non-printable ASCII character, abort the construction and return an empty array
    console.error("Error: Input contains non-printable ASCII characters. Aborting construct.");
    return [];
  }

  // Iterate through each character in the input string
  input.split("").forEach(char => {
    // Retrieve the ASCII representation for the current character
    const charLines = font.chars[char];

    // Add the corresponding lines of the character representation to the output array
    for (let i = 0; i < font.height; i++) {
      outputArray[i] += charLines[i];
    }
  });

  // Return the output array containing the ASCII art representation of the input string
  return outputArray;
}

/**
 * Formats the ASCII art output based on the specified language.
 *
 * @param {AsciiFont} font - The font object containing ASCII character representations.
 * @param {string[]} outputArray - The array of strings representing the ASCII art.
 * @param {string} [language="plain"] - The language specifying the desired comment style for the output.
 * @returns {Promise<string>} A Promise that resolves to a formatted string containing the ASCII art.
 *
 */
async function format(font: AsciiFont, outputArray: string[], language: string = "plain"): Promise<string> {

  /**
   * Transforms an array of strings by adding a prefix to each element and joining them with a newline.
   * Internal helper function.
   *
   * @param {string} prefix - The prefix to be added to each element in the outputArray.
   * @param {string[]} outputArray - The array of strings to be transformed.
   * @returns {string} The transformed string with the prefix added to each line and separated by newlines.
   * 
   */
  const transform = (prefix: string, lines: string[]): string => {
    return lines.map(line => prefix + line).join("\n");
  };

  // Check if the specified language is in the list of code languages
  if (codeLanguages.includes(language)) {
    // Transform the outputArray with a "*" prefix for code languages
    const transformedText = transform(" *  ", outputArray.slice(0, font.height));
    // Return the formatted output string with a JSDoc-style comment block
    return `/**\n${transformedText}\n *  \n */  `;
  }

  // Check if the specified language is in the list of script languages
  if (scriptLanguages.includes(language)) {
    // Transform the outputArray with a "#" prefix for script languages
    const transformedText = transform("#  ", outputArray.slice(0, font.height));
    // Return the formatted output string with a Unix shell-style comment block
    return `#  \n${transformedText}\n#  \n#  `;
  }

  // Check if the specified language is "html"
  if (language === "html") {
    // Transform the outputArray with a " " prefix for HTML
    const transformedText = transform("  ", outputArray.slice(0, font.height));
    // Return the formatted output string with an HTML-style comment block
    return `<!--  \n${transformedText}\n  \n-->  `;
  }

    // Check if the specified language is "latex"
    if (language === "latex") {
      // Transform the outputArray with a "% " prefix for LaTeX
      const transformedText = transform("%  ", outputArray.slice(0, font.height));
      // Return the formatted output string with an LaTeX-style comment block
      return `%\n${transformedText}\n%`;
    }

  // If no specific language is specified or matched, default to plain formatting
  return outputArray.join("\n");
}

/**
 * Renders the ASCII art representation of the input string using the provided font and language.
 *
 * @param {AsciiFont} font - The font object containing ASCII character representations.
 * @param {string} [input="default"] - The input string to be converted to ASCII art.
 * @param {string} [language="plain"] - The language specifying the desired comment style for the output.
 * @returns {Promise<void>} A Promise that resolves when the rendering is complete.
 * 
 */
export async function render(font: AsciiFont, input: string = "default", language: string = "plain"): Promise<void> {

  // Check if the input string is empty or contains only whitespace
  if (!input.trim().length) {
    // Log an error message and use the default input string
    console.error("Error: Missing or empty input string. Using default template.");
  }

  // Construct the ASCII art representation of the input string
  const outputArray: string[] = await construct(font, input);

  // Format the output according to the specified language
  const outputString: string = await format(font, outputArray, language);

  // Log the formatted output string with a newline at the end
  console.info(`${outputString}\n`);

}

mod.ts

export * as fonts from "./fonts.ts";
export { render } from "./engine.ts";

test.ts

import { fonts, render } from "./mod.ts";

/**
 * @dev
 * deno run --allow-read --check test.ts
 * 
 * Available fonts
 * fBright, fBanner, fThick, f4Max
 * 
 * function Signature
 * render(fonts.fNAME, input, language);
 * 
 * Test cases below:
 * 
 */

await render(fonts.fBright, `HELLO WORLD!`, "ts");

Output

/**
 *  ##  ##  ######  ##      ##       ####       ##   ##   ####   #####   ##      #####   ##  
 *  ##  ##  ##      ##      ##      ##  ##      ##   ##  ##  ##  ##  ##  ##      ##  ##  ##  
 *  ######  ####    ##      ##      ##  ##      ## # ##  ##  ##  #####   ##      ##  ##  ##  
 *  ##  ##  ##      ##      ##      ##  ##      #######  ##  ##  ##  ##  ##      ##  ##      
 *  ##  ##  ######  ######  ######   ####        ## ##    ####   ##  ##  ######  #####   ##  
 *
 *  
 */