Anapest Generator: a JavaScript Poem Maker
My JavaScript iambic pentameter generator is among the most popular articles on this blog. If you liked that, you’re gonna love today’s article. I decided to make an anapest generator with a rhyme! It’s a JavaScript poetry generator using an anapest, that is, a poem with anapestic meter.

(see what I did there?)
An anapest, or anapestic meter, is a metrical foot consisting of two unstressed syllables followed by a stressed one. Perhaps the most famous example of an anapestic poem (also mentioned in my article on poetry) is Lord Byron’s “The Destruction of Sennacherib”.
The Assyrian came down like the wolf on the fold,
And his cohorts were gleaming in purple and gold;
And the sheen of their spears was like stars on the sea,
When the blue wave rolls nightly on deep Galilee.Like the leaves of the forest when Summer is green,
That host with their banners at sunset were seen:
Like the leaves of the forest when Autumn hath blown,
That host on the morrow lay withered and strown.
A Simple Anapest Generator in Javascript
Without further delay, here’s what I came up with:
Perceptive observers will notice that the anapest generator is running in an iframe. As I didn’t want to mess with running JavaScript code in the blog post, the code originates from a sandbox page on the main website.
Looking for the code? Here it is, you’re welcome:
<html> | |
<head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/rita/1.3.11/rita-full.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> | |
</head> | |
<input type="button" value="Generate New" onclick="window.location.reload();"> | |
<br> | |
</header> | |
<div id="out1"></div><br> | |
<script> | |
var i=0; | |
var rhymedWord, rhymedWord2; | |
var preRhyme, preRhymeB; | |
var advS, advSB; | |
var det = " they "; | |
//creating rhymes | |
var w1 = wordChoice("vbn", 2); | |
var w1b = wordChoice("vb", 2); | |
var w2 = rhymeGen('https://api.datamuse.com/words?rel_rhy=', w1) //wordChoice("vb", 3) | |
var w2b = rhymeGen('https://api.datamuse.com/words?rel_rhy=', w1b) // wordChoice("vb", 2) | |
var syllNum = new_count(w2); | |
var syllNumB = new_count(w2b); | |
// first & second lines | |
if (w2 != undefined) { | |
rhymedWord = w2; | |
if (syllNum == 1) { | |
advS = 3; | |
det = " some "; | |
preRhyme = wordChoice("nns", advS) | |
} | |
else if (syllNum == 2) { | |
advS = 2; | |
preRhyme = RiTa.randomWord("rb", advS) | |
} | |
else if (syllNum == 3) { | |
advS = 1; | |
preRhyme = RiTa.randomWord("rb", advS); | |
} | |
else if (syllNum == 4) { | |
preRhyme = ""; | |
} | |
else { | |
advS = 1; | |
preRhyme = RiTa.randomWord("rb", advS); | |
} | |
} | |
else { | |
rhymedWord = wordChoice("vb", 3); | |
advS = 1; | |
preRhyme = RiTa.randomWord("rb", advS); | |
} | |
// third and fourth lines | |
if (w2b != undefined) { | |
rhymedWord2 = w2b; | |
if (syllNumB == 1) { | |
advSB = 2; | |
preRhymeB = wordChoice("rb", advSB) | |
} | |
else if (syllNumB == 2) { | |
advSB = 1; | |
preRhymeB = RiTa.randomWord("md", advSB) | |
} | |
else if (syllNumB == 3) { | |
advSB = 1; | |
preRhymeB = ""; | |
} | |
else { | |
advSB = 1; | |
preRhymeB = RiTa.randomWord("md", advSB); | |
} | |
} | |
else { | |
rhymedWord2 = wordChoice("vb", 2); | |
advSB = 1; | |
preRhymeB = RiTa.randomWord("md",advSB); | |
} | |
// structuring lines | |
var line1 = capitalizeFirstLetter(RiTa.randomWord("prp$",1)) + " " + wordChoice("jj",2) + " " + wordChoice("nn",3) + " " + retConjunction() + " " + wordChoice("nns",2) + " has " + w1 + ","; | |
var line2 = RiTa.randomWord("jj",1) + " " + wordChoice2("jj",3) + " " + wordChoice("nns",2) + " " + retConjunction2() + det + preRhyme + " " + rhymedWord + "."; | |
var line3 = capitalizeFirstLetter(wordChoice("jj",3)) + " " + RiTa.randomWord("jj",1) + " " + wordChoice("nn",2) + " " + retConjunction() + " " + wordChoice("nns",2) + " " + RiTa.randomWord ("md", 1) + " " + w1b + ","; | |
var line4 = RiTa.randomWord("prp$",1) + " " + wordChoice("jj",2) + " " + RiTa.randomWord("jj", 1) + " " + wordChoice("nn",2) + " " + retConjunction2() + " " + wordChoice("nns",2) + " " + preRhymeB + " " + rhymedWord2 + "."; | |
$('#out1').append(line1+"<br/>"+line2+"<br/>"+line3+"<br/>"+line4+"<br/>"+"<br/>"); | |
// word picking functions for stress detection | |
function wordChoice(pos, syl) { | |
var word = RiTa.randomWord(pos, syl); | |
if ((RiTa.getStresses(word) == "0/1") || (RiTa.getStresses(word) == "0/0/1")) { | |
return (word); | |
} | |
else { | |
return (wordChoice(pos, syl)); | |
} | |
} | |
function wordChoice2(pos, syl) { | |
var word = RiTa.randomWord(pos, syl); | |
if (RiTa.getStresses(word) == "0/1/0") { | |
return (word); | |
} | |
else { | |
return (wordChoice2(pos, syl)); | |
} | |
} | |
function wordChoice3(pos, syl) { | |
var word = RiTa.randomWord(pos, syl); | |
if (RiTa.getStresses(word) == "1/0/0") { | |
return (word); | |
} | |
else { | |
return (wordChoice3(pos, syl)); | |
} | |
} | |
//capitalize first letter | |
function capitalizeFirstLetter(string) { | |
return string.charAt(0).toUpperCase() + string.slice(1); | |
} | |
// counts syllables | |
function new_count(word) { | |
word = word.toLowerCase(); //word.downcase! | |
if(word.length <= 3) { return 1; } //return 1 if word.length <= 3 | |
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, ''); //word.sub!(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '') | |
word = word.replace(/^y/, ''); //word.sub!(/^y/, '') | |
return word.match(/[aeiouy]{1,2}/g).length; //word.scan(/[aeiouy]{1,2}/).size | |
} | |
function rhymeGen(urlAdd2, sWord){ | |
var dmuseQuery2 = dataMUSE(urlAdd2 + sWord); | |
var aIndex2 = dmuseQuery2.length; | |
var rnd2 = Math.floor((Math.random() * aIndex2) + 1); | |
var dmuseWord2 = dmuseQuery2[rnd2]; | |
return dmuseWord2; | |
} | |
function dataMUSE (myURL) { | |
var json = (function () { | |
var json = null; | |
$.ajax({ | |
'async': false, | |
'global': false, | |
'url': myURL, | |
'dataType': "json", | |
'success': function (data) { | |
json = data; | |
} | |
}); | |
return json; | |
})(); | |
var amb2_proto = JSON.stringify(json); | |
var amb2_proto2 = amb2_proto.replace(/[.,\/#!?'"$%\^&\*;:{}\[\]=\-_`~()]/g,""); | |
var amb2_proto3 = amb2_proto2.replace(/word/g , " "); | |
var amb2_proto4 = amb2_proto3.replace(/score/g, " "); | |
var amb2_proto5 = amb2_proto4.replace(/[0-9]/g, " "); | |
var amb2_proto5b = amb2_proto5.replace(/numSyllables/g, " "); | |
var amb2_proto6 = amb2_proto5b.replace(/\s+/g,' ').trim(); | |
var amb2 = amb2_proto6.split(" "); | |
return amb2; | |
} | |
function retConjunction() { | |
var conjs = ["with", "near", "for"]; | |
var inde = Math.floor(Math.random() * (2 - 0 + 1) ) + 0; | |
return conjs[inde]; | |
} | |
function retConjunction2() { | |
var conjs = ["as", "while", "soon", "then", "which", "how"]; | |
var inde = Math.floor(Math.random() * (5 - 0 + 1) ) + 0; | |
return conjs[inde]; | |
} | |
</script> | |
</body> | |
</html> |
You will need the RiTa library for this to work. It also implements the Datamuse API (which means, if the Datamuse server is slow, this page will be slow as well; it’s out of my control). You will also need a bit of patience to get through my ridiculously redundant, ugly code (I got too bored to clean it up; finding the rhymes could be done with a function returning a string array).
Anapestic Poetry Generator: Next Steps
As with my iambic pentameter maker, this is really, really “alpha”. I’d like to work on it some more, if I only find the time. My main focus would be an attempt to improve semantic coherence.
I’ve also noticed that sometimes the generator draws a blank (not verse!). If that happens, pressing “Generate New” should resolve the issue.
Mansion Escape – a Text Adventure App for Android
There’s also the same issue as with the iambic pentameter generator, namely, that the library I’m using to detect syllable stress isn’t 100% correct. If you came up with an improved version, feel free to share it!
Where Are the Social Buttons?
There aren't any, because I don't want to advertise companies which I loathe. Besides, I consider my readers smart enough to know how to copy the link and share it anywhere they'd like.