2018-10-04 13:50:25 +02:00
<!DOCTYPE html> < html lang = "en" >< head >< meta charSet = "utf-8" />< meta http-equiv = "X-UA-Compatible" content = "IE=edge" />< title > Pluto · A grammar for data manipulation</ title >< meta name = "viewport" content = "width=device-width" />< meta name = "generator" content = "Docusaurus" />< meta name = "description" content = "A grammar for data manipulation" />< meta name = "docsearch:language" content = "en" />< meta property = "og:title" content = "Pluto · A grammar for data manipulation" />< meta property = "og:type" content = "website" />< meta property = "og:url" content = "https://status-im.github.io/pluto/index.html" />< meta property = "og:description" content = "A grammar for data manipulation" />< meta name = "twitter:card" content = "summary" />< link rel = "shortcut icon" href = "/pluto/img/favicon.png" />< link rel = "stylesheet" href = "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css" />< script type = "text/javascript" src = "https://buttons.github.io/buttons.js" ></ script >< script type = "text/javascript" src = "/pluto/js/pluto.js" ></ script >< link rel = "stylesheet" href = "/pluto/css/prism.css" />< link rel = "stylesheet" href = "/pluto/css/main.css" /></ head >< body >< div class = "fixedHeaderContainer" >< div class = "headerWrapper wrapper" >< header >< a href = "/pluto/" >< img class = "logo" src = "/pluto/img/logo_white.png" alt = "Pluto" />< h2 class = "headerTitleWithLogo" > Pluto</ h2 ></ a >< div class = "navigationWrapper navigationSlider" >< nav class = "slidingNav" >< ul class = "nav-site nav-site-internal" >< li class = "" >< a href = "/pluto/docs/Manifesto.html" target = "_self" > Docs</ a ></ li >< li class = "" >< a href = "/pluto/examples.html" target = "_self" > Examples</ a ></ li >< li class = "siteNavItemActive" >< a href = "/pluto/try.html" target = "_self" > Try</ a ></ li ></ ul ></ nav ></ div ></ header ></ div ></ div >< div class = "navPusher" >< div > <!doctype html>
2018-09-28 10:28:10 +02:00
< html >
< head >
< link rel = "stylesheet" href = "https://cdn.jsdelivr.net/npm/codemirror@5.40.2/lib/codemirror.css" >
< link rel = "stylesheet" href = "https://fonts.googleapis.com/icon?family=Material+Icons" >
< link rel = "stylesheet" href = "https://code.getmdl.io/1.3.0/material.indigo-pink.min.css" >
< script defer src = "https://code.getmdl.io/1.3.0/material.min.js" ></ script >
< script src = "https://cdn.jsdelivr.net/npm/codemirror@5.40.2/lib/codemirror.min.js" ></ script >
< script src = "https://cdn.jsdelivr.net/npm/codemirror@5.40.2/mode/clojure/clojure.js" ></ script >
< script src = "https://cdn.jsdelivr.net/npm/parinfer@3.12.0/parinfer.min.js" ></ script >
< script src = "https://cdn.jsdelivr.net/npm/parinfer-codemirror@1.4.2/parinfer-codemirror.min.js" ></ script >
< script src = "https://cdn.rawgit.com/neocotic/qrious/master/dist/qrious.js" ></ script >
</ head >
< body >
< script >
2018-11-15 08:28:14 +01:00
const TIMEOUT = 5 ; // seconds
const timeout = new Promise (( resolve , reject ) => {
return setTimeout (() => reject ( new Error ( 'request timeout' )), TIMEOUT * 1000 );
});
async function cat ( hash ) {
try {
const response = await Promise . race ([ timeout , fetch ( "https://ipfs.infura.io:5001/api/v0/cat?arg=" + hash )]);
if ( response . status === 200 ) {
return response . text ();
}
return null ;
} catch {
return null ;
}
2018-09-28 10:28:10 +02:00
}
2018-11-15 08:28:14 +01:00
async function add ( content ) {
const formData = new FormData ();
formData . append ( "extension.edn" , content );
const response = await fetch ( "https://ipfs.infura.io:5001/api/v0/add" , {
method : 'post' ,
body : formData
});
if ( response . status === 200 ) {
return response . json ();
}
return null ;
}
2018-11-29 16:19:05 +01:00
const defaultHash = "QmcfsYnFvKXApcFTCNttpQvQKYxiMCqVx5MvsocFyrr2KA" ;
2018-11-22 11:51:20 +01:00
function clearHash () {
history . replaceState ({ hash : null }, null , document . location . href . split ( '?' )[ 0 ]);
}
2018-11-15 08:28:14 +01:00
async function main () {
const params = ( new URL ( document . location )). searchParams ;
const hash = params . get ( "hash" ) || defaultHash ;
const content = await cat ( hash );
if ( content != null ) {
codeMirror . setValue ( content );
history . replaceState ({ hash : hash }, null , document . location . href . split ( '?' )[ 0 ] + "?hash=" + hash );
2018-11-21 13:29:40 +01:00
displayQR ( hash );
2018-11-15 08:28:14 +01:00
} else {
codeMirror . setValue ( "Failed to load the extension" );
2018-11-22 11:51:20 +01:00
clearHash ();
2018-11-15 08:28:14 +01:00
}
}
2018-09-28 10:28:10 +02:00
function extensionLink ( hash ) {
return "https://get.status.im/extension/ipfs@" + hash ;
}
async function publish () {
2018-10-04 13:50:25 +02:00
const content = codeMirror . getValue ();
2018-11-15 08:28:14 +01:00
const bel = document . getElementById ( "publish" );
bel . disabled = true ;
const object = await add ( content );
if ( object !== null ) {
const hash = object . Hash ;
history . pushState ({ hash : hash }, null , document . location . href . split ( '?' )[ 0 ] + "?hash=" + hash );
displayQR ( hash );
} else {
const qel = document . getElementById ( "qr-wrapper" );
qel . innerHTML = "Failed to publish the extension" ;
}
bel . disabled = false ;
2018-09-28 10:28:10 +02:00
}
function clearErrors () {
2018-10-04 13:50:25 +02:00
const elErrors = document . getElementById ( "errors" );
elErrors . innerHTML = '' ;
elErrors . className = "" ;
2018-09-28 10:28:10 +02:00
}
function displayErrors ( errors ) {
2018-10-04 13:50:25 +02:00
const elErrors = document . getElementById ( "errors" );
2018-09-28 10:28:10 +02:00
if ( errors == null ) {
2018-10-04 13:50:25 +02:00
elErrors . innerHTML = '<div>No errors</div>' ;
elErrors . classList . add ( "ok" );
2018-09-28 10:28:10 +02:00
} else {
2018-10-04 13:50:25 +02:00
elErrors . classList . add ( "errors" );
2018-09-28 10:28:10 +02:00
2018-11-15 08:28:14 +01:00
const names = errors . map ( ( error , i ) => {
2018-09-28 10:28:10 +02:00
return [ error . type , error . value ]
})
var s = '<div>Errors</div><ul>' ;
names . forEach ( function ( element ) {
2018-10-04 13:50:25 +02:00
s = s . concat ( "<li>" + element [ 0 ]);
if ( element [ 1 ] != null ) {
2018-10-08 20:09:09 +02:00
s = s . concat ( ":" + JSON . stringify ( element [ 1 ]));
2018-10-04 13:50:25 +02:00
}
s = s . concat ( "</li>" );
2018-09-28 10:28:10 +02:00
});
s = s . concat ( "</ul>" )
2018-10-04 13:50:25 +02:00
elErrors . innerHTML = s ;
2018-09-28 10:28:10 +02:00
}
}
2018-10-08 20:09:09 +02:00
function clearQR () {
const qel = document . getElementById ( "qr-wrapper" );
qel . innerHTML = '' ;
}
2018-11-08 09:47:44 +01:00
function displayQR ( hash ) {
2018-10-04 13:50:25 +02:00
const qel = document . getElementById ( "qr-wrapper" );
2018-11-08 09:47:44 +01:00
const s = extensionLink ( hash );
qel . innerHTML = '<canvas id="qr"></canvas><a href="' + s + '">Universal link</a><a href="https://ipfs.infura.io/ipfs/' + hash + '/">IPFS link</a>' ;
2018-09-28 10:28:10 +02:00
new QRious ({
2018-10-04 13:50:25 +02:00
element : document . getElementById ( 'qr' ),
2018-09-28 10:28:10 +02:00
value : s ,
size : 250
});
}
2018-11-15 08:28:14 +01:00
main ();
2018-09-28 10:28:10 +02:00
</ script >
< div id = "wrapper" >
< main >
< div id = "content" ></ div >
< div id = "errors" ></ div >
</ main >
2018-10-23 08:50:20 +02:00
< aside id = "side-column" >
< div id = "panel" >
< p > A playground to experiment with extensions and easily publish them on IPFS. Go ahead, modify the default extension on the left side!</ p >
2018-11-26 10:37:35 +01:00
< p > Find more details about building your own extension in this < a href = "https://status.im/extensions/" > tutorial</ a ></ p >
2018-11-15 08:28:14 +01:00
< button id = "publish" class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" onclick = "publish()" > Publish</ button >
2018-10-04 13:50:25 +02:00
< div id = "qr-wrapper" ></ div >
2018-10-23 08:50:20 +02:00
</ div >
< div id = "docs" >
< h6 > Components</ h6 >
< ul >
< li >< code > view</ code ></ li >
< li >< code > text</ code ></ li >
< li >
< code > touchable-opacity</ code >
< pre class = "inline-args" > {:on-press Event}</ pre >
</ li >
< li >
< code > image</ code >
< pre class = "inline-args" > {:uri String}</ pre >
</ li >
< li >
< code > input</ code >
< pre > {:on-change Event
:placeholder String}</ pre ></ li >
< li >
< code > button</ code >
< pre class = "inline-args" > {:on-click Event}</ pre ></ li >
< li >
< code > link</ code >
< pre class = "inline-args" > {:uri String}</ pre >
</ li >
< li >
< code > checkbox</ code >
2018-11-26 10:37:35 +01:00
< pre class = "inline-args" > {:on-change Event :checked Bool}</ pre >
2018-10-23 08:50:20 +02:00
</ li >
< li >
2018-11-26 10:37:35 +01:00
< code > list</ code >
< pre class = "inline-args" > {:data Vector :item-view View :key Keyword}</ pre >
</ li >
< li >
< code > picker</ code >
< pre class = "inline-args" > {:on-change Event :selected String :enabled Boolean :data Vector}</ pre >
</ li >
< li >
< code > activity-indicator</ code >
< pre class = "inline-args" > {:animating Boolean :color String :size Keyword :hides-when-stopped Boolean}</ pre >
2018-10-23 08:50:20 +02:00
</ li >
< li >
< code > nft-token-viewer</ code >
< pre class = "inline-args" > {:token String}</ pre >
</ li >
< li >< code > transaction-status</ code >
< pre class = "inline-args" > {:outgoing String :tx-hash String}</ pre ></ li >
< li >< code > asset-selector</ code ></ li >
< li >< code > token-selector</ code ></ li >
</ ul >
< h6 > Queries</ h6 >
< ul >
< li >
< code > store/get</ code >
< pre class = "inline-args" > {:key String}</ pre >
</ li >
< li >
< code > wallet/collectibles</ code >
< pre class = "inline-args" > {:token String :symbol String}</ pre >
</ li >
</ ul >
< h6 > Events</ h6 >
< ul >
< li >
< code > alert</ code >
< pre class = "inline-args" > {:value String}</ pre >
</ li >
< li >
< code > log</ code >
< pre class = "inline-args" > {:value String}</ pre >
</ li >
< li >
< code > store/put</ code >
< pre class = "inline-args" > {:key String :value String}</ pre >
</ li >
< li >
< code > store/append</ code >
< pre class = "inline-args" > {:key String :value String}</ pre >
</ li >
< li >
< code > store/clear</ code >
< pre class = "inline-args" > {:key String}</ pre >
</ li >
< li >
< code > http/get</ code >
< pre > {:url String
:timeout? String
:on-success Event
:on-failure? Event}</ pre >
</ li >
< li >
< code > http/post</ code >
< pre > {:url String
:body String
:timeout? String
:on-success Event
:on-failure? Event}</ pre >
</ li >
< li >
< code > ipfs/cat</ code >
< pre > {:hash String
:on-success Event
:on-failure? Event}</ pre >
</ li >
< li >
< code > ethereum/send-transaction</ code >
< pre > {:to String
:gas? String
:gas-price? String
:value? String
:method? String
:params? Vector
:nonce? String
:on-result? Event}</ pre >
</ li >
2018-11-26 10:37:35 +01:00
< li >
< code > ethereum/logs</ code >
< pre > {:fromBlock? String
:toBlock? String
:address? Vector
:topics? Vector
:blockhash? String
:on-result Event}</ pre >
</ li >
2018-10-23 08:50:20 +02:00
< li >
< code > ethereum/call</ code >
< pre > {:to String
:method String
:params? Vector
:on-result? Event}</ pre >
</ li >
</ ul >
</ div >
2018-09-28 10:28:10 +02:00
</ aside >
</ div >
< script >
2018-10-04 13:50:25 +02:00
const codeMirror = CodeMirror ( document . getElementById ( "content" ));
2018-10-08 20:09:09 +02:00
codeMirror . setValue ( "Loading content ..." );
2018-10-04 13:50:25 +02:00
codeMirror . on ( "change" , function ( c , change ) {
clearErrors ();
2018-10-08 20:09:09 +02:00
clearQR ();
2018-11-22 11:51:20 +01:00
clearHash ();
2018-10-04 13:50:25 +02:00
const read = pluto . reader . read ( codeMirror . getValue ());
2018-09-28 10:28:10 +02:00
const readJS = pluto . js . from_clj ( read );
displayErrors ( readJS . errors );
if ( readJS . errors == null ) {
2018-10-04 13:50:25 +02:00
const parsed = pluto . js . parse ( read );
const parsedJS = pluto . js . from_clj ( parsed );
displayErrors ( parsedJS . errors );
2018-09-28 10:28:10 +02:00
}
});
2018-10-04 13:50:25 +02:00
parinferCodeMirror . init ( codeMirror );
2018-09-28 10:28:10 +02:00
</ script >
</ body >
</ html >
</ div >< footer class = "nav-footer" id = "footer" >< section class = "sitemap" >< a href = "/pluto/" class = "nav-home" >< img src = "/pluto/img/logo_white.png" alt = "Pluto" width = "66" height = "58" /></ a >< div >< h5 > Docs</ h5 >< a href = "docs/Tutorial" > Getting Started</ a >< a href = "docs/API" > API Reference</ a ></ div >< div >< h5 > Community</ h5 >< a href = "https://chat.status.im" > Project Chat</ a >< a href = "https://twitter.com/ethstatus" target = "_blank" rel = "noreferrer noopener" > Twitter</ a ></ div >< div >< h5 > More</ h5 >< a href = "https://blog.status.im/" > Blog</ a >< a href = "https://github.com/status-im/pluto/" > GitHub</ a ></ div ></ section >< section class = "copyright" > Copyright © 2018 Status.im</ section ></ footer ></ div ></ body ></ html >