ref: 5518b554dd7848acd7839e1de01cfa485ba32bd8
dir: /kaios/apppage.pl/
#!/usr/bin/perl use strict; use warnings; @ARGV == 2 or die "usage: apppage.pl <name> <displayname>"; my ($name, $displayname) = @ARGV; my $prefs = ""; if ($name eq 'guess') { $prefs = <<EOF show-labels=true EOF } print <<EOF; <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ASCII" /> <meta name="theme-color" content="rgb(50,50,50)" /> <title>${displayname}</title> <!-- The KaiAds scripts are only present in Kai Store versions. --> <script src="kaiads.v5.min.js"></script> <script defer type="text/javascript" src="${name}.js"></script> <script defer type="text/javascript" src="kaiads-glue.js"></script> <!-- Override some defaults for small screens --> <script id="environment" type="application/json"> { "PATTERN_DEFAULT": "10x10", "PUZZLES_ALLOW_CUSTOM": false, "PUZZLES_SHOW_CURSOR": true } </script> <script class="preferences" type="text/plain"> $prefs</script> <style class="text/css"> body { margin: 0; display: flex; position: fixed; width: 100%; top: 0; bottom: 30px; font-family: "Open Sans", sans-serif; font-size: 17px; } /* Top-level form for the game menu */ #gamemenu { /* Add a little mild text formatting */ font-weight: bold; font-size: 14px; } /* Inside that form, the main menu bar and every submenu inside it is a <ul> */ #gamemenu ul { list-style: none; /* get rid of the normal unordered-list bullets */ display: flex; margin: 0; /* Compensate for the negative margins on menu items by adding a * little bit of padding so that the borders of the items don't protrude * beyond the menu. */ padding: 0.5px; /* Switch to vertical stacking, for drop-down submenus */ flex-direction: column; /* We must specify an explicit background colour for submenus, because * they must be opaque (don't want other page contents showing through * them). */ background: white; } /* Individual menu items are <li> elements within such a <ul> */ #gamemenu li { /* Suppress the text-selection I-beam pointer */ cursor: default; /* Surround each menu item with a border. */ border: 1px solid rgb(180,180,180); /* Arrange that the borders of each item overlap the ones next to it. */ margin: -0.5px; } #gamemenu ul li[role=separator] { color: transparent; border: 0; } /* The interactive contents of menu items are their child elements. */ #gamemenu li > * { padding: 0.2em 0.75em; margin: 0; display: block; } #gamemenu :disabled { /* Grey out disabled buttons */ color: rgba(0,0,0,0.5); } /* #gamemenu li > :hover:not(:disabled), */ #gamemenu li > .focus-within { /* When the mouse is over a menu item, highlight it */ background-color: rgba(0,0,0,0.3); } .transient { /* When they are displayed, they are positioned immediately above * their parent <li>, and with the left edge aligning */ position: fixed; bottom: 30px; max-height: calc(100vh - 30px); left: 100%; transition: left 0.1s; box-sizing: border-box; width: 100vw; overflow: auto; /* And make sure they appear in front. */ z-index: 50; } .transient.focus-within { /* Once a menu is actually focussed, bring it on screen. */ left: 0; /* Hiding what's behind. */ box-shadow: 0 0 1em 0 rgba(0, 0, 0, 0.8); } /* #gamemenu :hover > ul, */ #gamemenu .focus-within > ul { /* Last but by no means least, the all-important line that makes * submenus be displayed! Any <ul> whose parent <li> is being * hovered over gets display:flex overriding the display:none * from above. */ display: flex; } #gamemenu button { /* Menu items that trigger an action. We put some effort into * removing the default button styling. */ -moz-appearance: none; -webkit-appearance: none; appearance: none; font: inherit; color: inherit; background: initial; border: initial; border-radius: initial; text-align: inherit; width: 100%; } #gamemenu .tick { /* The tick at the start of a menu item, or its unselected equivalent. * This is represented by an <input type="radio">, so we put some * effort into overriding the default style. */ -moz-appearance: none; -webkit-appearance: none; appearance: none; margin: initial; font: inherit; } #gamemenu .tick::before { content: "\\2713"; } #gamemenu .tick:not(:checked) { /* Tick for an unselected menu entry. */ color: transparent; } #gamemenu li > div::after { content: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='10'%20height='10'%3E%3Cpolygon%20points='0,0,10,5,0,10'/%3E%3C/svg%3E"); float: right; } #puzzle { background: var(--puzzle-background, #e6e6e6); flex: 1 1 auto; flex-direction: column; align-items: center; display: flex; width: 100% } #statusbar { overflow: hidden; text-align: left; white-space: nowrap; text-overflow: ellipsis; line-height: 1; background: #d8d8d8; border-left: 2px solid #c8c8c8; border-top: 2px solid #c8c8c8; border-right: 2px solid #e8e8e8; border-bottom: 2px solid #e8e8e8; height: 1em; } #dlgdimmer { width: 100%; height: 100%; background: #000000; position: fixed; opacity: 0.3; left: 0; top: 0; z-index: 99; } #dlgform { width: 66.6667vw; opacity: 1; background: #ffffff; color: #000000; position: absolute; border: 2px solid black; padding: 20px; top: 10vh; left: 16.6667vw; z-index: 100; } #dlgform h2 { margin-top: 0px; } #puzzlecanvascontain { flex: 1 1 auto; display: flex; justify-content: center; align-items: center; min-width: 0; min-height: 0; } #puzzlecanvas { max-width: 100%; max-height: 100%; background-color: white; font-weight: 600; } #puzzlecanvas:focus { /* The focus will be here iff there's nothing else on * screen that can be focused, so the outline is * redundant. */ outline: none; } #puzzle > div { width: 100%; } .softkey { position: fixed; left: 0; right: 0; bottom: 0; height: 30px; font-weight: 600; font-size: 14px; line-height: 1; white-space: nowrap; background: rgb(50,50,50); color: white; z-index: 150; } :not(.focus-within) > .softkey { display: none; } .softkey > * { position: absolute; padding: 8px; } .lsk { left: 0; right: 70%; text-align: left; padding-right: 0; } .csk { left: 30%; right: 30%; text-align: center; text-transform: uppercase; padding-left: 0; padding-right: 0; } .rsk { right: 0; left: 70%; text-align: right; padding-left: 0 } </style> </head> <body> <div id="puzzle"> <div id="puzzlecanvascontain"> <canvas id="puzzlecanvas" width="1px" height="1px" tabindex="0"> </canvas> </div> <div id="statusbar"> </div> <div class="softkey"> <div class="lsk"></div><div class="csk"></div> <div class="rsk">Menu</div></div> </div> <form id="gamemenu" class="transient"> <ul> <!-- <li><div tabindex="0">Game<ul class="transient"> <li><button type="button" id="specific">Enter game ID...</button></li> <li><button type="button" id="random">Enter random seed...</button></li> <li><button type="button" id="save">Download save file...</button></li> <li><button type="button" id="load">Upload save file...</button></li> </ul></div></li> --> <li><div tabindex="0">Type<ul id="gametype" class="transient"></ul></div></li> <li role="separator"></li> <li><button type="button" id="new"> New<span class="verbiage"> game</span> </button></li> <li><button type="button" id="restart"> Restart<span class="verbiage"> game</span> </button></li> <li><button type="button" id="undo"> Undo<span class="verbiage"> move</span> </button></li> <li><button type="button" id="redo"> Redo<span class="verbiage"> move</span> </button></li> <li><button type="button" id="solve"> Solve<span class="verbiage"> game</span> </button></li> <li><a target="_blank" href="help/en/${name}.html#${name}"> Instructions </a></li> <li><a target="_blank" href="help/en/index.html"> Full manual </a></li> </ul> <div class="softkey"> <div class="csk">Select</div> <div class="rsk">Dismiss</div> </div> </form> </body> </html> EOF