1296 lines
36 KiB
Plaintext
1296 lines
36 KiB
Plaintext
const LAYOUT = {
|
|
FULL_WIDTH: 0,
|
|
FITTING: 1,
|
|
SMUSHING: 2,
|
|
CONTROLLED_SMUSHING: 3
|
|
};
|
|
class FigletFont {
|
|
constructor() {
|
|
this.comment = "";
|
|
this.numChars = 0;
|
|
this.options = {};
|
|
}
|
|
}
|
|
const fontList = [
|
|
"1Row",
|
|
"3-D",
|
|
"3D Diagonal",
|
|
"3D-ASCII",
|
|
"3x5",
|
|
"4Max",
|
|
"5 Line Oblique",
|
|
"AMC 3 Line",
|
|
"AMC 3 Liv1",
|
|
"AMC AAA01",
|
|
"AMC Neko",
|
|
"AMC Razor",
|
|
"AMC Razor2",
|
|
"AMC Slash",
|
|
"AMC Slider",
|
|
"AMC Thin",
|
|
"AMC Tubes",
|
|
"AMC Untitled",
|
|
"ANSI Regular",
|
|
"ANSI Shadow",
|
|
"ASCII 12",
|
|
"ASCII 9",
|
|
"ASCII New Roman",
|
|
"Acrobatic",
|
|
"Alligator",
|
|
"Alligator2",
|
|
"Alpha",
|
|
"Alphabet",
|
|
"Arrows",
|
|
"Avatar",
|
|
"B1FF",
|
|
"Babyface Lame",
|
|
"Babyface Leet",
|
|
"Banner",
|
|
"Banner3-D",
|
|
"Banner3",
|
|
"Banner4",
|
|
"Barbwire",
|
|
"Basic",
|
|
"Bear",
|
|
"Bell",
|
|
"Benjamin",
|
|
"Big ASCII 12",
|
|
"Big ASCII 9",
|
|
"Big Chief",
|
|
"Big Money-ne",
|
|
"Big Money-nw",
|
|
"Big Money-se",
|
|
"Big Money-sw",
|
|
"Big Mono 12",
|
|
"Big Mono 9",
|
|
"Big",
|
|
"Bigfig",
|
|
"Binary",
|
|
"Block",
|
|
"Blocks",
|
|
"Bloody",
|
|
"BlurVision ASCII",
|
|
"Bolger",
|
|
"Braced",
|
|
"Bright",
|
|
"Broadway KB",
|
|
"Broadway",
|
|
"Bubble",
|
|
"Bulbhead",
|
|
"Caligraphy",
|
|
"Caligraphy2",
|
|
"Calvin S",
|
|
"Cards",
|
|
"Catwalk",
|
|
"Chiseled",
|
|
"Chunky",
|
|
"Circle",
|
|
"Coinstak",
|
|
"Cola",
|
|
"Colossal",
|
|
"Computer",
|
|
"Contessa",
|
|
"Contrast",
|
|
"Cosmike",
|
|
"Cosmike2",
|
|
"Crawford",
|
|
"Crawford2",
|
|
"Crazy",
|
|
"Cricket",
|
|
"Cursive",
|
|
"Cyberlarge",
|
|
"Cybermedium",
|
|
"Cybersmall",
|
|
"Cygnet",
|
|
"DANC4",
|
|
"DOS Rebel",
|
|
"DWhistled",
|
|
"Dancing Font",
|
|
"Decimal",
|
|
"Def Leppard",
|
|
"Delta Corps Priest 1",
|
|
"DiamFont",
|
|
"Diamond",
|
|
"Diet Cola",
|
|
"Digital",
|
|
"Doh",
|
|
"Doom",
|
|
"Dot Matrix",
|
|
"Double Shorts",
|
|
"Double",
|
|
"Dr Pepper",
|
|
"Efti Chess",
|
|
"Efti Font",
|
|
"Efti Italic",
|
|
"Efti Piti",
|
|
"Efti Robot",
|
|
"Efti Wall",
|
|
"Efti Water",
|
|
"Electronic",
|
|
"Elite",
|
|
"Emboss 2",
|
|
"Emboss",
|
|
"Epic",
|
|
"Fender",
|
|
"Filter",
|
|
"Fire Font-k",
|
|
"Fire Font-s",
|
|
"Flipped",
|
|
"Flower Power",
|
|
"Four Tops",
|
|
"Fraktur",
|
|
"Fun Face",
|
|
"Fun Faces",
|
|
"Future",
|
|
"Fuzzy",
|
|
"Georgi16",
|
|
"Georgia11",
|
|
"Ghost",
|
|
"Ghoulish",
|
|
"Glenyn",
|
|
"Goofy",
|
|
"Gothic",
|
|
"Graceful",
|
|
"Gradient",
|
|
"Graffiti",
|
|
"Greek",
|
|
"Heart Left",
|
|
"Heart Right",
|
|
"Henry 3D",
|
|
"Hex",
|
|
"Hieroglyphs",
|
|
"Hollywood",
|
|
"Horizontal Left",
|
|
"Horizontal Right",
|
|
"ICL-1900",
|
|
"Impossible",
|
|
"Invita",
|
|
"Isometric1",
|
|
"Isometric2",
|
|
"Isometric3",
|
|
"Isometric4",
|
|
"Italic",
|
|
"Ivrit",
|
|
"JS Block Letters",
|
|
"JS Bracket Letters",
|
|
"JS Capital Curves",
|
|
"JS Cursive",
|
|
"JS Stick Letters",
|
|
"Jacky",
|
|
"Jazmine",
|
|
"Jerusalem",
|
|
"Katakana",
|
|
"Kban",
|
|
"Keyboard",
|
|
"Knob",
|
|
"Konto Slant",
|
|
"Konto",
|
|
"LCD",
|
|
"Larry 3D 2",
|
|
"Larry 3D",
|
|
"Lean",
|
|
"Letter",
|
|
"Letters",
|
|
"Lil Devil",
|
|
"Line Blocks",
|
|
"Linux",
|
|
"Lockergnome",
|
|
"Madrid",
|
|
"Marquee",
|
|
"Maxfour",
|
|
"Merlin1",
|
|
"Merlin2",
|
|
"Mike",
|
|
"Mini",
|
|
"Mirror",
|
|
"Mnemonic",
|
|
"Modular",
|
|
"Mono 12",
|
|
"Mono 9",
|
|
"Morse",
|
|
"Morse2",
|
|
"Moscow",
|
|
"Mshebrew210",
|
|
"Muzzle",
|
|
"NScript",
|
|
"NT Greek",
|
|
"NV Script",
|
|
"Nancyj-Fancy",
|
|
"Nancyj-Improved",
|
|
"Nancyj-Underlined",
|
|
"Nancyj",
|
|
"Nipples",
|
|
"O8",
|
|
"OS2",
|
|
"Octal",
|
|
"Ogre",
|
|
"Old Banner",
|
|
"Pagga",
|
|
"Patorjk's Cheese",
|
|
"Patorjk-HeX",
|
|
"Pawp",
|
|
"Peaks Slant",
|
|
"Peaks",
|
|
"Pebbles",
|
|
"Pepper",
|
|
"Poison",
|
|
"Puffy",
|
|
"Puzzle",
|
|
"Pyramid",
|
|
"Rammstein",
|
|
"Rebel",
|
|
"Rectangles",
|
|
"Red Phoenix",
|
|
"Relief",
|
|
"Relief2",
|
|
"Reverse",
|
|
"Roman",
|
|
"Rot13",
|
|
"Rotated",
|
|
"Rounded",
|
|
"Rowan Cap",
|
|
"Rozzo",
|
|
"RubiFont",
|
|
"Runic",
|
|
"Runyc",
|
|
"S Blood",
|
|
"SL Script",
|
|
"Santa Clara",
|
|
"Script",
|
|
"Serifcap",
|
|
"Shaded Blocky",
|
|
"Shadow",
|
|
"Shimrod",
|
|
"Short",
|
|
"Slant Relief",
|
|
"Slant",
|
|
"Slide",
|
|
"Small ASCII 12",
|
|
"Small ASCII 9",
|
|
"Small Block",
|
|
"Small Braille",
|
|
"Small Caps",
|
|
"Small Isometric1",
|
|
"Small Keyboard",
|
|
"Small Mono 12",
|
|
"Small Mono 9",
|
|
"Small Poison",
|
|
"Small Script",
|
|
"Small Shadow",
|
|
"Small Slant",
|
|
"Small Tengwar",
|
|
"Small",
|
|
"Soft",
|
|
"Speed",
|
|
"Spliff",
|
|
"Stacey",
|
|
"Stampate",
|
|
"Stampatello",
|
|
"Standard",
|
|
"Star Strips",
|
|
"Star Wars",
|
|
"Stellar",
|
|
"Stforek",
|
|
"Stick Letters",
|
|
"Stop",
|
|
"Straight",
|
|
"Stronger Than All",
|
|
"Sub-Zero",
|
|
"Swamp Land",
|
|
"Swan",
|
|
"Sweet",
|
|
"THIS",
|
|
"Tanja",
|
|
"Tengwar",
|
|
"Term",
|
|
"Terrace",
|
|
"Test1",
|
|
"The Edge",
|
|
"Thick",
|
|
"Thin",
|
|
"Thorned",
|
|
"Three Point",
|
|
"Ticks Slant",
|
|
"Ticks",
|
|
"Tiles",
|
|
"Tinker-Toy",
|
|
"Tmplr",
|
|
"Tombstone",
|
|
"Train",
|
|
"Trek",
|
|
"Tsalagi",
|
|
"Tubular",
|
|
"Twisted",
|
|
"Two Point",
|
|
"USA Flag",
|
|
"Univers",
|
|
"Upside Down Text",
|
|
"Varsity",
|
|
"Wavescape",
|
|
"Wavy",
|
|
"Weird",
|
|
"Wet Letter",
|
|
"Whimsy",
|
|
"WideTerm",
|
|
"Wow",
|
|
"miniwi"
|
|
];
|
|
function escapeRegExpChar(char) {
|
|
const specialChars = /[.*+?^${}()|[\]\\]/;
|
|
return specialChars.test(char) ? "\\" + char : char;
|
|
}
|
|
const figlet = (() => {
|
|
const { FULL_WIDTH = 0, FITTING, SMUSHING, CONTROLLED_SMUSHING } = LAYOUT;
|
|
const figFonts = {};
|
|
const figDefaults = {
|
|
font: "Standard",
|
|
fontPath: "./fonts",
|
|
fetchFontIfMissing: true
|
|
};
|
|
function removeEndChar(line, lineNum, fontHeight) {
|
|
const endChar = escapeRegExpChar(line.trim().slice(-1)) || "@";
|
|
const endCharRegEx = lineNum === fontHeight - 1 ? new RegExp(endChar + endChar + "?\\s*$") : new RegExp(endChar + "\\s*$");
|
|
return line.replace(endCharRegEx, "");
|
|
}
|
|
function getSmushingRules(oldLayout = -1, newLayout = null) {
|
|
let rules = {};
|
|
let val;
|
|
let codes = [
|
|
[16384, "vLayout", SMUSHING],
|
|
[8192, "vLayout", FITTING],
|
|
[4096, "vRule5", true],
|
|
[2048, "vRule4", true],
|
|
[1024, "vRule3", true],
|
|
[512, "vRule2", true],
|
|
[256, "vRule1", true],
|
|
[128, "hLayout", SMUSHING],
|
|
[64, "hLayout", FITTING],
|
|
[32, "hRule6", true],
|
|
[16, "hRule5", true],
|
|
[8, "hRule4", true],
|
|
[4, "hRule3", true],
|
|
[2, "hRule2", true],
|
|
[1, "hRule1", true]
|
|
];
|
|
val = newLayout !== null ? newLayout : oldLayout;
|
|
for (const [code, rule, value] of codes) {
|
|
if (val >= code) {
|
|
val -= code;
|
|
if (rules[rule] === void 0) {
|
|
rules[rule] = value;
|
|
}
|
|
} else if (rule !== "vLayout" && rule !== "hLayout") {
|
|
rules[rule] = false;
|
|
}
|
|
}
|
|
if (typeof rules["hLayout"] === "undefined") {
|
|
if (oldLayout === 0) {
|
|
rules["hLayout"] = FITTING;
|
|
} else if (oldLayout === -1) {
|
|
rules["hLayout"] = FULL_WIDTH;
|
|
} else {
|
|
if (rules["hRule1"] || rules["hRule2"] || rules["hRule3"] || rules["hRule4"] || rules["hRule5"] || rules["hRule6"]) {
|
|
rules["hLayout"] = CONTROLLED_SMUSHING;
|
|
} else {
|
|
rules["hLayout"] = SMUSHING;
|
|
}
|
|
}
|
|
} else if (rules["hLayout"] === SMUSHING) {
|
|
if (rules["hRule1"] || rules["hRule2"] || rules["hRule3"] || rules["hRule4"] || rules["hRule5"] || rules["hRule6"]) {
|
|
rules["hLayout"] = CONTROLLED_SMUSHING;
|
|
}
|
|
}
|
|
if (typeof rules["vLayout"] === "undefined") {
|
|
if (rules["vRule1"] || rules["vRule2"] || rules["vRule3"] || rules["vRule4"] || rules["vRule5"]) {
|
|
rules["vLayout"] = CONTROLLED_SMUSHING;
|
|
} else {
|
|
rules["vLayout"] = FULL_WIDTH;
|
|
}
|
|
} else if (rules["vLayout"] === SMUSHING) {
|
|
if (rules["vRule1"] || rules["vRule2"] || rules["vRule3"] || rules["vRule4"] || rules["vRule5"]) {
|
|
rules["vLayout"] = CONTROLLED_SMUSHING;
|
|
}
|
|
}
|
|
return rules;
|
|
}
|
|
function hRule1_Smush(ch1, ch2, hardBlank = "") {
|
|
if (ch1 === ch2 && ch1 !== hardBlank) {
|
|
return ch1;
|
|
}
|
|
return false;
|
|
}
|
|
function hRule2_Smush(ch1, ch2) {
|
|
let rule2Str = "|/\\[]{}()<>";
|
|
if (ch1 === "_") {
|
|
if (rule2Str.indexOf(ch2) !== -1) {
|
|
return ch2;
|
|
}
|
|
} else if (ch2 === "_") {
|
|
if (rule2Str.indexOf(ch1) !== -1) {
|
|
return ch1;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
function hRule3_Smush(ch1, ch2) {
|
|
let rule3Classes = "| /\\ [] {} () <>";
|
|
let r3_pos1 = rule3Classes.indexOf(ch1);
|
|
let r3_pos2 = rule3Classes.indexOf(ch2);
|
|
if (r3_pos1 !== -1 && r3_pos2 !== -1) {
|
|
if (r3_pos1 !== r3_pos2 && Math.abs(r3_pos1 - r3_pos2) !== 1) {
|
|
const startPos = Math.max(r3_pos1, r3_pos2);
|
|
const endPos = startPos + 1;
|
|
return rule3Classes.substring(startPos, endPos);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
function hRule4_Smush(ch1, ch2) {
|
|
let rule4Str = "[] {} ()";
|
|
let r4_pos1 = rule4Str.indexOf(ch1);
|
|
let r4_pos2 = rule4Str.indexOf(ch2);
|
|
if (r4_pos1 !== -1 && r4_pos2 !== -1) {
|
|
if (Math.abs(r4_pos1 - r4_pos2) <= 1) {
|
|
return "|";
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
function hRule5_Smush(ch1, ch2) {
|
|
const patterns = {
|
|
"/\\": "|",
|
|
"\\/": "Y",
|
|
"><": "X"
|
|
};
|
|
return patterns[ch1 + ch2] || false;
|
|
}
|
|
function hRule6_Smush(ch1, ch2, hardBlank = "") {
|
|
if (ch1 === hardBlank && ch2 === hardBlank) {
|
|
return hardBlank;
|
|
}
|
|
return false;
|
|
}
|
|
function vRule1_Smush(ch1, ch2) {
|
|
if (ch1 === ch2) {
|
|
return ch1;
|
|
}
|
|
return false;
|
|
}
|
|
function vRule2_Smush(ch1, ch2) {
|
|
return hRule2_Smush(ch1, ch2);
|
|
}
|
|
function vRule3_Smush(ch1, ch2) {
|
|
return hRule3_Smush(ch1, ch2);
|
|
}
|
|
function vRule4_Smush(ch1, ch2) {
|
|
if (ch1 === "-" && ch2 === "_" || ch1 === "_" && ch2 === "-") {
|
|
return "=";
|
|
}
|
|
return false;
|
|
}
|
|
function vRule5_Smush(ch1, ch2) {
|
|
if (ch1 === "|" && ch2 === "|") {
|
|
return "|";
|
|
}
|
|
return false;
|
|
}
|
|
function uni_Smush(ch1, ch2, hardBlank) {
|
|
if (ch2 === " " || ch2 === "") {
|
|
return ch1;
|
|
} else if (ch2 === hardBlank && ch1 !== " ") {
|
|
return ch1;
|
|
} else {
|
|
return ch2;
|
|
}
|
|
}
|
|
function canVerticalSmush(txt1, txt2, opts) {
|
|
if (opts.fittingRules?.vLayout === FULL_WIDTH) {
|
|
return "invalid";
|
|
}
|
|
let ii, len = Math.min(txt1.length, txt2.length), ch1, ch2, endSmush = false, validSmush;
|
|
if (len === 0) {
|
|
return "invalid";
|
|
}
|
|
for (ii = 0; ii < len; ii++) {
|
|
ch1 = txt1.substring(ii, ii + 1);
|
|
ch2 = txt2.substring(ii, ii + 1);
|
|
if (ch1 !== " " && ch2 !== " ") {
|
|
if (opts.fittingRules?.vLayout === FITTING) {
|
|
return "invalid";
|
|
} else if (opts.fittingRules?.vLayout === SMUSHING) {
|
|
return "end";
|
|
} else {
|
|
if (vRule5_Smush(ch1, ch2)) {
|
|
endSmush = endSmush || false;
|
|
continue;
|
|
}
|
|
validSmush = false;
|
|
validSmush = opts.fittingRules?.vRule1 ? vRule1_Smush(ch1, ch2) : validSmush;
|
|
validSmush = !validSmush && opts.fittingRules?.vRule2 ? vRule2_Smush(ch1, ch2) : validSmush;
|
|
validSmush = !validSmush && opts.fittingRules?.vRule3 ? vRule3_Smush(ch1, ch2) : validSmush;
|
|
validSmush = !validSmush && opts.fittingRules?.vRule4 ? vRule4_Smush(ch1, ch2) : validSmush;
|
|
endSmush = true;
|
|
if (!validSmush) {
|
|
return "invalid";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (endSmush) {
|
|
return "end";
|
|
} else {
|
|
return "valid";
|
|
}
|
|
}
|
|
function getVerticalSmushDist(lines1, lines2, opts) {
|
|
let maxDist = lines1.length;
|
|
let len1 = lines1.length;
|
|
let subLines1, subLines2, slen;
|
|
let curDist = 1;
|
|
let ii, ret, result;
|
|
while (curDist <= maxDist) {
|
|
subLines1 = lines1.slice(Math.max(0, len1 - curDist), len1);
|
|
subLines2 = lines2.slice(0, Math.min(maxDist, curDist));
|
|
slen = subLines2.length;
|
|
result = "";
|
|
for (ii = 0; ii < slen; ii++) {
|
|
ret = canVerticalSmush(subLines1[ii], subLines2[ii], opts);
|
|
if (ret === "end") {
|
|
result = ret;
|
|
} else if (ret === "invalid") {
|
|
result = ret;
|
|
break;
|
|
} else {
|
|
if (result === "") {
|
|
result = "valid";
|
|
}
|
|
}
|
|
}
|
|
if (result === "invalid") {
|
|
curDist--;
|
|
break;
|
|
}
|
|
if (result === "end") {
|
|
break;
|
|
}
|
|
if (result === "valid") {
|
|
curDist++;
|
|
}
|
|
}
|
|
return Math.min(maxDist, curDist);
|
|
}
|
|
function verticallySmushLines(line1, line2, opts) {
|
|
let ii, len = Math.min(line1.length, line2.length);
|
|
let ch1, ch2, result = "", validSmush;
|
|
for (ii = 0; ii < len; ii++) {
|
|
ch1 = line1.substring(ii, ii + 1);
|
|
ch2 = line2.substring(ii, ii + 1);
|
|
if (ch1 !== " " && ch2 !== " ") {
|
|
if (opts.fittingRules?.vLayout === FITTING) {
|
|
result += uni_Smush(ch1, ch2);
|
|
} else if (opts.fittingRules?.vLayout === SMUSHING) {
|
|
result += uni_Smush(ch1, ch2);
|
|
} else {
|
|
validSmush = false;
|
|
validSmush = opts.fittingRules?.vRule5 ? vRule5_Smush(ch1, ch2) : validSmush;
|
|
validSmush = !validSmush && opts.fittingRules?.vRule1 ? vRule1_Smush(ch1, ch2) : validSmush;
|
|
validSmush = !validSmush && opts.fittingRules?.vRule2 ? vRule2_Smush(ch1, ch2) : validSmush;
|
|
validSmush = !validSmush && opts.fittingRules?.vRule3 ? vRule3_Smush(ch1, ch2) : validSmush;
|
|
validSmush = !validSmush && opts.fittingRules?.vRule4 ? vRule4_Smush(ch1, ch2) : validSmush;
|
|
result += validSmush;
|
|
}
|
|
} else {
|
|
result += uni_Smush(ch1, ch2);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function verticalSmush(lines1, lines2, overlap, opts) {
|
|
let len1 = lines1.length;
|
|
let len2 = lines2.length;
|
|
let piece1 = lines1.slice(0, Math.max(0, len1 - overlap));
|
|
let piece2_1 = lines1.slice(Math.max(0, len1 - overlap), len1);
|
|
let piece2_2 = lines2.slice(0, Math.min(overlap, len2));
|
|
let ii, len, line, piece2 = [], piece3;
|
|
len = piece2_1.length;
|
|
for (ii = 0; ii < len; ii++) {
|
|
if (ii >= len2) {
|
|
line = piece2_1[ii];
|
|
} else {
|
|
line = verticallySmushLines(piece2_1[ii], piece2_2[ii], opts);
|
|
}
|
|
piece2.push(line);
|
|
}
|
|
piece3 = lines2.slice(Math.min(overlap, len2), len2);
|
|
return [...piece1, ...piece2, ...piece3];
|
|
}
|
|
function padLines(lines, numSpaces) {
|
|
const padding = " ".repeat(numSpaces);
|
|
return lines.map((line) => line + padding);
|
|
}
|
|
function smushVerticalFigLines(output, lines, opts) {
|
|
let len1 = output[0].length;
|
|
let len2 = lines[0].length;
|
|
let overlap;
|
|
if (len1 > len2) {
|
|
lines = padLines(lines, len1 - len2);
|
|
} else if (len2 > len1) {
|
|
output = padLines(output, len2 - len1);
|
|
}
|
|
overlap = getVerticalSmushDist(output, lines, opts);
|
|
return verticalSmush(output, lines, overlap, opts);
|
|
}
|
|
function getHorizontalSmushLength(txt1, txt2, opts) {
|
|
if (opts.fittingRules?.hLayout === FULL_WIDTH) {
|
|
return 0;
|
|
}
|
|
let ii, len1 = txt1.length, len2 = txt2.length;
|
|
let maxDist = len1;
|
|
let curDist = 1;
|
|
let breakAfter = false;
|
|
let seg1, seg2, ch1, ch2;
|
|
if (len1 === 0) {
|
|
return 0;
|
|
}
|
|
distCal: while (curDist <= maxDist) {
|
|
const seg1StartPos = len1 - curDist;
|
|
seg1 = txt1.substring(seg1StartPos, seg1StartPos + curDist);
|
|
seg2 = txt2.substring(0, Math.min(curDist, len2));
|
|
for (ii = 0; ii < Math.min(curDist, len2); ii++) {
|
|
ch1 = seg1.substring(ii, ii + 1);
|
|
ch2 = seg2.substring(ii, ii + 1);
|
|
if (ch1 !== " " && ch2 !== " ") {
|
|
if (opts.fittingRules?.hLayout === FITTING) {
|
|
curDist = curDist - 1;
|
|
break distCal;
|
|
} else if (opts.fittingRules?.hLayout === SMUSHING) {
|
|
if (ch1 === opts.hardBlank || ch2 === opts.hardBlank) {
|
|
curDist = curDist - 1;
|
|
}
|
|
break distCal;
|
|
} else {
|
|
breakAfter = true;
|
|
const validSmush = opts.fittingRules?.hRule1 && hRule1_Smush(ch1, ch2, opts?.hardBlank) || opts.fittingRules?.hRule2 && hRule2_Smush(ch1, ch2) || opts.fittingRules?.hRule3 && hRule3_Smush(ch1, ch2) || opts.fittingRules?.hRule4 && hRule4_Smush(ch1, ch2) || opts.fittingRules?.hRule5 && hRule5_Smush(ch1, ch2) || opts.fittingRules?.hRule6 && hRule6_Smush(ch1, ch2, opts?.hardBlank);
|
|
if (!validSmush) {
|
|
curDist = curDist - 1;
|
|
break distCal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (breakAfter) {
|
|
break;
|
|
}
|
|
curDist++;
|
|
}
|
|
return Math.min(maxDist, curDist);
|
|
}
|
|
function horizontalSmush(textBlock1, textBlock2, overlap, opts) {
|
|
let ii, jj, outputFig = [], overlapStart, piece1, piece2, piece3, len1, len2, txt1, txt2;
|
|
if (typeof opts.height !== "number") {
|
|
throw new Error("height is not defined.");
|
|
}
|
|
for (ii = 0; ii < opts.height; ii++) {
|
|
txt1 = textBlock1[ii];
|
|
txt2 = textBlock2[ii];
|
|
len1 = txt1.length;
|
|
len2 = txt2.length;
|
|
overlapStart = len1 - overlap;
|
|
piece1 = txt1.slice(0, Math.max(0, overlapStart));
|
|
piece2 = "";
|
|
const seg1StartPos = Math.max(0, len1 - overlap);
|
|
let seg1 = txt1.substring(seg1StartPos, seg1StartPos + overlap);
|
|
let seg2 = txt2.substring(0, Math.min(overlap, len2));
|
|
for (jj = 0; jj < overlap; jj++) {
|
|
let ch1 = jj < len1 ? seg1.substring(jj, jj + 1) : " ";
|
|
let ch2 = jj < len2 ? seg2.substring(jj, jj + 1) : " ";
|
|
if (ch1 !== " " && ch2 !== " ") {
|
|
if (opts.fittingRules?.hLayout === FITTING || opts.fittingRules?.hLayout === SMUSHING) {
|
|
piece2 += uni_Smush(ch1, ch2, opts.hardBlank);
|
|
} else {
|
|
const nextCh = opts.fittingRules?.hRule1 && hRule1_Smush(ch1, ch2, opts.hardBlank) || opts.fittingRules?.hRule2 && hRule2_Smush(ch1, ch2) || opts.fittingRules?.hRule3 && hRule3_Smush(ch1, ch2) || opts.fittingRules?.hRule4 && hRule4_Smush(ch1, ch2) || opts.fittingRules?.hRule5 && hRule5_Smush(ch1, ch2) || opts.fittingRules?.hRule6 && hRule6_Smush(ch1, ch2, opts.hardBlank) || uni_Smush(ch1, ch2, opts.hardBlank);
|
|
piece2 += nextCh;
|
|
}
|
|
} else {
|
|
piece2 += uni_Smush(ch1, ch2, opts.hardBlank);
|
|
}
|
|
}
|
|
if (overlap >= len2) {
|
|
piece3 = "";
|
|
} else {
|
|
piece3 = txt2.substring(overlap, overlap + Math.max(0, len2 - overlap));
|
|
}
|
|
outputFig[ii] = piece1 + piece2 + piece3;
|
|
}
|
|
return outputFig;
|
|
}
|
|
function newFigChar(len) {
|
|
return new Array(len).fill("");
|
|
}
|
|
const figLinesWidth = function(textLines) {
|
|
return Math.max(...textLines.map((line) => line.length));
|
|
};
|
|
function joinFigArray(array, len, opts) {
|
|
return array.reduce(function(acc, data) {
|
|
return horizontalSmush(acc, data.fig, data.overlap || 0, opts);
|
|
}, newFigChar(len));
|
|
}
|
|
function breakWord(figChars, len, opts) {
|
|
for (let i = figChars.length - 1; i > 0; i--) {
|
|
const w = joinFigArray(figChars.slice(0, i), len, opts);
|
|
if (figLinesWidth(w) <= opts.width) {
|
|
return {
|
|
outputFigText: w,
|
|
chars: figChars.slice(i)
|
|
};
|
|
}
|
|
}
|
|
return { outputFigText: newFigChar(len), chars: figChars };
|
|
}
|
|
function generateFigTextLines(txt, figChars, opts) {
|
|
let charIndex, figChar, overlap = 0, row, outputFigText, len, height = opts.height, outputFigLines = [], maxWidth, nextFigChars = {
|
|
chars: [],
|
|
// list of characters is used to break in the middle of the word when word is longer
|
|
overlap
|
|
// chars is array of characters with {fig, overlap} and overlap is for whole word
|
|
}, figWords = [], char, isSpace, textFigWord, textFigLine, tmpBreak;
|
|
if (typeof height !== "number") {
|
|
throw new Error("height is not defined.");
|
|
}
|
|
outputFigText = newFigChar(height);
|
|
if (opts.printDirection === 1) {
|
|
txt = txt.split("").reverse().join("");
|
|
}
|
|
len = txt.length;
|
|
for (charIndex = 0; charIndex < len; charIndex++) {
|
|
char = txt.substring(charIndex, charIndex + 1);
|
|
isSpace = char.match(/\s/);
|
|
figChar = figChars[char.charCodeAt(0)];
|
|
textFigLine = null;
|
|
if (figChar) {
|
|
if (opts.fittingRules?.hLayout !== FULL_WIDTH) {
|
|
overlap = 1e4;
|
|
for (row = 0; row < height; row++) {
|
|
overlap = Math.min(
|
|
overlap,
|
|
getHorizontalSmushLength(outputFigText[row], figChar[row], opts)
|
|
);
|
|
}
|
|
overlap = overlap === 1e4 ? 0 : overlap;
|
|
}
|
|
if (opts.width > 0) {
|
|
if (opts.whitespaceBreak) {
|
|
textFigWord = joinFigArray(
|
|
nextFigChars.chars.concat([
|
|
{
|
|
fig: figChar,
|
|
overlap
|
|
}
|
|
]),
|
|
height,
|
|
opts
|
|
);
|
|
textFigLine = joinFigArray(
|
|
figWords.concat([
|
|
{
|
|
fig: textFigWord,
|
|
overlap: nextFigChars.overlap
|
|
}
|
|
]),
|
|
height,
|
|
opts
|
|
);
|
|
maxWidth = figLinesWidth(textFigLine);
|
|
} else {
|
|
textFigLine = horizontalSmush(
|
|
outputFigText,
|
|
figChar,
|
|
overlap,
|
|
opts
|
|
);
|
|
maxWidth = figLinesWidth(textFigLine);
|
|
}
|
|
if (maxWidth >= opts.width && charIndex > 0) {
|
|
if (opts.whitespaceBreak) {
|
|
outputFigText = joinFigArray(figWords.slice(0, -1), height, opts);
|
|
if (figWords.length > 1) {
|
|
outputFigLines.push(outputFigText);
|
|
outputFigText = newFigChar(height);
|
|
}
|
|
figWords = [];
|
|
} else {
|
|
outputFigLines.push(outputFigText);
|
|
outputFigText = newFigChar(height);
|
|
}
|
|
}
|
|
}
|
|
if (opts.width > 0 && opts.whitespaceBreak) {
|
|
if (!isSpace || charIndex === len - 1) {
|
|
nextFigChars.chars.push({ fig: figChar, overlap });
|
|
}
|
|
if (isSpace || charIndex === len - 1) {
|
|
tmpBreak = null;
|
|
while (true) {
|
|
textFigLine = joinFigArray(nextFigChars.chars, height, opts);
|
|
maxWidth = figLinesWidth(textFigLine);
|
|
if (maxWidth >= opts.width) {
|
|
tmpBreak = breakWord(nextFigChars.chars, height, opts);
|
|
nextFigChars = { chars: tmpBreak.chars };
|
|
outputFigLines.push(tmpBreak.outputFigText);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (maxWidth > 0) {
|
|
if (tmpBreak) {
|
|
figWords.push({ fig: textFigLine, overlap: 1 });
|
|
} else {
|
|
figWords.push({
|
|
fig: textFigLine,
|
|
overlap: nextFigChars.overlap
|
|
});
|
|
}
|
|
}
|
|
if (isSpace) {
|
|
figWords.push({ fig: figChar, overlap });
|
|
outputFigText = newFigChar(height);
|
|
}
|
|
if (charIndex === len - 1) {
|
|
outputFigText = joinFigArray(figWords, height, opts);
|
|
}
|
|
nextFigChars = {
|
|
chars: [],
|
|
overlap
|
|
};
|
|
continue;
|
|
}
|
|
}
|
|
outputFigText = horizontalSmush(outputFigText, figChar, overlap, opts);
|
|
}
|
|
}
|
|
if (figLinesWidth(outputFigText) > 0) {
|
|
outputFigLines.push(outputFigText);
|
|
}
|
|
if (!opts.showHardBlanks) {
|
|
outputFigLines.forEach(function(outputFigText2) {
|
|
len = outputFigText2.length;
|
|
for (row = 0; row < len; row++) {
|
|
outputFigText2[row] = outputFigText2[row].replace(
|
|
new RegExp("\\" + opts.hardBlank, "g"),
|
|
" "
|
|
);
|
|
}
|
|
});
|
|
}
|
|
if (txt === "" && outputFigLines.length === 0) {
|
|
outputFigLines.push(new Array(height).fill(""));
|
|
}
|
|
return outputFigLines;
|
|
}
|
|
const getHorizontalFittingRules = function(layout, options) {
|
|
let params;
|
|
if (layout === "default") {
|
|
params = {
|
|
hLayout: options.fittingRules?.hLayout,
|
|
hRule1: options.fittingRules?.hRule1,
|
|
hRule2: options.fittingRules?.hRule2,
|
|
hRule3: options.fittingRules?.hRule3,
|
|
hRule4: options.fittingRules?.hRule4,
|
|
hRule5: options.fittingRules?.hRule5,
|
|
hRule6: options.fittingRules?.hRule6
|
|
};
|
|
} else if (layout === "full") {
|
|
params = {
|
|
hLayout: FULL_WIDTH,
|
|
hRule1: false,
|
|
hRule2: false,
|
|
hRule3: false,
|
|
hRule4: false,
|
|
hRule5: false,
|
|
hRule6: false
|
|
};
|
|
} else if (layout === "fitted") {
|
|
params = {
|
|
hLayout: FITTING,
|
|
hRule1: false,
|
|
hRule2: false,
|
|
hRule3: false,
|
|
hRule4: false,
|
|
hRule5: false,
|
|
hRule6: false
|
|
};
|
|
} else if (layout === "controlled smushing") {
|
|
params = {
|
|
hLayout: CONTROLLED_SMUSHING,
|
|
hRule1: true,
|
|
hRule2: true,
|
|
hRule3: true,
|
|
hRule4: true,
|
|
hRule5: true,
|
|
hRule6: true
|
|
};
|
|
} else if (layout === "universal smushing") {
|
|
params = {
|
|
hLayout: SMUSHING,
|
|
hRule1: false,
|
|
hRule2: false,
|
|
hRule3: false,
|
|
hRule4: false,
|
|
hRule5: false,
|
|
hRule6: false
|
|
};
|
|
} else {
|
|
return;
|
|
}
|
|
return params;
|
|
};
|
|
const getVerticalFittingRules = function(layout, options) {
|
|
let params = {};
|
|
if (layout === "default") {
|
|
params = {
|
|
vLayout: options.fittingRules?.vLayout,
|
|
vRule1: options.fittingRules?.vRule1,
|
|
vRule2: options.fittingRules?.vRule2,
|
|
vRule3: options.fittingRules?.vRule3,
|
|
vRule4: options.fittingRules?.vRule4,
|
|
vRule5: options.fittingRules?.vRule5
|
|
};
|
|
} else if (layout === "full") {
|
|
params = {
|
|
vLayout: FULL_WIDTH,
|
|
vRule1: false,
|
|
vRule2: false,
|
|
vRule3: false,
|
|
vRule4: false,
|
|
vRule5: false
|
|
};
|
|
} else if (layout === "fitted") {
|
|
params = {
|
|
vLayout: FITTING,
|
|
vRule1: false,
|
|
vRule2: false,
|
|
vRule3: false,
|
|
vRule4: false,
|
|
vRule5: false
|
|
};
|
|
} else if (layout === "controlled smushing") {
|
|
params = {
|
|
vLayout: CONTROLLED_SMUSHING,
|
|
vRule1: true,
|
|
vRule2: true,
|
|
vRule3: true,
|
|
vRule4: true,
|
|
vRule5: true
|
|
};
|
|
} else if (layout === "universal smushing") {
|
|
params = {
|
|
vLayout: SMUSHING,
|
|
vRule1: false,
|
|
vRule2: false,
|
|
vRule3: false,
|
|
vRule4: false,
|
|
vRule5: false
|
|
};
|
|
} else {
|
|
return;
|
|
}
|
|
return params;
|
|
};
|
|
const generateText = function(fontName, options, txt) {
|
|
txt = txt.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
let lines = txt.split("\n");
|
|
let figLines = [];
|
|
let ii, len, output;
|
|
len = lines.length;
|
|
for (ii = 0; ii < len; ii++) {
|
|
figLines = figLines.concat(
|
|
generateFigTextLines(lines[ii], figFonts[fontName], options)
|
|
);
|
|
}
|
|
len = figLines.length;
|
|
output = figLines[0];
|
|
for (ii = 1; ii < len; ii++) {
|
|
output = smushVerticalFigLines(output, figLines[ii], options);
|
|
}
|
|
return output ? output.join("\n") : "";
|
|
};
|
|
function _reworkFontOpts(fontMeta, options) {
|
|
let myOpts;
|
|
if (typeof structuredClone !== "undefined") {
|
|
myOpts = structuredClone(fontMeta);
|
|
} else {
|
|
myOpts = JSON.parse(JSON.stringify(fontMeta));
|
|
}
|
|
myOpts.showHardBlanks = options.showHardBlanks || false;
|
|
myOpts.width = options.width || -1;
|
|
myOpts.whitespaceBreak = options.whitespaceBreak || false;
|
|
if (options.horizontalLayout) {
|
|
const params = getHorizontalFittingRules(
|
|
options.horizontalLayout,
|
|
fontMeta
|
|
);
|
|
if (params) {
|
|
Object.assign(myOpts.fittingRules, params);
|
|
}
|
|
}
|
|
if (options.verticalLayout) {
|
|
const params = getVerticalFittingRules(options.verticalLayout, fontMeta);
|
|
if (params) {
|
|
Object.assign(myOpts.fittingRules, params);
|
|
}
|
|
}
|
|
myOpts.printDirection = options.printDirection ?? fontMeta.printDirection;
|
|
return myOpts;
|
|
}
|
|
const me = async function(txt, optionsOrFontOrCallback, callback) {
|
|
return me.text(txt, optionsOrFontOrCallback, callback);
|
|
};
|
|
me.text = async function(txt, optionsOrFontOrCallback, callback) {
|
|
txt = txt + "";
|
|
let options, next;
|
|
if (typeof optionsOrFontOrCallback === "function") {
|
|
next = optionsOrFontOrCallback;
|
|
options = { font: figDefaults.font };
|
|
} else if (typeof optionsOrFontOrCallback === "string") {
|
|
options = { font: optionsOrFontOrCallback };
|
|
next = callback;
|
|
} else if (optionsOrFontOrCallback) {
|
|
options = optionsOrFontOrCallback;
|
|
next = callback;
|
|
} else {
|
|
options = { font: figDefaults.font };
|
|
next = callback;
|
|
}
|
|
const fontName = options.font || figDefaults.font;
|
|
try {
|
|
const fontOpts = await me.loadFont(fontName);
|
|
const generatedTxt = fontOpts ? generateText(fontName, _reworkFontOpts(fontOpts, options), txt) : "";
|
|
next?.(null, generatedTxt);
|
|
return generatedTxt;
|
|
} catch (err) {
|
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
if (next) {
|
|
next(error);
|
|
return "";
|
|
}
|
|
throw error;
|
|
}
|
|
};
|
|
me.textSync = function(txt, options) {
|
|
txt = txt + "";
|
|
if (typeof options === "string") {
|
|
options = { font: options };
|
|
} else {
|
|
options = options || {};
|
|
}
|
|
const fontName = options.font || figDefaults.font;
|
|
let fontOpts = _reworkFontOpts(me.loadFontSync(fontName), options);
|
|
return generateText(fontName, fontOpts, txt);
|
|
};
|
|
me.metadata = async function(fontName, callback) {
|
|
fontName = fontName + "";
|
|
try {
|
|
const fontOpts = await me.loadFont(fontName);
|
|
if (!fontOpts) {
|
|
throw new Error("Error loading font.");
|
|
}
|
|
const font = figFonts[fontName];
|
|
const result = [fontOpts, font?.comment || ""];
|
|
callback?.(null, fontOpts, font?.comment);
|
|
return result;
|
|
} catch (err) {
|
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
if (callback) {
|
|
callback(error);
|
|
return null;
|
|
}
|
|
throw error;
|
|
}
|
|
};
|
|
me.defaults = function(opts) {
|
|
if (opts && typeof opts === "object") {
|
|
Object.assign(figDefaults, opts);
|
|
}
|
|
if (typeof structuredClone !== "undefined") {
|
|
return structuredClone(figDefaults);
|
|
} else {
|
|
return JSON.parse(JSON.stringify(figDefaults));
|
|
}
|
|
};
|
|
me.parseFont = function(fontName, data, override = true) {
|
|
if (figFonts[fontName] && !override) {
|
|
return figFonts[fontName].options;
|
|
}
|
|
data = data.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
const font = new FigletFont();
|
|
const lines = data.split("\n");
|
|
const headerLine = lines.shift();
|
|
if (!headerLine) {
|
|
throw new Error("Invalid font file: missing header");
|
|
}
|
|
const headerData = headerLine.split(" ");
|
|
const opts = {
|
|
hardBlank: headerData[0].substring(5, 6),
|
|
height: parseInt(headerData[1], 10),
|
|
baseline: parseInt(headerData[2], 10),
|
|
maxLength: parseInt(headerData[3], 10),
|
|
oldLayout: parseInt(headerData[4], 10),
|
|
numCommentLines: parseInt(headerData[5], 10),
|
|
printDirection: headerData[6] ? parseInt(headerData[6], 10) : 0,
|
|
fullLayout: headerData[7] ? parseInt(headerData[7], 10) : null,
|
|
codeTagCount: headerData[8] ? parseInt(headerData[8], 10) : null
|
|
};
|
|
if (opts.hardBlank?.length !== 1 || [
|
|
opts.height,
|
|
opts.baseline,
|
|
opts.maxLength,
|
|
opts.oldLayout,
|
|
opts.numCommentLines
|
|
].some((val) => val === null || val === void 0 || isNaN(val))) {
|
|
throw new Error("FIGlet header contains invalid values.");
|
|
}
|
|
if (opts.height == null || opts.numCommentLines == null) {
|
|
throw new Error("FIGlet header contains invalid values.");
|
|
}
|
|
opts.fittingRules = getSmushingRules(opts.oldLayout, opts.fullLayout);
|
|
font.options = opts;
|
|
const charNums = [];
|
|
for (let i = 32; i <= 126; i++) {
|
|
charNums.push(i);
|
|
}
|
|
charNums.push(196, 214, 220, 228, 246, 252, 223);
|
|
if (lines.length < opts.numCommentLines + opts.height * charNums.length) {
|
|
throw new Error(
|
|
`FIGlet file is missing data. Line length: ${lines.length}. Comment lines: ${opts.numCommentLines}. Height: ${opts.height}. Num chars: ${charNums.length}.`
|
|
);
|
|
}
|
|
font.comment = lines.splice(0, opts.numCommentLines).join("\n");
|
|
font.numChars = 0;
|
|
while (lines.length > 0 && font.numChars < charNums.length) {
|
|
const cNum = charNums[font.numChars];
|
|
font[cNum] = lines.splice(0, opts.height);
|
|
for (let i = 0; i < opts.height; i++) {
|
|
if (typeof font[cNum][i] === "undefined") {
|
|
font[cNum][i] = "";
|
|
} else {
|
|
font[cNum][i] = removeEndChar(font[cNum][i], i, opts.height);
|
|
}
|
|
}
|
|
font.numChars++;
|
|
}
|
|
while (lines.length > 0) {
|
|
const cNumLine = lines.shift();
|
|
if (!cNumLine || cNumLine.trim() === "") break;
|
|
let cNum = cNumLine.split(" ")[0];
|
|
let parsedNum;
|
|
if (/^-?0[xX][0-9a-fA-F]+$/.test(cNum)) {
|
|
parsedNum = parseInt(cNum, 16);
|
|
} else if (/^-?0[0-7]+$/.test(cNum)) {
|
|
parsedNum = parseInt(cNum, 8);
|
|
} else if (/^-?[0-9]+$/.test(cNum)) {
|
|
parsedNum = parseInt(cNum, 10);
|
|
} else {
|
|
throw new Error(`Error parsing data. Invalid data: ${cNum}`);
|
|
}
|
|
if (parsedNum === -1 || parsedNum < -2147483648 || parsedNum > 2147483647) {
|
|
const msg = parsedNum === -1 ? "The char code -1 is not permitted." : `The char code cannot be ${parsedNum < -2147483648 ? "less than -2147483648" : "greater than 2147483647"}.`;
|
|
throw new Error(`Error parsing data. ${msg}`);
|
|
}
|
|
font[parsedNum] = lines.splice(0, opts.height);
|
|
for (let i = 0; i < opts.height; i++) {
|
|
if (typeof font[parsedNum][i] === "undefined") {
|
|
font[parsedNum][i] = "";
|
|
} else {
|
|
font[parsedNum][i] = removeEndChar(
|
|
font[parsedNum][i],
|
|
i,
|
|
opts.height
|
|
);
|
|
}
|
|
}
|
|
font.numChars++;
|
|
}
|
|
figFonts[fontName] = font;
|
|
return opts;
|
|
};
|
|
me.loadedFonts = () => {
|
|
return Object.keys(figFonts);
|
|
};
|
|
me.clearLoadedFonts = () => {
|
|
Object.keys(figFonts).forEach((key) => {
|
|
delete figFonts[key];
|
|
});
|
|
};
|
|
me.loadFont = async function(fontName, callback) {
|
|
if (figFonts[fontName]) {
|
|
const result = figFonts[fontName].options;
|
|
callback?.(null, result);
|
|
return Promise.resolve(result);
|
|
}
|
|
try {
|
|
if (!figDefaults.fetchFontIfMissing) {
|
|
throw new Error(`Font is not loaded: ${fontName}`);
|
|
}
|
|
const response = await fetch(`${figDefaults.fontPath}/${fontName}.flf`);
|
|
if (!response.ok) {
|
|
throw new Error(`Network response was not ok: ${response.status}`);
|
|
}
|
|
const text = await response.text();
|
|
const result = me.parseFont(fontName, text);
|
|
callback?.(null, result);
|
|
return result;
|
|
} catch (error) {
|
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
if (callback) {
|
|
callback(err);
|
|
return null;
|
|
}
|
|
throw err;
|
|
}
|
|
};
|
|
me.loadFontSync = function(name) {
|
|
if (figFonts[name]) {
|
|
return figFonts[name].options;
|
|
}
|
|
throw new Error(
|
|
"Synchronous font loading is not implemented for the browser, it will only work for fonts already loaded."
|
|
);
|
|
};
|
|
me.preloadFonts = async function(fonts, callback) {
|
|
try {
|
|
for (const name of fonts) {
|
|
const response = await fetch(`${figDefaults.fontPath}/${name}.flf`);
|
|
if (!response.ok) {
|
|
throw new Error(
|
|
`Failed to preload fonts. Error fetching font: ${name}, status code: ${response.statusText}`
|
|
);
|
|
}
|
|
const data = await response.text();
|
|
me.parseFont(name, data);
|
|
}
|
|
callback?.();
|
|
} catch (error) {
|
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
if (callback) {
|
|
callback(err);
|
|
return;
|
|
}
|
|
throw error;
|
|
}
|
|
};
|
|
me.fonts = function(callback) {
|
|
return new Promise(function(resolve, reject) {
|
|
resolve(fontList);
|
|
callback?.(null, fontList);
|
|
});
|
|
};
|
|
me.fontsSync = function() {
|
|
return fontList;
|
|
};
|
|
me.figFonts = figFonts;
|
|
return me;
|
|
})();
|
|
export {
|
|
figlet as default
|
|
};
|