JSFiddle - React, Tailwind, and code Playground
by fxi
HTML
<link rel="stylesheet" href="https://unpkg.com/@highlightjs/[email protected]/styles/default.min.css">
<script src="https://unpkg.com/@highlightjs/[email protected]/highlight.min.js"></script>
<!--
bgcolor = deprecated way of setting background.Value x is undocumented
onload = eval JS code
-->
<body bgcolor=x onload=''>
<!--
Our "canvas". id will be available as a global variable.
-->
<div class=quine>
<pre id=p></pre>
</div>
<div class="explain">
<p>There is three main tricks here :
<ol>
<li> Store the function as string and loop on characters for the "self printing" part </li>
<li> Encode binary value as an integer, ex.
<pre>
(30583).toString(2)
'111011101110111' (Top row of 2022) </pre></li>
<li> Use "fontcolor" to convert string to html with color, ex "s" -> '<font color="undefined"> s </font> '</li>
</ol>
<pre><code class="language-js">
setInterval( // Repeat funtion each n [ms] ( set at the end )
f= // Save callback in variable "f"
H // Use the H argument as the first letter of the greeting
/*appy New Year*/ // Use comment to display the rest of the greeting
=>{ // Arrow function
for( // Loop
// - INIT
i=0, // Start at 0
w=19, // Width of the message
b=30583, // Save the top row of 2022 ( binary )
t++, // Increment time ( for scroll )
o=``, // Reset output HTML
l=f+o; // Save the function as string
// - END CONDITION
i<l.length; // Continue the loop until the end of the string
// - INCREMENT
o+=( // Append each token to the string
l[i++]+(i%w?``:`\n`) // Add character and new line each 19 characters ( w value )
).fontcolor( ...
CSS
body {
font-family: Helvetica, Arial, sans-serif;
}
.quine {
padding:50px;
display: flex;
justify-content: center;
align-items: center;
margin: 50px;
outline: 1px solid #f0f;
background-color: #333;
}
.explain {
padding:50px;
}
JavaScript
hljs.highlightAll();
setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,b=30583,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!([b,17492,30551,4433,b][i/w+t&7]&1<<i%w-3)&&H));p.innerHTML=o/**/},t=500);
// better, but characters are not all monospaced, prduce unreguar lines
//setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!(H.charCodeAt(i/w+t&7)&1<<i%w-3)&&p.x));p.innerHTML=o},t=6e2,`睷䑔睗ᅑ睷`)
// Smarter, but encoded 2022 not included
//setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!(H.charCodeAt(i/w+t&7)&1<<i%w-3)&&p.x));p.innerHTML=o},t=6e2,`睷䑔睗ᅑ睷`)
// Compromise : char numbers
//setInterval(f=H/*appy New Year*/=>{for(i=0,w=19,b=30583,t++,o=``,l=f+o;i<l.length;o+=(l[i++]+(i%w?``:`\n`)).fontcolor(!([b,17492,30551,4433,b][i/w+t&7]&1<<i%w-3)&&H));p.innerHTML=o/**/},t=500)