The npm cowsay package supports loading custom .cow files from any path,
not just the built-in ones. This lets you create modified versions with
configurable features like dynamic eyes.
Looking at the cowsay source code in lib/cows.js:
if (cow.match(/\\/) || cow.match(/\//)) {
filePath = cow; // Use as full path if contains slash
} else {
filePath = path.join(__dirname, "/../cows", cow) + ".cow";
}Key insight: If the f option contains a / or \, cowsay treats it as
a file path instead of looking in node_modules/cowsay/cows/.
________________________
< Wa-pa-pa-pa-pa-pa-pow! >
------------------------
\
\
/\ /\ Todd Vargo
//\_//\ ____
\_ _/ / /
/ * * \ /^^^]
\_\O/_/ [ ]
/ \_ [ /
\ \_ / /
[ [ / \/ _/
_[ [ \ /_/
________
< Zzz... >
--------
\
\
/\ /\ Todd Vargo
//\_//\ ____
\_ _/ / /
/ - - \ /^^^]
\_\O/_/ [ ]
/ \_ [ /
\ \_ / /
[ [ / \/ _/
_[ [ \ /_/
Copy the original and replace hardcoded eyes with $eyes:
# new-cows/fox.cow
$the_cow = <<EOC;
$thoughts
$thoughts
/\ /\ Todd Vargo
//\\_//\\ ____
\_ _/ / /
/ $eyes \ /^^^]
\_\O/_/ [ ]
/ \_ [ /
\ \_ / /
[ [ / \/ _/
_[ [ \ /_/
EOC
import * as cowsay from "cowsay";
// Load custom cow file (path must contain a slash)
// Set eyes with the 'e' option
console.log(
cowsay.say({
text: "Hello!",
f: "./new-cows/fox.cow",
e: "* *",
}),
);const hour = new Date().getHours();
const isSleeping = hour >= 7 && hour < 19;
const text = isSleeping ? "Zzz..." : "What does the fox say?";
const eyes = isSleeping ? "- -" : "* *";
console.log(
cowsay.say({
text: text,
f: "./new-cows/fox.cow",
e: eyes,
}),
);| Variable | Description | Example |
|---|---|---|
$thoughts |
Speech bubble connector | \ or o |
$eyes |
Two-character eye string | oo, **, ^^ |
$tongue |
Tongue string | U |
- cowsay npm package
- Original fox ASCII art by Todd Vargo