Skip to content

Instantly share code, notes, and snippets.

@dmsnell
Created May 20, 2019 00:00
Show Gist options
  • Save dmsnell/929a33d222af31abbee6173d96a0fd1a to your computer and use it in GitHub Desktop.
Save dmsnell/929a33d222af31abbee6173d96a0fd1a to your computer and use it in GitHub Desktop.
KLIPSE-in-iframe
<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>
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 );
<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>
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