-
-
Save dmsnell/929a33d222af31abbee6173d96a0fd1a to your computer and use it in GitHub Desktop.
KLIPSE-in-iframe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="blocks"></div> | |
<select id="modeSelector"> | |
<option value="eval-javascript">JavaScript</option> | |
<option value="eval-markdown">Markdown</option> | |
<option value="eval-ocaml">OCaml</option> | |
</select> | |
<button id="newBlockButton">New Block</button> | |
<script src="index.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const getPort = () => new Promise( resolve => { | |
window.addEventListener( 'message', event => { | |
if ( event.data === 'klipse-loaded' ) { | |
resolve( event.ports[ 0 ] ); | |
} | |
} ); | |
const klipseFrame = document.createElement( 'iframe' ); | |
klipseFrame.setAttribute( 'style', 'display: none;' ); | |
klipseFrame.src = 'klipse-frame.html'; | |
document.body.appendChild( klipseFrame ); | |
} ); | |
document.addEventListener('DOMContentLoaded', async () => { | |
const controlPort = await getPort(); | |
const blocks = document.getElementById( 'blocks' ); | |
const newBlockButton = document.getElementById( 'newBlockButton' ); | |
const modeSelector = document.getElementById( 'modeSelector' ); | |
newBlockButton.addEventListener( 'click', event => { | |
// create DOM editor and output | |
const container = document.createElement( 'div' ); | |
const sourcebox = document.createElement( 'textarea' ); | |
sourcebox.setAttribute( 'style', 'width: 80%; height: 300px; font-size: 16px;'); | |
const outputBox = document.createElement( 'div' ); | |
const outputPre = document.createElement( 'pre' ); | |
const output = document.createElement( 'code' ); | |
outputPre.appendChild( output ); | |
outputBox.appendChild( outputPre ); | |
container.appendChild( sourcebox ); | |
container.appendChild( outputBox ); | |
blocks.appendChild( container ); | |
// connect editor to KLIPSE | |
const blockChannel = new MessageChannel(); | |
controlPort.postMessage( { | |
action: 'new-block', | |
mode: modeSelector.value | |
}, [ blockChannel.port2 ] ) | |
sourcebox.addEventListener( 'input', event => { | |
blockChannel.port1.postMessage( sourcebox.value ); | |
} ); | |
blockChannel.port1.onmessage = event => { | |
output.innerHTML = event.data; | |
} | |
}, false ); | |
}, false ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link rel="stylesheet" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css"> | |
<script> | |
window.klipse_settings = { | |
eval_idle_ms: 1000, | |
selector_eval_js: '.eval-js', | |
selector_eval_markdown: '.eval-markdown', | |
selector_eval_ocaml: '.eval-ocaml', | |
}; | |
const log = console.log.bind( console ); | |
const oldEval = window.eval; | |
window.evalPorts = new Map(); | |
window.pushQueue = new Map(); | |
window.eval = source => { | |
const value = oldEval( source ); | |
log( source ); | |
const ports = window.pushQueue.get( source ) || new Set(); | |
[ ...ports ] | |
.map( id => window.evalPorts.get( id ) ) | |
.forEach( port => port.postMessage( value ) ); | |
window.pushQueue.delete( source ); | |
return value; | |
} | |
</script> | |
<div id="blocks"></div> | |
<script src="https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"></script> | |
<script src="klipse-frame.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const waitUntil = ( p ) => new Promise( resolve => { | |
const runner = () => { | |
const v = p(); | |
if ( v ) { | |
resolve( v ); | |
} | |
requestIdleCallback( runner ); | |
} | |
runner(); | |
} ); | |
const findEditor = wrapper => waitUntil( () => { | |
const editorIndex = Object | |
.keys( window.klipse_editors ) | |
.find( | |
i => window.klipse_editors[ i ].display.wrapper.parentNode.parentNode === wrapper | |
); | |
if ( null === editorIndex ) { | |
return false; | |
} | |
const editor = window.klipse_editors[ editorIndex ]; | |
if ( null === editor ) { | |
return false; | |
} | |
return editor; | |
} ); | |
document.addEventListener('DOMContentLoaded', async () => { | |
const controlChannel = new MessageChannel(); | |
window.parentPort = controlChannel.port1; | |
await waitUntil( () => !! window.klipse ); | |
const blocks = document.getElementById( 'blocks' ); | |
controlChannel.port1.onmessage = async event => { | |
if ( event.data.action === 'new-block' ) { | |
const { data: { mode }, ports } = event; | |
const id = Symbol(); | |
// construct shadow DOM editor | |
const wrapper = document.createElement( 'div' ); | |
const input = document.createElement( 'div' ); | |
wrapper.appendChild( input ); | |
blocks.appendChild( wrapper ); | |
window.klipse.plugin.klipsify( input, window.klipse_settings, mode ); | |
await waitUntil( () => !! window.klipse_editors ); | |
window.evalPorts.set( id, ports[ 0 ] ); | |
ports[ 0 ].onmessage = async event => { | |
const queue = window.pushQueue.get( event.data ) || new Set(); | |
queue.add( id ); | |
window.pushQueue.set( event.data, queue ); | |
const editor = await findEditor( wrapper ); | |
editor.setValue( event.data ); | |
} | |
} | |
} | |
window.parent.postMessage( 'klipse-loaded', '*', [ controlChannel.port2 ] ); | |
}, false ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment