commit 001e26b7497c2ad35770e162656bdca46bb96ef5
parent a0399f95f80379b6954e7715b12051325e3b30b1
Author: Kyle Barlow <kb@kylebarlow.com>
Date: Mon, 17 Aug 2026 20:07:20 -0700
Stories changed to human made public domain stories
Diffstat:
4 files changed, 462 insertions(+), 40 deletions(-)
diff --git a/games/work/index.html b/games/work/index.html
@@ -42,6 +42,19 @@
user-select: none;
}
#audio-controls button:hover { background: rgba(0,0,0,0.1); color: #112; }
+ #story-credits {
+ flex-shrink: 0;
+ padding: 0.4rem 1.25rem 0.6rem;
+ font-size: 0.72rem;
+ line-height: 1.35;
+ color: #8a8a97;
+ text-align: center;
+ max-height: 4.6rem;
+ overflow-y: auto;
+ }
+ #story-credits a { color: #667; text-decoration: underline; }
+ #story-credits a:hover { color: #1D7CF2; }
+ #story-credits strong { font-weight: 600; color: #778; }
#audio-controls button.muted { color: #aab; border-color: rgba(0,0,0,0.07); }
</style>
</head>
@@ -51,12 +64,40 @@
<button id="btn-sfx">Sound: ON</button>
</div>
<div id="game-container"></div>
+ <footer id="story-credits">
+ <strong>For grown-ups:</strong> every fill-in-the-blank tale in Stories mode is adapted from a
+ public-domain children’s classic. Tap a title to read the original on
+ <a href="https://www.gutenberg.org/" target="_blank" rel="noopener">Project Gutenberg</a>.
+ <span id="story-credits-list"></span>
+ </footer>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.80.1/dist/phaser.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tone@14.7.77/build/Tone.js"></script>
<script src="../../js/shared/game-shared.js"></script>
<script src="lib.js"></script>
<script src="game.js"></script>
<script src="../../js/shared/touch-controls.js"></script>
+ <script>
+ // Build the parent credits list straight from the story data so the two
+ // can never drift apart.
+ (function () {
+ const el = document.getElementById('story-credits-list');
+ if (!el || !window.WorkLib) return;
+ const seen = new Set();
+ const parts = [];
+ WorkLib.MADLIB_TEMPLATES.forEach(function (t) {
+ const src = t.source;
+ if (!src || seen.has(src.title)) return;
+ seen.add(src.title);
+ const a = document.createElement('a');
+ a.href = src.url;
+ a.target = '_blank';
+ a.rel = 'noopener';
+ a.textContent = src.title;
+ parts.push(a.outerHTML + ' by ' + src.author);
+ });
+ el.innerHTML = '<br>' + parts.join(' · ') + '.';
+ }());
+ </script>
<script>KGames.initTouchControls({ layout: 'text' });</script>
</body>
</html>
diff --git a/games/work/lib.js b/games/work/lib.js
@@ -2,64 +2,426 @@
'use strict';
// ── Mad Libs templates ──────────────────────────────────────────────────────
- // Kid-friendly category labels only (never "noun/verb/adjective").
+ // Every story is adapted from a public-domain children’s classic (see the
+ // `source` field — surfaced to parents in the page footer). Kid-friendly
+ // category labels only (never "noun/verb/adjective").
// `story` uses {key} placeholders matching each blank's `key`.
const MADLIB_TEMPLATES = [
{
- id: 'zoo',
- title: 'A Day at the Zoo',
+ id: 'peter-rabbit',
+ title: 'The Tale of Peter Rabbit',
+ source: {
+ title: 'The Tale of Peter Rabbit',
+ author: 'Beatrix Potter',
+ url: 'https://www.gutenberg.org/ebooks/14838',
+ },
blanks: [
- { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
- { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
- { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
- { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
- { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
],
- story: 'One day, {name} went to the zoo and saw a {color} {animal}. ' +
- 'It was eating {food}! When it saw {name}, the {animal} said "{silly}!" ' +
- 'and did a happy dance. It was the best day ever.',
+ story: 'Once upon a time there were four little rabbits, and the naughtiest one was named {name}. ' +
+ 'Mother said, "Do not go into Mr. McGregor’s garden!" But {name} squeezed under the gate ' +
+ 'and ate some {food} until his tummy felt funny. Then Mr. McGregor came running, waving a rake! ' +
+ '{name} lost one {color} shoe among the cabbages and hid in a watering can with a little {animal}. ' +
+ 'He sneezed "{silly}!" and ran all the way home to bed.',
},
{
- id: 'space',
- title: 'Blast Off!',
+ id: 'three-pigs',
+ title: 'The Three Little Pigs',
+ source: {
+ title: 'The Story of the Three Little Pigs (English Fairy Tales)',
+ author: 'Joseph Jacobs',
+ url: 'https://www.gutenberg.org/ebooks/7439',
+ },
blanks: [
- { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
- { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
- { key: 'place', label: 'Tell me a place!', voice: 'Tell me a place!' },
- { key: 'number', label: 'Tell me a number!', voice: 'Tell me a number!' },
- { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'stuff', label: 'Tell me something you can build with!', voice: 'Tell me something you can build with!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
],
- story: 'Captain {name} flew a rocket all the way to {place}. ' +
- 'On board was a brave {animal} and {number} jellybeans. ' +
- 'When they landed, everyone shouted "{silly}!" and bounced around in space.',
+ story: 'There were three little pigs, and the cleverest one was named {name}. ' +
+ 'The first built a house of straw, the second a house of sticks, but {name} built a strong house of {stuff}. ' +
+ 'Along came the wolf and called, "Little pig, little pig, let me come in!" ' +
+ '"Not by the hair of my chinny chin chin!" said {name}. ' +
+ 'So the wolf huffed, and puffed, and shouted "{silly}!" — but the house of {stuff} would not fall down. ' +
+ 'The wolf ran away, and {name} had {food} for supper.',
},
{
- id: 'party',
- title: 'The Silly Party',
+ id: 'three-bears',
+ title: 'The Story of the Three Bears',
+ source: {
+ title: 'The Story of the Three Bears (English Fairy Tales)',
+ author: 'Joseph Jacobs',
+ url: 'https://www.gutenberg.org/ebooks/7439',
+ },
blanks: [
- { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
- { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
- { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
- { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
- { key: 'action', label: 'Tell me something you can do!', voice: 'Tell me something you can do!' },
+ { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'action', label: 'Tell me something you can do!', voice: 'Tell me something you can do!' },
],
- story: '{name} had a party with a giant {color} cake made of {food}. ' +
- 'A friendly {animal} came too, and everybody started to {action}! ' +
- 'It was the silliest party in the whole world.',
+ story: 'Three bears lived in a little house in the wood, and each one had a bowl of {food}. ' +
+ 'While it cooled, a girl named {name} walked right in. ' +
+ 'She tasted the great big bowl — too hot! The middle bowl — too cold! ' +
+ 'The teeny tiny bowl was just right, so she ate it all up. ' +
+ 'Then she sat in the teeny tiny chair until it went CRASH, and fell fast asleep upstairs. ' +
+ 'When the bears came home the teeny tiny bear squeaked, "Somebody has been eating my {food}!" ' +
+ '{name} woke up, saw a {animal} peeking through the window, and began to {action} all the way home.',
},
{
- id: 'breakfast',
- title: 'Funny Breakfast',
+ id: 'lion-mouse',
+ title: 'The Lion and the Mouse',
+ source: {
+ title: 'The Lion and the Mouse (The Fables of Æsop)',
+ author: 'Æsop, told anew by Joseph Jacobs',
+ url: 'https://www.gutenberg.org/ebooks/28',
+ },
blanks: [
- { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
- { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
- { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
- { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'place', label: 'Tell me a place!', voice: 'Tell me a place!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
],
- story: 'This morning {name} ate {food} for breakfast. ' +
- 'Then a sleepy {animal} hopped onto the table and yelled "{silly}!" ' +
- 'It wanted breakfast too, so {name} shared. Yum yum!',
+ story: 'A lion was fast asleep in {place} when a little mouse named {name} ran right across his nose. ' +
+ 'The lion woke with a roar and caught the mouse in his big paw. ' +
+ '"Please let me go," said {name}, "and one day I will help you!" ' +
+ 'The lion laughed "{silly}!" and let the mouse go. ' +
+ 'Not long after, hunters tied the lion up with ropes — and tiny {name} nibbled every rope through. ' +
+ 'Even a little friend can be a big help.',
+ },
+ {
+ id: 'hare-tortoise',
+ title: 'The Hare and the Tortoise',
+ source: {
+ title: 'The Hare and the Tortoise (The Fables of Æsop)',
+ author: 'Æsop, told anew by Joseph Jacobs',
+ url: 'https://www.gutenberg.org/ebooks/28',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'place', label: 'Tell me a place!', voice: 'Tell me a place!' },
+ { key: 'number', label: 'Tell me a number!', voice: 'Tell me a number!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ ],
+ story: 'A hare was bragging how fast he could run, so a slow tortoise named {name} said, ' +
+ '"I will race you all the way to {place}!" The hare laughed and zoomed ahead. ' +
+ 'He was so far in front that he stopped for a nap and {number} bites of {food}. ' +
+ 'Plod, plod, plod went {name}, never stopping once. ' +
+ 'When the hare woke up and ran his fastest, {name} was already there. Slow and steady wins the race!',
+ },
+ {
+ id: 'town-country-mouse',
+ title: 'The Town Mouse and the Country Mouse',
+ source: {
+ title: 'The Town Mouse and the Country Mouse (The Fables of Æsop)',
+ author: 'Æsop, told anew by Joseph Jacobs',
+ url: 'https://www.gutenberg.org/ebooks/28',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'A town mouse named {name} came to visit a country mouse, who gave him beans and crusts for dinner. ' +
+ '"Come to my house in town," said {name}, "and you shall have {food} instead!" ' +
+ 'So off they went, and the table in town was piled high. ' +
+ 'But just as they began to nibble, a big {animal} came in and they had to squeak "{silly}!" and hide in a hole. ' +
+ 'The country mouse said, "I would rather have beans in peace than {food} in fright," and went home.',
+ },
+ {
+ id: 'ugly-duckling',
+ title: 'The Ugly Duckling',
+ source: {
+ title: 'The Ugly Duckling (Andersen’s Fairy Tales)',
+ author: 'Hans Christian Andersen',
+ url: 'https://www.gutenberg.org/ebooks/1597',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'Down by the water, a mother duck’s eggs went crack, crack, crack. ' +
+ 'Out came the ducklings — and the very last one was big and {color}, so everyone called him {name}. ' +
+ '"You look funny!" said the other birds, and poor {name} waddled away all by himself. ' +
+ 'He was cold all winter, with only a little {food} to eat. ' +
+ 'But in the spring he looked into the water and said "{silly}!" — ' +
+ 'for he was not a duckling at all. He had grown into a beautiful swan.',
+ },
+ {
+ id: 'emperors-clothes',
+ title: 'The Emperor’s New Clothes',
+ source: {
+ title: 'The Emperor’s New Clothes (Andersen’s Fairy Tales)',
+ author: 'Hans Christian Andersen',
+ url: 'https://www.gutenberg.org/ebooks/1597',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'There was an emperor who loved new clothes more than anything. ' +
+ 'Two tricky tailors said they could sew him a {color} suit so magic that only clever people could see it. ' +
+ 'They sewed with nothing at all! But nobody wanted to look silly, so everyone said, "How fine!" ' +
+ 'The emperor marched down the street in his underwear, with a {animal} following behind. ' +
+ 'Then a little kid named {name} shouted, "{silly}! He has no clothes on!" ' +
+ 'And everybody laughed, because it was true.',
+ },
+ {
+ id: 'elves-shoemaker',
+ title: 'The Elves and the Shoemaker',
+ source: {
+ title: 'The Elves and the Shoemaker (Grimms’ Fairy Tales)',
+ author: 'Jacob and Wilhelm Grimm',
+ url: 'https://www.gutenberg.org/ebooks/2591',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'number', label: 'Tell me a number!', voice: 'Tell me a number!' },
+ { key: 'action', label: 'Tell me something you can do!', voice: 'Tell me something you can do!' },
+ ],
+ story: 'A shoemaker named {name} had only enough leather left for one pair of shoes, ' +
+ 'so {name} cut it out and went to bed. ' +
+ 'In the morning — surprise! — the shoes were already finished, and they were {color} and perfect. ' +
+ 'This happened again and again, until {name} peeked and saw {number} tiny elves ' +
+ 'hop onto the table and {action} all night long. ' +
+ 'So {name} sewed them tiny coats to say thank you, and the elves danced right out the door.',
+ },
+ {
+ id: 'bremen-musicians',
+ title: 'The Bremen Town Musicians',
+ source: {
+ title: 'The Bremen Town Musicians (Grimms’ Fairy Tales)',
+ author: 'Jacob and Wilhelm Grimm',
+ url: 'https://www.gutenberg.org/ebooks/2591',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'place', label: 'Tell me a place!', voice: 'Tell me a place!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'An old donkey named {name} set off to be a musician in {place}. ' +
+ 'Along the way a dog, a cat, a rooster, and even a {animal} came too. ' +
+ 'When night fell they found a little house full of robbers, so they stood one on top of the other ' +
+ 'and sang their song: hee-haw, woof, meow, cock-a-doodle-doo, "{silly}!" ' +
+ 'The robbers ran away as fast as they could, and the four friends slept there happily ever after.',
+ },
+ {
+ id: 'frog-prince',
+ title: 'The Frog Prince',
+ source: {
+ title: 'The Frog Prince (Grimms’ Fairy Tales)',
+ author: 'Jacob and Wilhelm Grimm',
+ url: 'https://www.gutenberg.org/ebooks/2591',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'A princess named {name} was playing with a {color} golden ball when — plop! — it fell into the well. ' +
+ '"I will fetch it," said a frog, "if you let me eat {food} from your little plate." ' +
+ '{name} said yes, and the frog dived down and brought the ball back up. ' +
+ 'That night the frog knocked at the palace door: tap, tap, "{silly}!" ' +
+ 'A promise is a promise, so {name} let him in — and in the morning the frog was a prince.',
+ },
+ {
+ id: 'jack-beanstalk',
+ title: 'Jack and the Beanstalk',
+ source: {
+ title: 'Jack and the Beanstalk (English Fairy Tales)',
+ author: 'Joseph Jacobs',
+ url: 'https://www.gutenberg.org/ebooks/7439',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'number', label: 'Tell me a number!', voice: 'Tell me a number!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ ],
+ story: 'A boy named {name} traded the family cow for {number} magic beans. ' +
+ 'His mother tossed them out the window — and by morning a beanstalk had grown up past the clouds! ' +
+ '{name} climbed and climbed, all the way to a giant’s castle in the sky. ' +
+ 'The giant roared, "Fee-fi-fo-fum!" but he was busy eating {food}, ' +
+ 'so {name} grabbed the hen that laid golden eggs and a {animal} that could sing. ' +
+ 'Down the beanstalk he scrambled, chop-chop, and he and his mother were never hungry again.',
+ },
+ {
+ id: 'red-riding-hood',
+ title: 'Little Red Riding Hood',
+ source: {
+ title: 'Little Red Riding Hood (English Fairy Tales)',
+ author: 'Flora Annie Steel',
+ url: 'https://www.gutenberg.org/ebooks/17034',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'A little girl named {name} had a {color} hooded cape, so everyone called her Little {color} Riding Hood. ' +
+ 'One morning she carried a basket of {food} through the wood to her grandmother’s house. ' +
+ 'A sly wolf hurried on ahead and hopped into Grandmother’s bed. ' +
+ '"What big eyes you have!" said {name}. "What big ears you have!" ' +
+ 'Then the woodcutter came in shouting "{silly}!" and the wolf ran off into the trees. ' +
+ 'Grandmother came out of the closet, and they all shared the {food}.',
+ },
+ {
+ id: 'elephants-child',
+ title: 'The Elephant’s Child',
+ source: {
+ title: 'The Elephant’s Child (Just So Stories)',
+ author: 'Rudyard Kipling',
+ url: 'https://www.gutenberg.org/ebooks/2781',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'place', label: 'Tell me a place!', voice: 'Tell me a place!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'In the long ago, elephants had no trunks at all — only a little squashy nose. ' +
+ 'But one baby elephant named {name} was full of questions, like ' +
+ '"What does the crocodile have for dinner?" ' +
+ 'So {name} went all the way to {place} to find out, and the crocodile grabbed that little nose and PULLED. ' +
+ '{name} pulled back, and pulled, and hollered "{silly}!" — ' +
+ 'and when the crocodile let go, the nose had stretched into a long, useful trunk. ' +
+ 'Now {name} could pick {food} right off the tallest tree.',
+ },
+ {
+ id: 'camel-hump',
+ title: 'How the Camel Got His Hump',
+ source: {
+ title: 'How the Camel Got His Hump (Just So Stories)',
+ author: 'Rudyard Kipling',
+ url: 'https://www.gutenberg.org/ebooks/2781',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'action', label: 'Tell me something you can do!', voice: 'Tell me something you can do!' },
+ { key: 'number', label: 'Tell me a number!', voice: 'Tell me a number!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'At the beginning of the world, a lazy camel named {name} lived in the middle of the desert. ' +
+ 'The horse said, "Come and {action} with us!" The dog said it too, and the ox said it too. ' +
+ 'But {name} only answered, "{silly}!" and would not work at all. ' +
+ 'So the Djinn of the desert came along and gave {name} a great big humph — I mean, hump — ' +
+ 'right on his back. Now {name} can work {number} whole days without stopping for dinner, ' +
+ 'and camels have had humps ever since.',
+ },
+ {
+ id: 'wizard-of-oz',
+ title: 'The Wonderful Wizard of Oz',
+ source: {
+ title: 'The Wonderful Wizard of Oz',
+ author: 'L. Frank Baum',
+ url: 'https://www.gutenberg.org/ebooks/55',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'action', label: 'Tell me something you can do!', voice: 'Tell me something you can do!' },
+ ],
+ story: 'A cyclone picked up a little house with {name} and a small dog inside, and set it down in the land of Oz. ' +
+ '"We are not in Kansas any more!" said {name}. ' +
+ 'To get home, {name} followed the road of yellow brick, ' +
+ 'and along the way met a scarecrow, a tin woodman, a lion, and a friendly {animal}. ' +
+ 'In the {color} City the great wizard turned out to be an ordinary man behind a curtain, ' +
+ 'but he could still {action}, and the silver shoes carried {name} all the way home.',
+ },
+ {
+ id: 'alice-rabbit-hole',
+ title: 'Alice Down the Rabbit Hole',
+ source: {
+ title: 'Alice’s Adventures in Wonderland',
+ author: 'Lewis Carroll',
+ url: 'https://www.gutenberg.org/ebooks/11',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'A girl named {name} saw a white rabbit run past, saying, "Oh dear! I shall be late!" ' +
+ 'Down the rabbit hole she went, tumbling and tumbling. ' +
+ 'At the bottom she found a little bottle marked DRINK ME and grew very small, ' +
+ 'then a bit of {food} marked EAT ME and grew very TALL. ' +
+ 'A grinning {animal} showed her the way to a tea party where everyone shouted "{silly}!" ' +
+ 'and passed the cups around. What a curious dream {name} had that day.',
+ },
+ {
+ id: 'velveteen-rabbit',
+ title: 'The Velveteen Rabbit',
+ source: {
+ title: 'The Velveteen Rabbit',
+ author: 'Margery Williams Bianco',
+ url: 'https://www.gutenberg.org/ebooks/11757',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'place', label: 'Tell me a place!', voice: 'Tell me a place!' },
+ { key: 'action', label: 'Tell me something you can do!', voice: 'Tell me something you can do!' },
+ ],
+ story: 'On Christmas morning a boy named {name} found a {color} velveteen rabbit in his stocking. ' +
+ 'The old rocking horse said, "When a child loves you for a long, long time, you become Real." ' +
+ '{name} took the rabbit everywhere — even to {place} — and hugged him until his fur was rubbed away. ' +
+ '"Am I Real yet?" asked the rabbit. ' +
+ 'Then one spring day a fairy kissed him, and the rabbit found he could hop and {action} ' +
+ 'with all the wild rabbits. He was Real at last.',
+ },
+ {
+ id: 'tom-kitten',
+ title: 'The Tale of Tom Kitten',
+ source: {
+ title: 'The Tale of Tom Kitten',
+ author: 'Beatrix Potter',
+ url: 'https://www.gutenberg.org/ebooks/14837',
+ },
+ blanks: [
+ { key: 'name', label: 'Tell me a friend’s name!', voice: 'Tell me a friend’s name!' },
+ { key: 'color', label: 'Tell me a color!', voice: 'Tell me a color!' },
+ { key: 'food', label: 'Tell me a yummy food!', voice: 'Tell me a yummy food!' },
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ ],
+ story: 'Mrs. Tabitha Twitchit had three kittens, and the naughtiest was named {name}. ' +
+ 'Company was coming for {food}, so she scrubbed their faces and dressed them in {color} clothes. ' +
+ '"Now keep clean!" she said, and put them out in the garden. ' +
+ 'Of course {name} climbed the wall straightaway, and all the buttons popped off — pop, pop, pop. ' +
+ 'A passing {animal} tried the clothes on and found them a very good fit. ' +
+ 'And that is why the kittens had to stay upstairs when the company came.',
+ },
+ {
+ id: 'mother-goose',
+ title: 'Hey Diddle Diddle',
+ source: {
+ title: 'Hey Diddle Diddle (The Real Mother Goose)',
+ author: 'compiled by Blanche Fisher Wright',
+ url: 'https://www.gutenberg.org/ebooks/10607',
+ },
+ blanks: [
+ { key: 'animal', label: 'Tell me an animal!', voice: 'Tell me an animal!' },
+ { key: 'place', label: 'Tell me a place!', voice: 'Tell me a place!' },
+ { key: 'name', label: 'Tell me your name!', voice: 'Tell me your name!' },
+ { key: 'silly', label: 'Tell me a silly word!', voice: 'Tell me a silly word!' },
+ ],
+ story: 'Hey diddle diddle, the {animal} and the fiddle, ' +
+ 'the cow jumped over {place}! ' +
+ 'The little dog laughed to see such fun, and shouted "{silly}!" ' +
+ 'And the dish ran away with the spoon — and with {name}, too.',
},
];
diff --git a/tests/browser/runner.js b/tests/browser/runner.js
@@ -186,6 +186,16 @@ async function main() {
if (!canvas) throw new Error('No canvas element');
});
+ await test('work: story credits link to public-domain sources', async (page, url) => {
+ await page.goto(`${url}/games/work/`, { waitUntil: 'domcontentloaded' });
+ await page.waitForTimeout(500);
+ const hrefs = await page.$$eval('#story-credits a', (as) => as.map(a => a.getAttribute('href')));
+ if (!hrefs.length) throw new Error('No source links in #story-credits');
+ if (!hrefs.every(h => /^https:\/\/www\.gutenberg\.org\//.test(h))) {
+ throw new Error('Credit links must point at Project Gutenberg: ' + hrefs.join(', '));
+ }
+ });
+
await test('work: canvas renders multiple colors', async (page, url) => {
await page.goto(`${url}/games/work/`, { waitUntil: 'domcontentloaded' });
await page.waitForTimeout(1500);
diff --git a/tests/unit/work-lib.test.js b/tests/unit/work-lib.test.js
@@ -61,3 +61,12 @@ test('pickTemplate returns a real template', () => {
const t = lib.pickTemplate(() => 0);
assert.equal(t, lib.MADLIB_TEMPLATES[0]);
});
+
+test('every mad lib cites a public-domain source with author and link', () => {
+ lib.MADLIB_TEMPLATES.forEach((tpl) => {
+ assert.ok(tpl.source, `${tpl.id}: missing source`);
+ assert.ok(tpl.source.title && tpl.source.title.length > 3, `${tpl.id}: source needs a title`);
+ assert.ok(tpl.source.author && tpl.source.author.length > 2, `${tpl.id}: source needs an author`);
+ assert.match(tpl.source.url, /^https:\/\/www\.gutenberg\.org\//, `${tpl.id}: source needs a public link`);
+ });
+});