185 lines
4.8 KiB
JavaScript
185 lines
4.8 KiB
JavaScript
|
let pl
|
||
|
|
||
|
function importPebblisp() {
|
||
|
if (pl) {
|
||
|
return
|
||
|
}
|
||
|
pl = () => {}
|
||
|
return import('./pebblisp.js')
|
||
|
.then(async mod => await mod.default())
|
||
|
.then(async module =>
|
||
|
pl = function pl(code) {
|
||
|
return module.ccall('run', 'string', ['string'], [code])
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
|
||
|
class PlConsole extends HTMLElement {
|
||
|
constructor() {
|
||
|
super()
|
||
|
this.codeHistory = `
|
||
|
(if (= 4 (+ 2 2))
|
||
|
"Math still works!"
|
||
|
"Uh-oh...")
|
||
|
|
||
|
> Math still works!`
|
||
|
}
|
||
|
|
||
|
input(e) {
|
||
|
e.preventDefault()
|
||
|
}
|
||
|
|
||
|
connectedCallback() {
|
||
|
const shadow = this.attachShadow({ mode: 'closed' })
|
||
|
|
||
|
shadow.innerHTML = `
|
||
|
<script>
|
||
|
window.pl = function pl(code) {
|
||
|
return Module.ccall('run', 'string', ['string'], [code])
|
||
|
}
|
||
|
</script>
|
||
|
<style>
|
||
|
.loadable {
|
||
|
transition: opacity, display;
|
||
|
transition-duration: 2s;
|
||
|
transition-timing-function: ease-in;
|
||
|
opacity: 1;
|
||
|
}
|
||
|
#pebblisp-console.unloaded .loadable {
|
||
|
opacity: 0;
|
||
|
cursor: pointer;
|
||
|
user-select: none;
|
||
|
pointer-events: none;
|
||
|
}
|
||
|
#pebblisp-console {
|
||
|
width: calc(min(500px, 90%));
|
||
|
height: 400px;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
justify-content: end;
|
||
|
background-color: black;
|
||
|
color: white;
|
||
|
padding: 1em;
|
||
|
font-size: 115%;
|
||
|
border-radius: 6px;
|
||
|
position: relative;
|
||
|
}
|
||
|
@media only screen and (max-width: 600px) {
|
||
|
#pebblisp-console {
|
||
|
width: calc(min(500px, 105%));
|
||
|
margin-left: -20px;
|
||
|
margin-right: -20px;
|
||
|
font-size: 75%;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#pebblisp-output {
|
||
|
text-align: left;
|
||
|
overflow-y: scroll;
|
||
|
white-space: pre-wrap;
|
||
|
word-wrap: break-word;
|
||
|
margin-top: 0;
|
||
|
}
|
||
|
|
||
|
.pebblisp-repl-input {
|
||
|
font-family: monospace;
|
||
|
margin: 0;
|
||
|
padding: 3px;
|
||
|
border-width: 0;
|
||
|
outline: #555 solid 1px;
|
||
|
width: 98%;
|
||
|
background-color: #2b2a33;
|
||
|
color: #eee;
|
||
|
}
|
||
|
|
||
|
.pebblisp-repl-input:focus {
|
||
|
outline: #aaa solid 1px;
|
||
|
}
|
||
|
|
||
|
#pebblisp-console-preload {
|
||
|
opacity: 0;
|
||
|
height: 100%;
|
||
|
width: 100%;
|
||
|
text-align: center;
|
||
|
user-select: none;
|
||
|
cursor: pointer;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
justify-content: center;
|
||
|
position: absolute;
|
||
|
top: 0;
|
||
|
left: 0;
|
||
|
transition: opacity 1s;
|
||
|
text-shadow: -1px 2px 2px #FFFFFF77;
|
||
|
}
|
||
|
#pebblisp-console-preload:hover {
|
||
|
/*text-shadow: -1px 2px 2px white;*/
|
||
|
animation: 1s infinite jumpy-text steps(5, end);
|
||
|
}
|
||
|
#pebblisp-console.unloaded #pebblisp-console-preload {
|
||
|
opacity: 1;
|
||
|
}
|
||
|
@keyframes jumpy-text {
|
||
|
0% {
|
||
|
text-shadow: -1px 2px 2px #FFFFFF77;
|
||
|
}
|
||
|
20% {
|
||
|
text-shadow: 1px 1px 2px #FFFFFF77;
|
||
|
}
|
||
|
40% {
|
||
|
text-shadow: 0px 3px 2px #FFFFFF77;
|
||
|
}
|
||
|
60% {
|
||
|
text-shadow: -2px 0px 2px #FFFFFF77;
|
||
|
}
|
||
|
80% {
|
||
|
text-shadow: 0px -3px 2px #FFFFFF77;
|
||
|
}
|
||
|
}
|
||
|
</style>
|
||
|
<div id="pebblisp-console" class="unloaded">
|
||
|
<div id="pebblisp-console-preload">
|
||
|
<div>Click to load the Pebblisp REPL (< 0.5mB)</div>
|
||
|
</div>
|
||
|
<pre id="pebblisp-output" class="loadable">${this.codeHistory}</pre>
|
||
|
<form id='repl-form' class="loadable">
|
||
|
<input name="input" type="text" class="pebblisp-repl-input loadable">
|
||
|
</form>
|
||
|
</div>
|
||
|
`
|
||
|
const consoleNode = shadow.getElementById('pebblisp-console')
|
||
|
const preloadMessage = shadow.getElementById('pebblisp-console-preload')
|
||
|
const replForm = shadow.getElementById('repl-form')
|
||
|
|
||
|
preloadMessage.addEventListener('click', e => {
|
||
|
setTimeout(() => preloadMessage.remove(), 1000)
|
||
|
importPebblisp().then(() => {
|
||
|
consoleNode.classList.remove('unloaded')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
replForm.addEventListener('submit', e => {
|
||
|
e.preventDefault()
|
||
|
const input = e.target.input.value
|
||
|
e.target.input.value = ''
|
||
|
const result = pl(input)
|
||
|
this.codeHistory += `
|
||
|
|
||
|
${input}
|
||
|
> ${result}`
|
||
|
const output = shadow.getElementById('pebblisp-output')
|
||
|
output.innerText = this.codeHistory
|
||
|
output.scrollTop = output.scrollHeight
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
customElements.define("pebblisp-console", PlConsole);
|
||
|
|
||
|
document.addEventListener('DOMContentLoaded', () => {
|
||
|
const element = document.getElementById('user-content-pebblisp-console-placeholder')
|
||
|
element?.replaceWith(document.createElement('pebblisp-console'))
|
||
|
})
|
||
|
|