removed web directory to reduce confusion with current web repo https://github.com/gundb/gundb.github.io

This commit is contained in:
MetaSean 2015-12-18 14:58:41 -07:00
parent af30651ddd
commit 2ed41745d1
63 changed files with 0 additions and 19093 deletions

View File

@ -1,57 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<a href="https://github.com/amark/gun" target="_blank"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
<a href="https://gunDB.io/" style="font-family: Arial;">Home</a>
<!-- BLOG POST HERE -->
<style>
#main {
min-width: 250px;
max-width: 700px;
width: 75%;
margin: 7% auto;
padding: 2% 5%;
background: white;
background: rgba(100%,100%,100%,.6);
font-family: Arial;
font-size: 18pt;
text-shadow: 0px 0px 7px #DDD;
line-height: 20pt;
}
#main p {
text-indent: 2em;
}
</style>
<div id="main">
<h3>Do You have Time to Chat?</h3>
<p>
Let's build a chat app. But we're going to do it in a mind boggling way.
Conversations take time to have, therefore rather than storing every message
individually, we are going to store them in time. What does that even mean?
</p>
<p>
The first requirement is understanding immutable data.
Most database systems overwrite old data with new data when there is an update.
This preserves data in space, but loses its history.
Immutable data is the idea of never changing data,
but appending a new record every time. Such approach preserves history.
</p>
<p>
</p>
</div>
<!-- END OLD BLOG POST -->
</body>
</html>

View File

@ -1,293 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./dep/jquery.js"></script>
</head>
<body>
<p>Now that we can jot down our thoughts in a <a href="./think.html">To-Do</a> app, let us add something ambitious to it. To-Do: Build a realtime chat app! Which is exactly what we are going to do in this tutorial. It is the next natural step, we can track our thoughts - but now we want to have conversations about them with others to refine our ideas.</p>
<p>So what are the requirements? The ability to write a message, send a message, and receive messages. We will also need a space to keep these messages in, and a web page to access the chat through. Let's start with making a copy of our code from the To-Do app! You can edit the code below, which will update the live preview.</p>
<div class="edit">... loading editor and preview ...
<textarea style="height: 36em"><html>
<body>
<h1>Thoughts</h1>
<form>
<input><button>Add</button>
</form>
<ul></ul>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://rawgit.com/amark/gun/master/gun.js"></script>
<script>
var gun = Gun().get('thoughts');
$('form').on('submit', function(event){
event.preventDefault();
gun.set($('input').val());
$('input').val("");
});
gun.on().map(function(thought, id){
var li = $('#' + id).get(0) || $('<li>').attr('id', id).appendTo('ul');
if(thought){
$(li).text(thought);
} else {
$(li).hide();
}
});
$('body').on('dblclick', 'li', function(event){
gun.path(this.id).put(null);
});
</script>
</body>
</html></textarea>
</div>
<script>
var code = $('.edit').load('./editor.html', function(){setTimeout(function(){
var editor = $('.CodeMirror')[0].CodeMirror;
editor.live(function(frame){
$('body', frame).on('submit', 'form', function(e){e.preventDefault()});
});
editor.setValue(code);
},1)}).find('textarea').text();
</script>
<style>
.none { display: none }
.step-at { display: block }
textarea { border: none; width: 100%; }
</style>
<div id="step-0" class="step">
<p>The first thing we need to do is update the HTML.</p>
<ol>
<li>Change the text in the <u>h1</u> tag to "Chat".</li>
<li>Move the <u>ul</u> tags up to be above the <u>form</u> tag.</li>
<li>Add an opening closing <u>textarea</u> tag inbetween the input and button.</li>
<li>Make the <u>button</u> say "send" instead of "Add".</li>
<li>
Now we want to model what the HTML for our message will look like. Copy the following into the editor to be above the first <u>script</u> tag:
<textarea style="height: 9em;"><div class="model" style="display: none;">
<li class="message">
<i class="when">0</i>
<b class="who"></b>:
<span class="what"></span>
</li>
</div>
</textarea>
</li>
</ol>
<p>What is happening?</p>
<ul>
<li>We do not actually have any messages yet, so we do not want an empty chat message displaying on the screen.</li>
<li>There are a bunch of other HTML tags out there, let us do a quick review of the new ones we added.
<ul>
<li>The <u>textarea</u> tag is like an <u>input</u> tag except longer content.</li>
<li>A <u>div</u> tag is a generic HTML tag to put anything else inside of.</li>
<li>The <i><u>i</u>talicize</i> tag stylizes your text as so.</li>
<li>The <b><u>b</u>old</b> tag does similarly.</li>
<li>And a <u>span</u> tag is a generic HTML tag to put text inside of.</li>
</ul>
</li>
<li>It turns out that HTML allows you to add extra data to your page, let us go over them.
<ul>
<li>One of these attributes is a <u>class</u> which lets you categorize your HTML.</li>
<li>The other one is a <u>style</u> attribute, which lets you style your HTML with <a href="https://www.google.com/search?q=CSS">CSS</a>.</li>
</ul>
<li>To keep our models hidden, we wrap them inside of <u>div</u> container, and then tell the computer not to display it.</li>
<li>When we receive a message, we will make a copy of the <u>"message"</u> model and fill it up with the data using javascript.</li>
</ul>
<button class="none">All tweaked!</button>
</div>
<div id="step-1" class="step">
<p>Before we get started with writing any javascript, we need to clean up some code that no longer applies! Go ahead and remove the following 3 lines of code from the bottom of our script tag:</p>
<textarea style="height: 4em;">
$('body').on('dblclick', 'li', function(event){
gun.path(this.id).put(null);
});</textarea>
<button class="none">I removed it!</button>
</div>
<div id="step-2" class="step">
<p>Wonderful! Now we want to change the name of the data so we do not get our previous app's data. Additionally, if we want this data to be shared and updated in realtime with other people, we have to connect to them directly or a server that does this for us. Modify the line where we initialize gun (hint: it is the very first line) with this:</p>
<textarea style="height: 1em;"> var gun = Gun('https://gunjs.herokuapp.com/gun').get('tutorial/chat/app');</textarea>
<p>What does this do?</p>
<ul>
<li>The URL <u>'https://gunjs.herokuapp.com/gun'</u> happens to be a gun peer.</li>
<li>Anyone can run a gun peer, by using <a href="https://github.com/amark/gun">gun on a server</a>.</li>
<li>This particular peer is a testing server, please do not use it outside these tutorials - it is not very fast or reliable, as we regularly delete data from it.</li>
<li>The <u>'tutorial/chat/app'</u> is the name of our shared data, it acts as a key to help us find it.</li>
</ul>
<button class="none">Connect!</button>
</div>
<div id="step-3" class="step">
<p>Oops, our current code is handling the data incorrectly. We need to fix that, adjust the commented line in the editor to this:</p>
<textarea style="height: 1em;">gun.map().val(function(message, id){</textarea>
<p>Why?</p>
<ul>
<li>Because we do not expect <u>message</u>s to change, therefore we just get the <u>val</u>ue instead of reacting <u>on</u> updates.</li>
<li>We also swap the order, placing <u>map</u> in front because we want to get each message item in the set (or that will be in the set) once rather than every item in the set every time it changes. Kinda confusing, but just reread that a couple of times and think about it.</li>
</ul>
<button class="none">Got it.</button>
</div>
<div id="step-4" class="step">
<p>We still have breaking changes, we need to revamp the inside of the val function with the following:</p>
<textarea style="height: 8em;">
var $li = $(
$('#' + id).get(0) ||
$('.model').find('.message').clone(true).attr('id', id).appendTo('ul')
);
$li.find('.who').text(message.who);
$li.find('.what').text(message.what);
$li.find('.when').text(message.when);</textarea>
<p>What does this do?</p>
<ul>
<li>As before, if the list item already exists, use it.</li>
<li><u>||</u> or find a model message, <u>clone</u> it, set its <u>id</u> so we can reuse it later, and <u>append</u> it to the list.</li>
<li>Then fill in the model with the specific pieces of data from our message.</li>
</ul>
<p>Now we need to make sure that the data we save matches the same format as the messages we receive.</p>
<button class="none">Okay.</button>
</div>
<div id="step-5" class="step">
<p>Replace everything inside of the form on submit function with the following:</p>
<textarea style="height: 8em;">
event.preventDefault();
var message = {};
message.who = $('form').find('input').val();
message.what = $('form').find('textarea').val();
message.when = new Date().getTime();
gun.set(message);
$('form').find('textarea').val("");</textarea>
<p>What is happening?</p>
<ul>
<li>We still want to prevent the default behavior of the browser, which would be to reload the page.</li>
<li>Then we want to create a javascript object using <u>{}</u> curly braces, which allows us to describe complex data.<li>Our data will be composed of three parts, <u>who</u> sent the message, <u>what</u> the message is, and <u>when</u> it was written.</li>
<li>We then add this message to a <u>set</u> of messages in the chat, which will get <u>map</u>ped over.</li>
<li>Finally we want to clear out the <u>textarea</u> we wrote our message in, so that way we can type another.</li>
</ul>
<button class="none">Try sending a message!</button>
</div>
<div id="step-6" class="step">
<p>Wow! Our chat is fully functioning! You can pat yourself on the back and be done now if you want. But there are lots of little things we can do to polish up the experience.</p>
<p>We will not be doing any design, as that exceeds the scope of what this tutorial teaches. So prepare for your app to look pretty ugly, you can try to make things pretty on your own. What then, is left?</p>
<ul>
<li>The message's sent time is not human friendly, we will need to convert it.</li>
<li>Messages currently may be shown out of order, so we need to order them correctly.</li>
<li>Every time a message comes in you have to scroll down to read it, we should automate that.</li>
</ul>
<button class="none">Let's do it!</button>
</div>
<div id="step-7" class="step">
<p>Tutorial Unfinished, Sad Face. We're Working On It Though!</p>
<p>Check out the <a href="https://github.com/amark/gun">github</a> in the meanwhile for more documentation.</p>
</div>
<div id="step-8" class="step">
<p>Congratulations! You have built a realtime chat app! That is quite the accomplishment, you should go celebrate by eating a sandwhich.</p>
<p>Now that we can converse with people, we might want to know <i>who</i> they are. In the next tutorial we will create a contact app with some basic social network features and learn a little bit about security.</p>
<a href="#">Coming Later!</a>
<p>Check out the <a href="https://github.com/amark/gun">github</a> in the meanwhile for more documentation.</p>
</div>
<script>
$('.step').addClass('none').first().addClass('step-at');
$('button').on('click', next).removeClass('none');
function next(){
$('.step-at').removeClass('step-at');
$('#step-' + (++next.at)).addClass('step-at');
(next.step[next.at] || function(){})();
}
next.at = 0;
next.comment = /\s*\/\*(.*?)\*\/\s*/i;
next.unwrap = /\s*<\/?(html|body)>\s*\s*/ig;
next.wrap = function(c){ return '<html>\n\t<body>\n\t\t' + c + '\n\t</body>\n</html>' }
next.code = function(){ return $('<div>' + next.mir.getValue().replace(next.wrap, '') + '</div>') }
next.step = [null, function(){
next.mir = $('.CodeMirror')[0].CodeMirror;
var code = next.code();
if(code.find('h1').text().toLowerCase() == 'thoughts'){
code.find('h1').text('Chat');
}
if(code.find('button').text().toLowerCase() == 'add'){
code.find('button').text('send');
}
if(!code.find('textarea').length){
code.find('button').before("<textarea>");
}
if(code.find('form').index() < code.find('ul').index()){
code.find('ul').insertBefore(code.find('form')).after('\n\t\t');
code.contents().filter(function(){
return $(this).text().indexOf('\n') >= 0 && $(this).prev().is('form')
}).remove();
code.find('form').after('\n\n\t\t');
}
if(!code.find('.model').length){
code.find('script').first().before($('#step-0').find('textarea').first().text() + '\n\t\t');
}
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
script.text(script.text().slice(0, script.text().indexOf(
$('#step-1').find('textarea').first().text().replace(/\s/ig,'').slice(0,7)
)));
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
if(script.text().indexOf('Gun()')){
script.text(script.text().replace('Gun()', 'Gun(' +
($('#step-2').find('textarea').first().text().match(/Gun\((.*?)\)/i)||[])[1]
+ ')'));
}
if(script.text().indexOf("'thoughts'")){
script.text(script.text().replace("'thoughts'",
($('#step-2').find('textarea').first().text().match(/get\((.*?)\)/i)||[])[1]
));
}
script.text(script.text().replace(/gun\.on\(\)\.map(.*)\n/ig, "gun.on().map(function(thought, id){ // Edit this line!\n"));
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
if(script.text().indexOf('.on().map')){
script.text(script.text().replace(/gun\.on\(\)\.map(.*)\n/ig,
$('#step-3').find('textarea').first().text() + '\n'
));
}
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
var jsq = jsQuery(script.text());
if(0 > jsq.find('.function').last().text().indexOf('.clone(')){
jsq.find('.function').last().empty().append(
jsQuery($('#step-4').find('textarea').first().text()).contents()
);
script.text(jsq.text());
}
next.mir.setValue(html_beautify(next.wrap($.trim(code.html()))));
}, function(){
var code = next.code();
var script = code.find('script').last();
var jsq = jsQuery(script.text());
if(0 > jsq.find('.function').first().text().indexOf('.what = ')){
jsq.find('.function').first().empty().append(
jsQuery($('#step-5').find('textarea').first().text()).contents()
);
script.text(jsq.text());
}
next.mir.setValue(html_beautify(next.wrap($.trim(code.html()))));
}]
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

View File

@ -1,46 +0,0 @@
<style>
html, body {
margin: 0;
padding: 0;
text-align: center;
font-size: 36pt;
font-family: Verdana, Geneva, sans-serif;
}
</style>
<div style="height: 100%; min-height: 500px; background-color: rgb(241, 90, 34); color: white;">
<div id="e1413969480658t7942" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 413px;
background-image: url('wave.png'); background-color: rgb(108, 197, 195); background-position: 43.1875% 100%; background-repeat: repeat-x;">
<div id="e1414010158000t6484" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 9px;" contenteditable="false">Problem</div>
<div id="e1414009476621t898" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 481px; width: 370px;
background-image: url('whale.png'); background-position: 50% 50%; background-repeat: no-repeat;"></div>
</div>
<div id="e1414009076551t8032" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto 51px; min-height: 100px;">
<br>Hassle to deploy slow databases that are costly to scale</div>
</div>
<div id="e1414009851463t501" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 100%; min-height: 500px;">
<div id="e1414009879758t838" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px; background-color: rgba(0, 0, 0, 0);" contenteditable="false">Solution</div>
<div id="e1414009950683t8894" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; width: 50%; min-width: 200px; max-width: 500px; height: 400px;
background-image: url('../../img/gun-logo.png'); background-position: 50% 50%; background-repeat: no-repeat; background-size: 100%;"></div>
<div id="e1414009972993t897" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px; background-color: rgba(0, 0, 0, 0);" contenteditable="false">the NoDB database</div>
</div>
<div id="e1414010217854t5686" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 100%; min-height: 500px; background-color: black; color: white;
background-image: url('polygen.png'); background-position: 50% 50%; background-repeat: no-repeat; background-size: 100%;">
<div id="e1414010395848t489" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">How</div>
<div id="e1414010397417t8943" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 500px;"></div>
<div id="e1414010398484t2942" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">peer to peer algorithms that mimic reality</div>
</div>
<div id="e1414010478794t8943" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 100%; min-height: 500px;">
<div id="e1414010488753t8274" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">Now</div>
<div id="e1414010489729t8174" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 400px;
background-image: url('stats.png'); background-position: 50% 50%; background-repeat: no-repeat; background-size: 100%;"></div>
<div id="e1414010490585t2896" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">fastest growing trends ever in software history</div>
</div>
<div id="e1414010542879t6487" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 500px; height: 100%; background-color: black; color: white;
background-image: url('team2.jpg'); background-position: 39.8610229492188% 17.7705977382876%; background-repeat: no-repeat; background-size: 100%;">
<div id="e1414010614360t886" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">Team</div>
<div id="e1414010615329t6812" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 400px;"></div>
<div id="e1414010616147t6367" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false"></div>
</div>
<div id="e1414010638042t831" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 500px; height: 100%;" contenteditable="false">
<div id="e1414010679930t7366" class="create-evyt" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">we@gunDB.io are raising $500k</div>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

View File

@ -1,204 +0,0 @@
<html>
<head>
<title>gun</title>
<meta name="viewport" content="width=device-width, minimum-scale=0.1">
</head>
<body>
<style>
html, body {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma;
font-size: 20pt;
color: #222;
}
@media (max-width: 1000px){
html, body {
font-size: 20pt;
}
}
@media (max-width: 700px) {
html, body {
font-size: 10pt;
}
}
.screen {
top: 0; left: 0;
right: 0; bottom: 0;
height: 100%;
width: 100%;
text-align: center;
-webkit-animation: fade 7s;
-moz-animation: fade 7s;
animation: fade 7s;
}
.big {
font-size: 300%;
}
.small {
font-size: 75%;
}
.break {
border: none;
border-bottom: dashed 5px gainsboro;
}
.bump {
height: 20%;
}
@-webkit-keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
} @-moz-keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
} @keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
}
</style>
<div class="screen break"><div style="height: 20%"></div>
<img src="../../img/gun-logo.png" width="40%">
<div><b>raising $1m</b></div>
<div>Realtime Distributed Graph Database</div>
<br>
<div>
<i>$12k fulfilled by</i>
</div>
<div>
<i>Adam Draper, Boost;</i>
</div>
</div>
<div id="problem" class="screen break"><div style="height: 10%"></div>
</div>
<!--<div id="problem" class="screen break"><div style="height: 10%"></div>
<div class="big">Problem</div>
<div>Businesses struggle with "sharding" data.</div>
<div>Concurrency is infamous within software, and we solve it.</div>
<img src="jargon.png" height="50%" title="via http://tagul.com">
<div class="small">The amount of academic jargon invented for the topic is absurd.</div>
<div>"<i>There are only two hard things in Computer Science: cache invalidation and naming things.</i>" ~ Phil Karlton</div>
</div>-->
<div class="screen break"><div style="height: 10%"></div>
<div id="how" class="big">How</div>
<div>
<i>Speed of light</i> is the <b>scientific barrier</b> to <u>the problem</u>.
</div>
<div>
The <u>crazy idea</u> was <i>what if</i> we modeled <b>data as light</b>?
</div>
<div>
We could then exploit the quantum behavior of photons.
</div>
<div>
Such <b>algorithms always collapse</b> to <u>the same answer</u> eventually, even over <i>significant latency</i>.
</div>
<br>
<div id="why" class="big">Why</div>
<div>
<u>Instant load times</u>, because <i>everything is a cache</i> in a <b>Named Data Network</b><sup><small>1</small></sup>.
</div>
<div>
Combined with <b>graphs</b>, the <u>mathematical superset</u> of <i>SQL and NoSQL</i>,
</div>
<div>
Developers can now run Turing Complete queries on their data.
</div>
<div>
<i>Big Data</i> turns into <b>meaningful data</b><sup><small>2</small></sup>, in <u>fast and affordable</u> ways.
</div>
<div class="small">
<div class="small">
[1] Van Jacobsen,
<a href="http://www.youtube.com/watch?v=oCZMoY3q2uM">
A New Way to look at Networking</a>
- Google Tech Talk.
<br>
[2] Alan Kay,
<a href="https://www.youtube.com/watch?v=gTAghAJcO1o">
The Future Doesn't Have to Be Incremental</a>
- Tech Talk</a>.
</div>
</div>
</div>
<div class="screen break"><div style="height: 10%"></div>
<div id="how" class="big">Now</div>
<div>Market interest in javascript and graphs is exploding.</div>
<div class="small">At accelerated rates never seen before in the software world.</div>
<img src="graph.png" width="44%">
<img src="npm.png" width="37%">
<div>Gun is the union of these two niches.</div>
<div><b>The facts predict they are the buzzwords of the future.</b></div>
</div>
<div id="team" class="screen break"><div style="height: 12%"></div>
<div class="big">Team</div>
<div><i>Here are the people powering the<br>"Open Source Firebase", "Dropbox for Developers", or "Bitcoin for Data".</i></div>
<br>
<div>
<div>
<img src="prudential.gif" style="height: 2.5em">
<img src="ucla.png" style="height: 2.5em">
<img src="thiel.svg" style="height: 2.3em">
</div>
<b>Mark Nadal</b>
CEO, 4 years experience in Synchronization Systems.
<div class="small">
Consulting clientele include a Thiel Fellow,
prototyped Prudential Retirement's SuperBowl advert's online interactive,
startup UCLA alumni.
</div>
</div>
<br>
<div>
<div>
<img src="stackoverflow.png" style="height: 3em">
<img src="boi.png" style="height: 3em">
<img src="nodejs.png" style="height: 2.7em">
</div>
<b>AJ ONeal</b>
CIO, 8 years experience with Software and Database Architecture.
<div class="small">
Contributor to NodeJS core,
in the top 1 percentile rank of all StackOverflow users,
built a Billboard Hot 100 rap artist's Twitter feed client.
</div>
</div>
</div>
<div style="text-align: center; padding: 2.5em 0 4em;">
<div id="how" class="big">You?</div>
<div>
Gun is the <b style="color: gold">first</b> company in this space, but it is going to fill up fast.
</div>
<div><br>
Without any marketing, we already have <b style="color: crimson"><u>250</u>+</b> developers interested.
<div class="small">
With <b style="color: crimson"><u>1600</u></b> demo video views in less than <b style="color: crimson"><u>24</u></b> hours.
</div>
</div>
<div><br>
Our <b style="color: green"><u>value proposition</u></b> for developers,
<span class="small" style="color: darkorange">slashing operational time and costs while making things faster and easier</span>,
<br>is convincing enough that some are likely to even leave established non-javascript databases.
</div>
<div><br>
By being <b style="color: skyblue"><i>open source</i></b>, we maintain trust with developers and get their contributions back.
</div>
<div><br>
Together, this effectively <b style="color: violetred">highgrades all the talent for us</b>, away from new competitors.
<div class="small">
Leaving them fighting to compete with "free".
</div>
</div>
<div><br>
Gun becomes the <b><i>de facto</i></b>,
like <span class="small" style="color: MidnightBlue">MySQL</span>
and <span class="small" style="color: SaddleBrown">MongoDB</span> did for their hype niche,
<br>and <b style="color: limegreen">profits</b> from enterprise licenses and consulting.
</div><br>
<div><b>
An established revenue model that you, as an investor, share in. Your choice.
</b></div>
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 987 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 KiB

View File

@ -1,111 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Isolation_Mode" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="549.693px" height="166.442px" viewBox="0 0 549.693 166.442" enable-background="new 0 0 549.693 166.442"
xml:space="preserve">
<g>
<g>
<path d="M156.21,79.881V0.037H69.236l17.892-0.033H0.147v79.841c0,0-4.679,23.033,38.795,56.3
c32.896,25.178,38.472,29.553,39.239,30.192c0.79-0.648,6.422-5.046,39.234-30.156C160.888,102.911,156.21,79.881,156.21,79.881z
M113.121,127.801c-29.219,21.883-34.236,25.72-34.94,26.286c0.219,0.179-0.003,0.023-0.003,0.023s-0.226,0.161,0.003-0.023
c-0.683-0.558-5.648-4.374-34.943-26.319C4.521,98.774,8.689,78.7,8.689,78.7V9.111h77.459L70.215,9.141h77.453v69.593
C147.668,78.733,151.833,98.804,113.121,127.801z"/>
<g>
<rect x="56.269" y="108.486" fill="#FFFFFF" width="45.354" height="3.808"/>
<g>
<path d="M57.109,43.013c0-6.719,2.986-10.078,9.799-10.078c6.16,0,9.239,3.827,9.239,9.985v6.533c0,2.52-0.56,6.16-1.493,8.866
L61.682,95.644h14.557v5.229h-19.97v-6.254l12.599-36.953c1.121-3.173,1.493-5.972,1.493-9.237v-5.321
c0-3.731-1.212-5.507-3.732-5.507c-2.519,0-3.731,1.775-3.731,5.507v7.746h-5.787V43.013z"/>
<path d="M82.399,42.92c0-8.489,5.412-9.985,9.612-9.985c4.198,0,9.611,1.496,9.611,9.985v48.527
c0,8.492-5.413,9.985-9.611,9.985c-4.2,0-9.612-1.493-9.612-9.985V42.92z M95.838,42.268c0-1.68,0-4.668-3.827-4.668
c-3.826,0-3.826,2.988-3.826,4.668V92.1c0,1.683,0,4.667,3.826,4.667c3.827,0,3.827-2.984,3.827-4.667V42.268z"/>
</g>
</g>
</g>
<g>
<path d="M209.396,65.962c-5.494,0-7.8-2.571-7.711-8.421l0.355-24.375c-2.04,0-4.787,0-5.673,0.09
c-0.354,0-0.443-0.977-0.266-1.064c4.342-3.014,8.065-6.736,11.788-10.902c0.089-0.089,0.709,0.177,0.709,0.443
c-0.177,1.773-0.62,6.471-0.709,8.242h4.787c3.724,0,6.56-0.088,7.71-0.442c0.71-0.179,0.266,3.989-0.708,3.9
c-0.976-0.089-2.571-0.177-5.851-0.267h-5.939l-0.354,22.337c-0.088,5.406,2.481,7.09,6.382,7.09c1.86,0,4.254-0.354,6.38-0.887
c0.089,0,0.445,0.71,0.178,0.799C216.841,64.81,211.877,65.962,209.396,65.962z"/>
<path d="M260,64.721c-3.458,0-6.116,0.089-8.598,0.442c-0.354,0.089-0.177-1.063,0-1.063c4.609-0.443,5.584-1.063,5.584-7.8
V43.004c0-7.8-1.861-11.078-6.472-11.078c-2.835,0-4.962,0.709-11.609,4.787V56.3c0,6.293,0.797,7.356,5.583,7.8
c0.176,0,0.354,1.152,0,1.063c-1.771-0.266-5.672-0.442-8.155-0.442c-3.367,0-7.533,0.089-9.925,0.442
c-0.355,0.089-0.179-1.063-0.09-1.063c6.115-0.622,6.736-0.886,6.736-7.8V13.578c0-5.85-1.063-6.913-5.673-5.407
c-0.177,0.089-0.532-0.62-0.177-0.797c3.545-1.95,8.774-4.698,11.612-7.356c0.089-0.089,0.797,0.178,0.709,0.443
c-0.445,1.684-0.62,9.484-0.533,12.764l-0.087,22.068c6.913-5.406,11.434-6.912,15.51-6.912c6.206,0,8.42,3.988,8.42,10.724V56.3
c0,6.382,0.356,7.356,6.648,7.8c0.177,0,0.265,1.152,0,1.063C267.71,64.897,262.481,64.721,260,64.721z"/>
<path d="M283.567,64.721c-3.367,0-7.268,0.089-9.75,0.442c-0.264,0.089-0.176-0.974,0-0.974c6.028-0.712,6.649-0.976,6.649-7.89
V41.32c0-5.85-1.064-6.912-5.673-5.317c-0.178,0-0.443-0.622-0.178-0.799c3.546-2.038,8.775-4.963,11.612-7.71
c0.087-0.09,0.797,0.177,0.797,0.443c-0.442,1.771-0.71,9.838-0.621,13.028V56.3c0,6.914,0.621,7.178,6.647,7.89
c0.177,0,0.267,1.062,0,0.974C290.569,64.81,286.936,64.721,283.567,64.721z M284.542,16.061c-1.95,0-3.545-1.772-3.545-3.724
c0-2.038,1.595-3.899,3.722-3.899c2.04,0,3.635,1.772,3.635,3.723C288.354,14.198,286.759,16.061,284.542,16.061z"/>
<path d="M330.096,42.119l-24.817,0.531c-0.089,0.975-0.177,2.039-0.177,3.103c0,11.966,6.736,16.752,13.206,16.752
c4.077,0,8.155-1.507,11.257-3.812c0.089-0.088,0.62,0.622,0.442,0.799c-3.102,3.635-9.04,6.471-14.624,6.471
c-9.838,0-16.573-7.27-16.573-17.551c0-10.636,9.395-20.03,18.523-20.03c8.687,0,13.03,6.469,13.03,11.61
C330.363,40.699,330.274,41.41,330.096,42.119z M315.028,30.507c-4.608,0-8.42,3.989-9.572,10.725l18.702-0.444
C324.069,36.18,320.79,30.507,315.028,30.507z"/>
<path d="M343.384,64.721c-3.368,0-7.002,0.089-9.482,0.442c-0.268,0.089-0.178-0.974,0-0.974c6.027-0.712,6.646-0.976,6.646-7.89
V13.578c0-5.85-1.063-6.913-5.672-5.407c-0.179,0.089-0.444-0.62-0.179-0.797c3.546-1.95,8.776-4.698,11.612-7.356
c0.088-0.089,0.798,0.178,0.798,0.443c-0.443,1.684-0.71,9.484-0.62,12.764V56.3c0,6.914,0.62,7.178,6.646,7.89
c0.179,0,0.267,1.062,0,0.974C350.652,64.81,346.841,64.721,343.384,64.721z"/>
<path d="M225.617,87.11c-2.216,0-5.497-3.724-9.483-3.724c-6.117,0-7.888,4.255-7.888,19.5v5.495h4.785
c3.723,0,6.206-0.089,7.267-0.354c0.533-0.177,0.533,3.279,0,3.192c-0.974-0.09-2.835-0.178-6.114-0.178h-5.938v23.662
c0,6.206,1.063,7.536,8.95,7.891c0.176,0,0.355,1.063,0,0.976c-1.86-0.267-9.04-0.443-11.521-0.443
c-3.368,0-7.445,0.088-9.927,0.443c-0.356,0.088-0.179-0.976,0-0.976c6.028-0.711,6.648-0.977,6.648-7.891v-23.662
c-2.04,0-6.294-0.089-7.179-0.089c-0.355,0.089-0.445-1.508-0.268-1.508c3.368-0.177,5.762-0.442,7.447-1.33v-3.544
c0-14.979,9.039-25.792,19.588-25.792c3.455,0,6.913,2.214,6.913,3.367C228.896,83.83,226.856,87.11,225.617,87.11z"/>
<path d="M257.519,120.525l-24.817,0.531c-0.089,0.977-0.177,2.04-0.177,3.104c0,11.964,6.734,16.75,13.205,16.75
c4.079,0,8.155-1.504,11.257-3.812c0.089-0.086,0.621,0.622,0.443,0.8c-3.104,3.635-9.041,6.47-14.625,6.47
c-9.837,0-16.575-7.27-16.575-17.55c0-10.636,9.396-20.03,18.525-20.03c8.686,0,13.031,6.47,13.031,11.609
C257.786,119.105,257.696,119.816,257.519,120.525z M242.45,108.914c-4.607,0-8.419,3.988-9.571,10.725l18.7-0.443
C251.491,114.587,248.212,108.914,242.45,108.914z"/>
<path d="M272.579,143.127c-3.37,0-7.002,0.088-9.483,0.443c-0.266,0.088-0.177-0.976,0-0.976c6.027-0.711,6.646-0.977,6.646-7.891
V91.985c0-5.851-1.063-6.914-5.672-5.408c-0.177,0.09-0.444-0.62-0.177-0.797c3.544-1.95,8.774-4.697,11.611-7.356
c0.088-0.089,0.797,0.178,0.797,0.443c-0.442,1.685-0.709,9.482-0.62,12.763v43.074c0,6.914,0.62,7.18,6.648,7.891
c0.177,0,0.265,1.063,0,0.976C279.847,143.215,276.035,143.127,272.579,143.127z"/>
<path d="M299.341,143.127c-3.369,0-7.001,0.088-9.482,0.443c-0.268,0.088-0.178-0.976,0-0.976
c6.026-0.711,6.646-0.977,6.646-7.891V91.985c0-5.851-1.063-6.914-5.674-5.408c-0.177,0.09-0.442-0.62-0.177-0.797
c3.546-1.95,8.775-4.697,11.61-7.356c0.089-0.089,0.799,0.178,0.799,0.443c-0.442,1.685-0.71,9.482-0.621,12.763v43.074
c0,6.914,0.621,7.18,6.647,7.891c0.179,0,0.267,1.063,0,0.976C306.609,143.215,302.798,143.127,299.341,143.127z"/>
<path d="M331.335,144.367c-11.081,0-18.172-8.687-18.172-18.17c0-10.016,7.269-19.41,19.146-19.41
c11.078,0,18.17,8.687,18.17,18.167C350.479,134.972,343.21,144.367,331.335,144.367z M330.358,108.735
c-7.18,0-10.813,6.56-10.813,13.918c0,12.318,5.495,19.765,13.738,19.765c7.18,0,10.726-6.561,10.726-13.915
C344.009,116.182,338.513,108.735,330.358,108.735z"/>
<path d="M405.336,116.182l-11.168,28.099c-0.177,0.44-1.064,0.44-1.241,0.087l-9.396-26.415l-10.369,26.328
c-0.179,0.44-1.064,0.44-1.241,0.087l-11.168-28.186c-2.395-6.026-4.166-7.446-8.687-7.8c-0.177,0-0.266-1.062,0.088-0.974
c1.686,0.264,6.382,0.354,8.863,0.354c3.458,0,6.472-0.09,8.953-0.354c0.266-0.088,0.089,0.974,0,0.974
c-4.698,0.532-5.583,1.597-3.103,7.8l7.711,19.499l7.978-20.474c-1.95-5.229-3.723-6.472-7.978-6.825
c-0.177,0-0.266-1.062,0.089-0.974c1.773,0.264,6.47,0.354,8.952,0.354c3.367,0,6.381-0.09,8.861-0.354
c0.268-0.088,0.18,0.974,0,0.974c-4.695,0.532-5.672,1.597-3.455,7.8l6.736,19.145l7.355-19.145
c2.395-6.026,1.685-7.268-3.102-7.8c-0.087,0-0.264-1.062,0-0.974c2.483,0.264,3.724,0.354,7.091,0.354
c2.48,0,5.052-0.09,6.825-0.354c0.267-0.088,0.178,0.974,0.089,0.974C409.147,108.735,407.462,110.599,405.336,116.182z"/>
<path d="M425.533,144.367c-3.812,0-7.532-1.063-10.189-2.572c-0.354-0.263-0.446-6.026-0.446-9.835
c0-0.269,0.887-0.177,0.976-0.091c2.128,7.891,6.56,10.902,11.169,10.902c4.432,0,6.292-2.571,6.292-6.471
c0-8.598-17.104-9.307-17.104-19.409c0-5.229,4.343-10.104,12.053-10.104c3.191,0,5.405,0.442,7.532,1.506
c0.445,0.266,0.891,5.229,0.891,8.865c0,0.177-0.978,0.177-0.978,0.088c-1.594-5.317-5.496-8.953-9.306-8.953
c-3.278,0-5.053,2.306-5.053,5.849c0,8.246,16.842,8.155,16.842,18.882C438.211,139.049,433.156,144.367,425.533,144.367z"/>
<path d="M475.96,143.127c-3.456,0-6.114,0.088-8.595,0.443c-0.356,0.088-0.177-1.063,0-1.063c4.606-0.443,5.583-1.066,5.583-7.803
v-13.293c0-7.801-1.862-11.079-6.472-11.079c-2.837,0-4.963,0.71-11.608,4.786v19.586c0,6.294,0.794,7.359,5.583,7.803
c0.177,0,0.354,1.151,0,1.063c-1.771-0.267-5.675-0.443-8.154-0.443c-3.37,0-7.533,0.088-9.927,0.443
c-0.355,0.088-0.178-1.063-0.089-1.063c6.114-0.623,6.735-0.889,6.735-7.803V91.985c0-5.851-1.063-6.914-5.673-5.408
c-0.179,0.09-0.531-0.62-0.179-0.797c3.548-1.95,8.776-4.697,11.611-7.356c0.092-0.089,0.8,0.178,0.712,0.443
c-0.443,1.685-0.62,9.482-0.535,12.763l-0.085,22.069c6.913-5.406,11.432-6.912,15.509-6.912c6.206,0,8.421,3.988,8.421,10.725
v17.192c0,6.383,0.356,7.359,6.646,7.803c0.18,0,0.267,1.151,0,1.063C483.672,143.304,478.443,143.127,475.96,143.127z"/>
<path d="M497.758,143.127c-3.367,0-7.269,0.088-9.749,0.443c-0.27,0.088-0.178-0.976,0-0.976c6.028-0.711,6.646-0.977,6.646-7.891
v-14.976c0-5.852-1.062-6.915-5.669-5.319c-0.18,0-0.445-0.621-0.18-0.799c3.546-2.037,8.775-4.963,11.612-7.71
c0.088-0.089,0.797,0.177,0.797,0.443c-0.442,1.771-0.709,9.838-0.62,13.028v15.332c0,6.914,0.62,7.18,6.646,7.891
c0.18,0,0.266,1.063,0,0.976C504.758,143.215,501.126,143.127,497.758,143.127z M498.734,94.467c-1.951,0-3.546-1.772-3.546-3.724
c0-2.038,1.595-3.898,3.724-3.898c2.04,0,3.634,1.771,3.634,3.722C502.546,92.604,500.952,94.467,498.734,94.467z"/>
<path d="M527.979,144.367c-1.95,0-3.901-0.177-5.938-0.797v13.648c0,6.735,0.887,7.27,9.04,7.532c0.178,0,0.354,1.066,0,1.066
c-2.482-0.178-9.132-0.178-11.611-0.089c-3.457,0.089-6.561,0.266-9.041,0.708c-0.266,0.092-0.177-0.975,0-0.975
c5.584-0.797,5.672-1.242,5.672-8.065v-16.31c-0.886-0.443-1.86-1.063-2.923-1.681l2.923-4.522v-15.067
c0-5.85-1.063-7.003-5.672-5.407c-0.088,0-0.531-0.621-0.177-0.799c3.546-2.037,7.889-5.229,10.726-7.888
c0.087-0.089,0.709,0.266,0.709,0.532c0.263,1.507,0.178,4.875,0.263,6.913c4.435-3.812,9.044-5.584,12.676-5.584
c8.601,0,15.069,7.534,15.069,16.396C549.693,133.644,540.298,144.367,527.979,144.367z M530.903,111.751
c-3.014,0-5.761,0.974-8.863,2.836v23.399c3.721,2.129,7.798,3.101,11.078,3.101c6.026,0,10.106-5.672,10.106-15.155
C543.225,116.537,537.106,111.751,530.903,111.751z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,491 +0,0 @@
/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
/*
The MIT License (MIT)
Copyright (c) 2007-2013 Einar Lielmanis and contributors.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
CSS Beautifier
---------------
Written by Harutyun Amirjanyan, (amirjanyan@gmail.com)
Based on code initially developed by: Einar Lielmanis, <einar@jsbeautifier.org>
http://jsbeautifier.org/
Usage:
css_beautify(source_text);
css_beautify(source_text, options);
The options are (default in brackets):
indent_size (4) indentation size,
indent_char (space) character to indent with,
selector_separator_newline (true) - separate selectors with newline or
not (e.g. "a,\nbr" or "a, br")
end_with_newline (false) - end with a newline
newline_between_rules (true) - add a new line after every css rule
e.g
css_beautify(css_source_text, {
'indent_size': 1,
'indent_char': '\t',
'selector_separator': ' ',
'end_with_newline': false,
'newline_between_rules': true
});
*/
// http://www.w3.org/TR/CSS21/syndata.html#tokenization
// http://www.w3.org/TR/css3-syntax/
(function() {
function css_beautify(source_text, options) {
options = options || {};
source_text = source_text || '';
// HACK: newline parsing inconsistent. This brute force normalizes the input.
source_text = source_text.replace(/\r\n|[\r\u2028\u2029]/g, '\n')
var indentSize = options.indent_size || 4;
var indentCharacter = options.indent_char || ' ';
var selectorSeparatorNewline = (options.selector_separator_newline === undefined) ? true : options.selector_separator_newline;
var end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
var newline_between_rules = (options.newline_between_rules === undefined) ? true : options.newline_between_rules;
var eol = options.eol ? options.eol : '\n';
// compatibility
if (typeof indentSize === "string") {
indentSize = parseInt(indentSize, 10);
}
if(options.indent_with_tabs){
indentCharacter = '\t';
indentSize = 1;
}
eol = eol.replace(/\\r/, '\r').replace(/\\n/, '\n')
// tokenizer
var whiteRe = /^\s+$/;
var wordRe = /[\w$\-_]/;
var pos = -1,
ch;
var parenLevel = 0;
function next() {
ch = source_text.charAt(++pos);
return ch || '';
}
function peek(skipWhitespace) {
var result = '';
var prev_pos = pos;
if (skipWhitespace) {
eatWhitespace();
}
result = source_text.charAt(pos + 1) || '';
pos = prev_pos - 1;
next();
return result;
}
function eatString(endChars) {
var start = pos;
while (next()) {
if (ch === "\\") {
next();
} else if (endChars.indexOf(ch) !== -1) {
break;
} else if (ch === "\n") {
break;
}
}
return source_text.substring(start, pos + 1);
}
function peekString(endChar) {
var prev_pos = pos;
var str = eatString(endChar);
pos = prev_pos - 1;
next();
return str;
}
function eatWhitespace() {
var result = '';
while (whiteRe.test(peek())) {
next();
result += ch;
}
return result;
}
function skipWhitespace() {
var result = '';
if (ch && whiteRe.test(ch)) {
result = ch;
}
while (whiteRe.test(next())) {
result += ch;
}
return result;
}
function eatComment(singleLine) {
var start = pos;
singleLine = peek() === "/";
next();
while (next()) {
if (!singleLine && ch === "*" && peek() === "/") {
next();
break;
} else if (singleLine && ch === "\n") {
return source_text.substring(start, pos);
}
}
return source_text.substring(start, pos) + ch;
}
function lookBack(str) {
return source_text.substring(pos - str.length, pos).toLowerCase() ===
str;
}
// Nested pseudo-class if we are insideRule
// and the next special character found opens
// a new block
function foundNestedPseudoClass() {
var openParen = 0;
for (var i = pos + 1; i < source_text.length; i++) {
var ch = source_text.charAt(i);
if (ch === "{") {
return true;
} else if (ch === '(') {
// pseudoclasses can contain ()
openParen += 1;
} else if (ch === ')') {
if (openParen == 0) {
return false;
}
openParen -= 1;
} else if (ch === ";" || ch === "}") {
return false;
}
}
return false;
}
// printer
var basebaseIndentString = source_text.match(/^[\t ]*/)[0];
var singleIndent = new Array(indentSize + 1).join(indentCharacter);
var indentLevel = 0;
var nestedLevel = 0;
function indent() {
indentLevel++;
basebaseIndentString += singleIndent;
}
function outdent() {
indentLevel--;
basebaseIndentString = basebaseIndentString.slice(0, -indentSize);
}
var print = {};
print["{"] = function(ch) {
print.singleSpace();
output.push(ch);
print.newLine();
};
print["}"] = function(ch) {
print.newLine();
output.push(ch);
print.newLine();
};
print._lastCharWhitespace = function() {
return whiteRe.test(output[output.length - 1]);
};
print.newLine = function(keepWhitespace) {
if (output.length) {
if (!keepWhitespace && output[output.length - 1] !== '\n') {
print.trim();
}
output.push('\n');
if (basebaseIndentString) {
output.push(basebaseIndentString);
}
}
};
print.singleSpace = function() {
if (output.length && !print._lastCharWhitespace()) {
output.push(' ');
}
};
print.preserveSingleSpace = function() {
if (isAfterSpace) {
print.singleSpace();
}
};
print.trim = function() {
while (print._lastCharWhitespace()) {
output.pop();
}
};
var output = [];
/*_____________________--------------------_____________________*/
var insideRule = false;
var insidePropertyValue = false;
var enteringConditionalGroup = false;
var top_ch = '';
var last_top_ch = '';
while (true) {
var whitespace = skipWhitespace();
var isAfterSpace = whitespace !== '';
var isAfterNewline = whitespace.indexOf('\n') !== -1;
last_top_ch = top_ch;
top_ch = ch;
if (!ch) {
break;
} else if (ch === '/' && peek() === '*') { /* css comment */
var header = indentLevel === 0;
if (isAfterNewline || header) {
print.newLine();
}
output.push(eatComment());
print.newLine();
if (header) {
print.newLine(true);
}
} else if (ch === '/' && peek() === '/') { // single line comment
if (!isAfterNewline && last_top_ch !== '{' ) {
print.trim();
}
print.singleSpace();
output.push(eatComment());
print.newLine();
} else if (ch === '@') {
print.preserveSingleSpace();
output.push(ch);
// strip trailing space, if present, for hash property checks
var variableOrRule = peekString(": ,;{}()[]/='\"");
if (variableOrRule.match(/[ :]$/)) {
// we have a variable or pseudo-class, add it and insert one space before continuing
next();
variableOrRule = eatString(": ").replace(/\s$/, '');
output.push(variableOrRule);
print.singleSpace();
}
variableOrRule = variableOrRule.replace(/\s$/, '')
// might be a nesting at-rule
if (variableOrRule in css_beautify.NESTED_AT_RULE) {
nestedLevel += 1;
if (variableOrRule in css_beautify.CONDITIONAL_GROUP_RULE) {
enteringConditionalGroup = true;
}
}
} else if (ch === '#' && peek() === '{') {
print.preserveSingleSpace();
output.push(eatString('}'));
} else if (ch === '{') {
if (peek(true) === '}') {
eatWhitespace();
next();
print.singleSpace();
output.push("{}");
print.newLine();
if (newline_between_rules && indentLevel === 0) {
print.newLine(true);
}
} else {
indent();
print["{"](ch);
// when entering conditional groups, only rulesets are allowed
if (enteringConditionalGroup) {
enteringConditionalGroup = false;
insideRule = (indentLevel > nestedLevel);
} else {
// otherwise, declarations are also allowed
insideRule = (indentLevel >= nestedLevel);
}
}
} else if (ch === '}') {
outdent();
print["}"](ch);
insideRule = false;
insidePropertyValue = false;
if (nestedLevel) {
nestedLevel--;
}
if (newline_between_rules && indentLevel === 0) {
print.newLine(true);
}
} else if (ch === ":") {
eatWhitespace();
if ((insideRule || enteringConditionalGroup) &&
!(lookBack("&") || foundNestedPseudoClass())) {
// 'property: value' delimiter
// which could be in a conditional group query
insidePropertyValue = true;
output.push(':');
print.singleSpace();
} else {
// sass/less parent reference don't use a space
// sass nested pseudo-class don't use a space
if (peek() === ":") {
// pseudo-element
next();
output.push("::");
} else {
// pseudo-class
output.push(':');
}
}
} else if (ch === '"' || ch === '\'') {
print.preserveSingleSpace();
output.push(eatString(ch));
} else if (ch === ';') {
insidePropertyValue = false;
output.push(ch);
print.newLine();
} else if (ch === '(') { // may be a url
if (lookBack("url")) {
output.push(ch);
eatWhitespace();
if (next()) {
if (ch !== ')' && ch !== '"' && ch !== '\'') {
output.push(eatString(')'));
} else {
pos--;
}
}
} else {
parenLevel++;
print.preserveSingleSpace();
output.push(ch);
eatWhitespace();
}
} else if (ch === ')') {
output.push(ch);
parenLevel--;
} else if (ch === ',') {
output.push(ch);
eatWhitespace();
if (selectorSeparatorNewline && !insidePropertyValue && parenLevel < 1) {
print.newLine();
} else {
print.singleSpace();
}
} else if (ch === ']') {
output.push(ch);
} else if (ch === '[') {
print.preserveSingleSpace();
output.push(ch);
} else if (ch === '=') { // no whitespace before or after
eatWhitespace()
ch = '=';
output.push(ch);
} else {
print.preserveSingleSpace();
output.push(ch);
}
}
var sweetCode = '';
if (basebaseIndentString) {
sweetCode += basebaseIndentString;
}
sweetCode += output.join('').replace(/[\r\n\t ]+$/, '');
// establish end_with_newline
if (end_with_newline) {
sweetCode += '\n';
}
if (eol != '\n') {
sweetCode = sweetCode.replace(/[\n]/g, eol);
}
return sweetCode;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule
css_beautify.NESTED_AT_RULE = {
"@page": true,
"@font-face": true,
"@keyframes": true,
// also in CONDITIONAL_GROUP_RULE below
"@media": true,
"@supports": true,
"@document": true
};
css_beautify.CONDITIONAL_GROUP_RULE = {
"@media": true,
"@supports": true,
"@document": true
};
/*global define */
if (typeof define === "function" && define.amd) {
// Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )
define([], function() {
return {
css_beautify: css_beautify
};
});
} else if (typeof exports !== "undefined") {
// Add support for CommonJS. Just put this file somewhere on your require.paths
// and you will be able to `var html_beautify = require("beautify").html_beautify`.
exports.css_beautify = css_beautify;
} else if (typeof window !== "undefined") {
// If we're running a web page and don't have either of the above, add our one global
window.css_beautify = css_beautify;
} else if (typeof global !== "undefined") {
// If we don't even have window, try global.
global.css_beautify = css_beautify;
}
}());

View File

@ -1,952 +0,0 @@
/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
/*
The MIT License (MIT)
Copyright (c) 2007-2013 Einar Lielmanis and contributors.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Style HTML
---------------
Written by Nochum Sossonko, (nsossonko@hotmail.com)
Based on code initially developed by: Einar Lielmanis, <einar@jsbeautifier.org>
http://jsbeautifier.org/
Usage:
style_html(html_source);
style_html(html_source, options);
The options are:
indent_inner_html (default false) indent <head> and <body> sections,
indent_size (default 4) indentation size,
indent_char (default space) character to indent with,
wrap_line_length (default 250) - maximum amount of characters per line (0 = disable)
brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "none"
put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line, or attempt to keep them where they are.
unformatted (defaults to inline tags) - list of tags, that shouldn't be reformatted
indent_scripts (default normal) - "keep"|"separate"|"normal"
preserve_newlines (default true) - whether existing line breaks before elements should be preserved
Only works before elements, not inside tags or for text.
max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk
indent_handlebars (default false) - format and indent {{#foo}} and {{/foo}}
end_with_newline (false) - end with a newline
extra_liners (default [head,body,/html]) -List of tags that should have an extra newline before them.
e.g.
style_html(html_source, {
'indent_inner_html': false,
'indent_size': 2,
'indent_char': ' ',
'wrap_line_length': 78,
'brace_style': 'expand',
'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u'],
'preserve_newlines': true,
'max_preserve_newlines': 5,
'indent_handlebars': false,
'extra_liners': ['/html']
});
*/
(function() {
function trim(s) {
return s.replace(/^\s+|\s+$/g, '');
}
function ltrim(s) {
return s.replace(/^\s+/g, '');
}
function rtrim(s) {
return s.replace(/\s+$/g,'');
}
function style_html(html_source, options, js_beautify, css_beautify) {
//Wrapper function to invoke all the necessary constructors and deal with the output.
var multi_parser,
indent_inner_html,
indent_size,
indent_character,
wrap_line_length,
brace_style,
unformatted,
preserve_newlines,
max_preserve_newlines,
indent_handlebars,
wrap_attributes,
wrap_attributes_indent_size,
end_with_newline,
extra_liners,
eol;
options = options || {};
// backwards compatibility to 1.3.4
if ((options.wrap_line_length === undefined || parseInt(options.wrap_line_length, 10) === 0) &&
(options.max_char !== undefined && parseInt(options.max_char, 10) !== 0)) {
options.wrap_line_length = options.max_char;
}
indent_inner_html = (options.indent_inner_html === undefined) ? false : options.indent_inner_html;
indent_size = (options.indent_size === undefined) ? 4 : parseInt(options.indent_size, 10);
indent_character = (options.indent_char === undefined) ? ' ' : options.indent_char;
brace_style = (options.brace_style === undefined) ? 'collapse' : options.brace_style;
wrap_line_length = parseInt(options.wrap_line_length, 10) === 0 ? 32786 : parseInt(options.wrap_line_length || 250, 10);
unformatted = options.unformatted || ['a', 'span', 'img', 'bdo', 'em', 'strong', 'dfn', 'code', 'samp', 'kbd',
'var', 'cite', 'abbr', 'acronym', 'q', 'sub', 'sup', 'tt', 'i', 'b', 'big', 'small', 'u', 's', 'strike',
'font', 'ins', 'del', 'pre', 'address', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;
max_preserve_newlines = preserve_newlines ?
(isNaN(parseInt(options.max_preserve_newlines, 10)) ? 32786 : parseInt(options.max_preserve_newlines, 10))
: 0;
indent_handlebars = (options.indent_handlebars === undefined) ? false : options.indent_handlebars;
wrap_attributes = (options.wrap_attributes === undefined) ? 'auto' : options.wrap_attributes;
wrap_attributes_indent_size = (options.wrap_attributes_indent_size === undefined) ? indent_size : parseInt(options.wrap_attributes_indent_size, 10) || indent_size;
end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
extra_liners = (typeof options.extra_liners == 'object') && options.extra_liners ?
options.extra_liners.concat() : (typeof options.extra_liners === 'string') ?
options.extra_liners.split(',') : 'head,body,/html'.split(',');
eol = options.eol ? options.eol : '\n';
if(options.indent_with_tabs){
indent_character = '\t';
indent_size = 1;
}
eol = eol.replace(/\\r/, '\r').replace(/\\n/, '\n')
function Parser() {
this.pos = 0; //Parser position
this.token = '';
this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
parent: 'parent1',
parentcount: 1,
parent1: ''
};
this.tag_type = '';
this.token_text = this.last_token = this.last_text = this.token_type = '';
this.newlines = 0;
this.indent_content = indent_inner_html;
this.Utils = { //Uilities made available to the various functions
whitespace: "\n\r\t ".split(''),
single_token: 'br,input,link,meta,source,!doctype,basefont,base,area,hr,wbr,param,img,isindex,embed'.split(','), //all the single tags for HTML
extra_liners: extra_liners, //for tags that need a line of whitespace before them
in_array: function(what, arr) {
for (var i = 0; i < arr.length; i++) {
if (what === arr[i]) {
return true;
}
}
return false;
}
};
// Return true if the given text is composed entirely of whitespace.
this.is_whitespace = function(text) {
for (var n = 0; n < text.length; text++) {
if (!this.Utils.in_array(text.charAt(n), this.Utils.whitespace)) {
return false;
}
}
return true;
};
this.traverse_whitespace = function() {
var input_char = '';
input_char = this.input.charAt(this.pos);
if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
this.newlines = 0;
while (this.Utils.in_array(input_char, this.Utils.whitespace)) {
if (preserve_newlines && input_char === '\n' && this.newlines <= max_preserve_newlines) {
this.newlines += 1;
}
this.pos++;
input_char = this.input.charAt(this.pos);
}
return true;
}
return false;
};
// Append a space to the given content (string array) or, if we are
// at the wrap_line_length, append a newline/indentation.
this.space_or_wrap = function(content) {
if (this.line_char_count >= this.wrap_line_length) { //insert a line when the wrap_line_length is reached
this.print_newline(false, content);
this.print_indentation(content);
} else {
this.line_char_count++;
content.push(' ');
}
};
this.get_content = function() { //function to capture regular content between tags
var input_char = '',
content = [],
space = false; //if a space is needed
while (this.input.charAt(this.pos) !== '<') {
if (this.pos >= this.input.length) {
return content.length ? content.join('') : ['', 'TK_EOF'];
}
if (this.traverse_whitespace()) {
this.space_or_wrap(content);
continue;
}
if (indent_handlebars) {
// Handlebars parsing is complicated.
// {{#foo}} and {{/foo}} are formatted tags.
// {{something}} should get treated as content, except:
// {{else}} specifically behaves like {{#if}} and {{/if}}
var peek3 = this.input.substr(this.pos, 3);
if (peek3 === '{{#' || peek3 === '{{/') {
// These are tags and not content.
break;
} else if (peek3 === '{{!') {
return [this.get_tag(), 'TK_TAG_HANDLEBARS_COMMENT'];
} else if (this.input.substr(this.pos, 2) === '{{') {
if (this.get_tag(true) === '{{else}}') {
break;
}
}
}
input_char = this.input.charAt(this.pos);
this.pos++;
this.line_char_count++;
content.push(input_char); //letter at-a-time (or string) inserted to an array
}
return content.length ? content.join('') : '';
};
this.get_contents_to = function(name) { //get the full content of a script or style to pass to js_beautify
if (this.pos === this.input.length) {
return ['', 'TK_EOF'];
}
var input_char = '';
var content = '';
var reg_match = new RegExp('</' + name + '\\s*>', 'igm');
reg_match.lastIndex = this.pos;
var reg_array = reg_match.exec(this.input);
var end_script = reg_array ? reg_array.index : this.input.length; //absolute end of script
if (this.pos < end_script) { //get everything in between the script tags
content = this.input.substring(this.pos, end_script);
this.pos = end_script;
}
return content;
};
this.record_tag = function(tag) { //function to record a tag and its parent in this.tags Object
if (this.tags[tag + 'count']) { //check for the existence of this tag type
this.tags[tag + 'count']++;
this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
} else { //otherwise initialize this tag type
this.tags[tag + 'count'] = 1;
this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
}
this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
};
this.retrieve_tag = function(tag) { //function to retrieve the opening tag to the corresponding closer
if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
var temp_parent = this.tags.parent; //check to see if it's a closable tag.
while (temp_parent) { //till we reach '' (the initial value);
if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
break;
}
temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
}
if (temp_parent) { //if we caught something
this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
}
delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
if (this.tags[tag + 'count'] === 1) {
delete this.tags[tag + 'count'];
} else {
this.tags[tag + 'count']--;
}
}
};
this.indent_to_tag = function(tag) {
// Match the indentation level to the last use of this tag, but don't remove it.
if (!this.tags[tag + 'count']) {
return;
}
var temp_parent = this.tags.parent;
while (temp_parent) {
if (tag + this.tags[tag + 'count'] === temp_parent) {
break;
}
temp_parent = this.tags[temp_parent + 'parent'];
}
if (temp_parent) {
this.indent_level = this.tags[tag + this.tags[tag + 'count']];
}
};
this.get_tag = function(peek) { //function to get a full tag and parse its type
var input_char = '',
content = [],
comment = '',
space = false,
first_attr = true,
tag_start, tag_end,
tag_start_char,
orig_pos = this.pos,
orig_line_char_count = this.line_char_count;
peek = peek !== undefined ? peek : false;
do {
if (this.pos >= this.input.length) {
if (peek) {
this.pos = orig_pos;
this.line_char_count = orig_line_char_count;
}
return content.length ? content.join('') : ['', 'TK_EOF'];
}
input_char = this.input.charAt(this.pos);
this.pos++;
if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
space = true;
continue;
}
if (input_char === "'" || input_char === '"') {
input_char += this.get_unformatted(input_char);
space = true;
}
if (input_char === '=') { //no space before =
space = false;
}
if (content.length && content[content.length - 1] !== '=' && input_char !== '>' && space) {
//no space after = or before >
this.space_or_wrap(content);
space = false;
if (!first_attr && wrap_attributes === 'force' && input_char !== '/') {
this.print_newline(true, content);
this.print_indentation(content);
for (var count = 0; count < wrap_attributes_indent_size; count++) {
content.push(indent_character);
}
}
for (var i = 0; i < content.length; i++) {
if (content[i] === ' ') {
first_attr = false;
break;
}
}
}
if (indent_handlebars && tag_start_char === '<') {
// When inside an angle-bracket tag, put spaces around
// handlebars not inside of strings.
if ((input_char + this.input.charAt(this.pos)) === '{{') {
input_char += this.get_unformatted('}}');
if (content.length && content[content.length - 1] !== ' ' && content[content.length - 1] !== '<') {
input_char = ' ' + input_char;
}
space = true;
}
}
if (input_char === '<' && !tag_start_char) {
tag_start = this.pos - 1;
tag_start_char = '<';
}
if (indent_handlebars && !tag_start_char) {
if (content.length >= 2 && content[content.length - 1] === '{' && content[content.length - 2] === '{') {
if (input_char === '#' || input_char === '/' || input_char === '!') {
tag_start = this.pos - 3;
} else {
tag_start = this.pos - 2;
}
tag_start_char = '{';
}
}
this.line_char_count++;
content.push(input_char); //inserts character at-a-time (or string)
if (content[1] && (content[1] === '!' || content[1] === '?' || content[1] === '%')) { //if we're in a comment, do something special
// We treat all comments as literals, even more than preformatted tags
// we just look for the appropriate close tag
content = [this.get_comment(tag_start)];
break;
}
if (indent_handlebars && content[1] && content[1] === '{' && content[2] && content[2] === '!') { //if we're in a comment, do something special
// We treat all comments as literals, even more than preformatted tags
// we just look for the appropriate close tag
content = [this.get_comment(tag_start)];
break;
}
if (indent_handlebars && tag_start_char === '{' && content.length > 2 && content[content.length - 2] === '}' && content[content.length - 1] === '}') {
break;
}
} while (input_char !== '>');
var tag_complete = content.join('');
var tag_index;
var tag_offset;
if (tag_complete.indexOf(' ') !== -1) { //if there's whitespace, thats where the tag name ends
tag_index = tag_complete.indexOf(' ');
} else if (tag_complete.charAt(0) === '{') {
tag_index = tag_complete.indexOf('}');
} else { //otherwise go with the tag ending
tag_index = tag_complete.indexOf('>');
}
if (tag_complete.charAt(0) === '<' || !indent_handlebars) {
tag_offset = 1;
} else {
tag_offset = tag_complete.charAt(2) === '#' ? 3 : 2;
}
var tag_check = tag_complete.substring(tag_offset, tag_index).toLowerCase();
if (tag_complete.charAt(tag_complete.length - 2) === '/' ||
this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
if (!peek) {
this.tag_type = 'SINGLE';
}
} else if (indent_handlebars && tag_complete.charAt(0) === '{' && tag_check === 'else') {
if (!peek) {
this.indent_to_tag('if');
this.tag_type = 'HANDLEBARS_ELSE';
this.indent_content = true;
this.traverse_whitespace();
}
} else if (this.is_unformatted(tag_check, unformatted)) { // do not reformat the "unformatted" tags
comment = this.get_unformatted('</' + tag_check + '>', tag_complete); //...delegate to get_unformatted function
content.push(comment);
tag_end = this.pos - 1;
this.tag_type = 'SINGLE';
} else if (tag_check === 'script' &&
(tag_complete.search('type') === -1 ||
(tag_complete.search('type') > -1 &&
tag_complete.search(/\b(text|application)\/(x-)?(javascript|ecmascript|jscript|livescript)/) > -1))) {
if (!peek) {
this.record_tag(tag_check);
this.tag_type = 'SCRIPT';
}
} else if (tag_check === 'style' &&
(tag_complete.search('type') === -1 ||
(tag_complete.search('type') > -1 && tag_complete.search('text/css') > -1))) {
if (!peek) {
this.record_tag(tag_check);
this.tag_type = 'STYLE';
}
} else if (tag_check.charAt(0) === '!') { //peek for <! comment
// for comments content is already correct.
if (!peek) {
this.tag_type = 'SINGLE';
this.traverse_whitespace();
}
} else if (!peek) {
if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
this.tag_type = 'END';
} else { //otherwise it's a start-tag
this.record_tag(tag_check); //push it on the tag stack
if (tag_check.toLowerCase() !== 'html') {
this.indent_content = true;
}
this.tag_type = 'START';
}
// Allow preserving of newlines after a start or end tag
if (this.traverse_whitespace()) {
this.space_or_wrap(content);
}
if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
this.print_newline(false, this.output);
if (this.output.length && this.output[this.output.length - 2] !== '\n') {
this.print_newline(true, this.output);
}
}
}
if (peek) {
this.pos = orig_pos;
this.line_char_count = orig_line_char_count;
}
return content.join(''); //returns fully formatted tag
};
this.get_comment = function(start_pos) { //function to return comment content in its entirety
// this is will have very poor perf, but will work for now.
var comment = '',
delimiter = '>',
matched = false;
this.pos = start_pos;
input_char = this.input.charAt(this.pos);
this.pos++;
while (this.pos <= this.input.length) {
comment += input_char;
// only need to check for the delimiter if the last chars match
if (comment.charAt(comment.length - 1) === delimiter.charAt(delimiter.length - 1) &&
comment.indexOf(delimiter) !== -1) {
break;
}
// only need to search for custom delimiter for the first few characters
if (!matched && comment.length < 10) {
if (comment.indexOf('<![if') === 0) { //peek for <![if conditional comment
delimiter = '<![endif]>';
matched = true;
} else if (comment.indexOf('<![cdata[') === 0) { //if it's a <[cdata[ comment...
delimiter = ']]>';
matched = true;
} else if (comment.indexOf('<![') === 0) { // some other ![ comment? ...
delimiter = ']>';
matched = true;
} else if (comment.indexOf('<!--') === 0) { // <!-- comment ...
delimiter = '-->';
matched = true;
} else if (comment.indexOf('{{!') === 0) { // {{! handlebars comment
delimiter = '}}';
matched = true;
} else if (comment.indexOf('<?') === 0) { // {{! handlebars comment
delimiter = '?>';
matched = true;
} else if (comment.indexOf('<%') === 0) { // {{! handlebars comment
delimiter = '%>';
matched = true;
}
}
input_char = this.input.charAt(this.pos);
this.pos++;
}
return comment;
};
this.get_unformatted = function(delimiter, orig_tag) { //function to return unformatted content in its entirety
if (orig_tag && orig_tag.toLowerCase().indexOf(delimiter) !== -1) {
return '';
}
var input_char = '';
var content = '';
var min_index = 0;
var space = true;
do {
if (this.pos >= this.input.length) {
return content;
}
input_char = this.input.charAt(this.pos);
this.pos++;
if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
if (!space) {
this.line_char_count--;
continue;
}
if (input_char === '\n' || input_char === '\r') {
content += '\n';
/* Don't change tab indention for unformatted blocks. If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array'
for (var i=0; i<this.indent_level; i++) {
content += this.indent_string;
}
space = false; //...and make sure other indentation is erased
*/
this.line_char_count = 0;
continue;
}
}
content += input_char;
this.line_char_count++;
space = true;
if (indent_handlebars && input_char === '{' && content.length && content.charAt(content.length - 2) === '{') {
// Handlebars expressions in strings should also be unformatted.
content += this.get_unformatted('}}');
// These expressions are opaque. Ignore delimiters found in them.
min_index = content.length;
}
} while (content.toLowerCase().indexOf(delimiter, min_index) === -1);
return content;
};
this.get_token = function() { //initial handler for token-retrieval
var token;
if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
var type = this.last_token.substr(7);
token = this.get_contents_to(type);
if (typeof token !== 'string') {
return token;
}
return [token, 'TK_' + type];
}
if (this.current_mode === 'CONTENT') {
token = this.get_content();
if (typeof token !== 'string') {
return token;
} else {
return [token, 'TK_CONTENT'];
}
}
if (this.current_mode === 'TAG') {
token = this.get_tag();
if (typeof token !== 'string') {
return token;
} else {
var tag_name_type = 'TK_TAG_' + this.tag_type;
return [token, tag_name_type];
}
}
};
this.get_full_indent = function(level) {
level = this.indent_level + level || 0;
if (level < 1) {
return '';
}
return Array(level + 1).join(this.indent_string);
};
this.is_unformatted = function(tag_check, unformatted) {
//is this an HTML5 block-level link?
if (!this.Utils.in_array(tag_check, unformatted)) {
return false;
}
if (tag_check.toLowerCase() !== 'a' || !this.Utils.in_array('a', unformatted)) {
return true;
}
//at this point we have an tag; is its first child something we want to remain
//unformatted?
var next_tag = this.get_tag(true /* peek. */ );
// test next_tag to see if it is just html tag (no external content)
var tag = (next_tag || "").match(/^\s*<\s*\/?([a-z]*)\s*[^>]*>\s*$/);
// if next_tag comes back but is not an isolated tag, then
// let's treat the 'a' tag as having content
// and respect the unformatted option
if (!tag || this.Utils.in_array(tag, unformatted)) {
return true;
} else {
return false;
}
};
this.printer = function(js_source, indent_character, indent_size, wrap_line_length, brace_style) { //handles input/output and some other printing functions
this.input = js_source || ''; //gets the input for the Parser
// HACK: newline parsing inconsistent. This brute force normalizes the input.
this.input = this.input.replace(/\r\n|[\r\u2028\u2029]/g, '\n')
this.output = [];
this.indent_character = indent_character;
this.indent_string = '';
this.indent_size = indent_size;
this.brace_style = brace_style;
this.indent_level = 0;
this.wrap_line_length = wrap_line_length;
this.line_char_count = 0; //count to see if wrap_line_length was exceeded
for (var i = 0; i < this.indent_size; i++) {
this.indent_string += this.indent_character;
}
this.print_newline = function(force, arr) {
this.line_char_count = 0;
if (!arr || !arr.length) {
return;
}
if (force || (arr[arr.length - 1] !== '\n')) { //we might want the extra line
if ((arr[arr.length - 1] !== '\n')) {
arr[arr.length - 1] = rtrim(arr[arr.length - 1]);
}
arr.push('\n');
}
};
this.print_indentation = function(arr) {
for (var i = 0; i < this.indent_level; i++) {
arr.push(this.indent_string);
this.line_char_count += this.indent_string.length;
}
};
this.print_token = function(text) {
// Avoid printing initial whitespace.
if (this.is_whitespace(text) && !this.output.length) {
return;
}
if (text || text !== '') {
if (this.output.length && this.output[this.output.length - 1] === '\n') {
this.print_indentation(this.output);
text = ltrim(text);
}
}
this.print_token_raw(text);
};
this.print_token_raw = function(text) {
// If we are going to print newlines, truncate trailing
// whitespace, as the newlines will represent the space.
if (this.newlines > 0) {
text = rtrim(text);
}
if (text && text !== '') {
if (text.length > 1 && text.charAt(text.length - 1) === '\n') {
// unformatted tags can grab newlines as their last character
this.output.push(text.slice(0, -1));
this.print_newline(false, this.output);
} else {
this.output.push(text);
}
}
for (var n = 0; n < this.newlines; n++) {
this.print_newline(n > 0, this.output);
}
this.newlines = 0;
};
this.indent = function() {
this.indent_level++;
};
this.unindent = function() {
if (this.indent_level > 0) {
this.indent_level--;
}
};
};
return this;
}
/*_____________________--------------------_____________________*/
multi_parser = new Parser(); //wrapping functions Parser
multi_parser.printer(html_source, indent_character, indent_size, wrap_line_length, brace_style); //initialize starting values
while (true) {
var t = multi_parser.get_token();
multi_parser.token_text = t[0];
multi_parser.token_type = t[1];
if (multi_parser.token_type === 'TK_EOF') {
break;
}
switch (multi_parser.token_type) {
case 'TK_TAG_START':
multi_parser.print_newline(false, multi_parser.output);
multi_parser.print_token(multi_parser.token_text);
if (multi_parser.indent_content) {
multi_parser.indent();
multi_parser.indent_content = false;
}
multi_parser.current_mode = 'CONTENT';
break;
case 'TK_TAG_STYLE':
case 'TK_TAG_SCRIPT':
multi_parser.print_newline(false, multi_parser.output);
multi_parser.print_token(multi_parser.token_text);
multi_parser.current_mode = 'CONTENT';
break;
case 'TK_TAG_END':
//Print new line only if the tag has no content and has child
if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
var tag_name = multi_parser.token_text.match(/\w+/)[0];
var tag_extracted_from_last_output = null;
if (multi_parser.output.length) {
tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length - 1].match(/(?:<|{{#)\s*(\w+)/);
}
if (tag_extracted_from_last_output === null ||
(tag_extracted_from_last_output[1] !== tag_name && !multi_parser.Utils.in_array(tag_extracted_from_last_output[1], unformatted))) {
multi_parser.print_newline(false, multi_parser.output);
}
}
multi_parser.print_token(multi_parser.token_text);
multi_parser.current_mode = 'CONTENT';
break;
case 'TK_TAG_SINGLE':
// Don't add a newline before elements that should remain unformatted.
var tag_check = multi_parser.token_text.match(/^\s*<([a-z-]+)/i);
if (!tag_check || !multi_parser.Utils.in_array(tag_check[1], unformatted)) {
multi_parser.print_newline(false, multi_parser.output);
}
multi_parser.print_token(multi_parser.token_text);
multi_parser.current_mode = 'CONTENT';
break;
case 'TK_TAG_HANDLEBARS_ELSE':
multi_parser.print_token(multi_parser.token_text);
if (multi_parser.indent_content) {
multi_parser.indent();
multi_parser.indent_content = false;
}
multi_parser.current_mode = 'CONTENT';
break;
case 'TK_TAG_HANDLEBARS_COMMENT':
multi_parser.print_token(multi_parser.token_text);
multi_parser.current_mode = 'TAG';
break;
case 'TK_CONTENT':
multi_parser.print_token(multi_parser.token_text);
multi_parser.current_mode = 'TAG';
break;
case 'TK_STYLE':
case 'TK_SCRIPT':
if (multi_parser.token_text !== '') {
multi_parser.print_newline(false, multi_parser.output);
var text = multi_parser.token_text,
_beautifier,
script_indent_level = 1;
if (multi_parser.token_type === 'TK_SCRIPT') {
_beautifier = typeof js_beautify === 'function' && js_beautify;
} else if (multi_parser.token_type === 'TK_STYLE') {
_beautifier = typeof css_beautify === 'function' && css_beautify;
}
if (options.indent_scripts === "keep") {
script_indent_level = 0;
} else if (options.indent_scripts === "separate") {
script_indent_level = -multi_parser.indent_level;
}
var indentation = multi_parser.get_full_indent(script_indent_level);
if (_beautifier) {
// call the Beautifier if avaliable
var Child_options = function() {
this.eol = '\n';
};
Child_options.prototype = options;
var child_options = new Child_options();
text = _beautifier(text.replace(/^\s*/, indentation), child_options);
} else {
// simply indent the string otherwise
var white = text.match(/^\s*/)[0];
var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
var reindent = multi_parser.get_full_indent(script_indent_level - _level);
text = text.replace(/^\s*/, indentation)
.replace(/\r\n|\r|\n/g, '\n' + reindent)
.replace(/\s+$/, '');
}
if (text) {
multi_parser.print_token_raw(text);
multi_parser.print_newline(true, multi_parser.output);
}
}
multi_parser.current_mode = 'TAG';
break;
default:
// We should not be getting here but we don't want to drop input on the floor
// Just output the text and move on
if (multi_parser.token_text !== '') {
multi_parser.print_token(multi_parser.token_text);
}
break;
}
multi_parser.last_token = multi_parser.token_type;
multi_parser.last_text = multi_parser.token_text;
}
var sweet_code = multi_parser.output.join('').replace(/[\r\n\t ]+$/, '');
// establish end_with_newline
if (end_with_newline) {
sweet_code += '\n';
}
if (eol != '\n') {
sweet_code = sweet_code.replace(/[\n]/g, eol);
}
return sweet_code;
}
if (typeof define === "function" && define.amd) {
// Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )
define(["require", "./beautify", "./beautify-css"], function(requireamd) {
var js_beautify = requireamd("./beautify");
var css_beautify = requireamd("./beautify-css");
return {
html_beautify: function(html_source, options) {
return style_html(html_source, options, js_beautify.js_beautify, css_beautify.css_beautify);
}
};
});
} else if (typeof exports !== "undefined") {
// Add support for CommonJS. Just put this file somewhere on your require.paths
// and you will be able to `var html_beautify = require("beautify").html_beautify`.
var js_beautify = require('./beautify.js');
var css_beautify = require('./beautify-css.js');
exports.html_beautify = function(html_source, options) {
return style_html(html_source, options, js_beautify.js_beautify, css_beautify.css_beautify);
};
} else if (typeof window !== "undefined") {
// If we're running a web page and don't have either of the above, add our one global
window.html_beautify = function(html_source, options) {
return style_html(html_source, options, window.js_beautify, window.css_beautify);
};
} else if (typeof global !== "undefined") {
// If we don't even have window, try global.
global.html_beautify = function(html_source, options) {
return style_html(html_source, options, global.js_beautify, global.css_beautify);
};
}
}());

File diff suppressed because it is too large Load Diff

View File

@ -1,103 +0,0 @@
//
// simple unpacker/deobfuscator for scripts messed up with javascriptobfuscator.com
// written by Einar Lielmanis <einar@jsbeautifier.org>
//
// usage:
//
// if (JavascriptObfuscator.detect(some_string)) {
// var unpacked = JavascriptObfuscator.unpack(some_string);
// }
//
//
var JavascriptObfuscator = {
detect: function (str) {
return /^var _0x[a-f0-9]+ ?\= ?\[/.test(str);
},
unpack: function (str) {
if (JavascriptObfuscator.detect(str)) {
var matches = /var (_0x[a-f\d]+) ?\= ?\[(.*?)\];/.exec(str);
if (matches) {
var var_name = matches[1];
var strings = JavascriptObfuscator._smart_split(matches[2]);
str = str.substring(matches[0].length);
for (var k in strings) {
str = str.replace(new RegExp(var_name + '\\[' + k + '\\]', 'g'),
JavascriptObfuscator._fix_quotes(JavascriptObfuscator._unescape(strings[k])));
}
}
}
return str;
},
_fix_quotes: function(str) {
var matches = /^"(.*)"$/.exec(str);
if (matches) {
str = matches[1];
str = "'" + str.replace(/'/g, "\\'") + "'";
}
return str;
},
_smart_split: function(str) {
var strings = [];
var pos = 0;
while (pos < str.length) {
if (str.charAt(pos) == '"') {
// new word
var word = '';
pos += 1;
while (pos < str.length) {
if (str.charAt(pos) == '"') {
break;
}
if (str.charAt(pos) == '\\') {
word += '\\';
pos++;
}
word += str.charAt(pos);
pos++;
}
strings.push('"' + word + '"');
}
pos += 1;
}
return strings;
},
_unescape: function (str) {
// inefficient if used repeatedly or on small strings, but wonderful on single large chunk of text
for (var i = 32; i < 128; i++) {
str = str.replace(new RegExp('\\\\x' + i.toString(16), 'ig'), String.fromCharCode(i));
}
str = str.replace(/\\x09/g, "\t");
return str;
},
run_tests: function (sanity_test) {
var t = sanity_test || new SanityTest();
t.test_function(JavascriptObfuscator._smart_split, "JavascriptObfuscator._smart_split");
t.expect('', []);
t.expect('"a", "b"', ['"a"', '"b"']);
t.expect('"aaa","bbbb"', ['"aaa"', '"bbbb"']);
t.expect('"a", "b\\\""', ['"a"', '"b\\\""']);
t.test_function(JavascriptObfuscator._unescape, 'JavascriptObfuscator._unescape');
t.expect('\\x40', '@');
t.expect('\\x10', '\\x10');
t.expect('\\x1', '\\x1');
t.expect("\\x61\\x62\\x22\\x63\\x64", 'ab"cd');
t.test_function(JavascriptObfuscator.detect, 'JavascriptObfuscator.detect');
t.expect('', false);
t.expect('abcd', false);
t.expect('var _0xaaaa', false);
t.expect('var _0xaaaa = ["a", "b"]', true);
t.expect('var _0xaaaa=["a", "b"]', true);
t.expect('var _0x1234=["a","b"]', true);
return t;
}
};

View File

@ -1,90 +0,0 @@
//
// simple unpacker/deobfuscator for scripts messed up with myobfuscate.com
// You really don't want to obfuscate your scripts there: they're tracking
// your unpackings, your script gets turned into something like this,
// as of 2011-04-25:
/*
var _escape = 'your_script_escaped';
var _111 = document.createElement('script');
_111.src = 'http://api.www.myobfuscate.com/?getsrc=ok' +
'&ref=' + encodeURIComponent(document.referrer) +
'&url=' + encodeURIComponent(document.URL);
var 000 = document.getElementsByTagName('head')[0];
000.appendChild(_111);
document.write(unescape(_escape));
*/
//
// written by Einar Lielmanis <einar@jsbeautifier.org>
//
// usage:
//
// if (MyObfuscate.detect(some_string)) {
// var unpacked = MyObfuscate.unpack(some_string);
// }
//
//
var MyObfuscate = {
detect: function (str) {
if (/^var _?[0O1lI]{3}\=('|\[).*\)\)\);/.test(str)) {
return true;
}
if (/^function _?[0O1lI]{3}\(_/.test(str) && /eval\(/.test(str)) {
return true;
}
return false;
},
unpack: function (str) {
if (MyObfuscate.detect(str)) {
var __eval = eval;
try {
eval = function (unpacked) {
if (MyObfuscate.starts_with(unpacked, 'var _escape')) {
// fetch the urlencoded stuff from the script,
var matches = /'([^']*)'/.exec(unpacked);
var unescaped = unescape(matches[1]);
if (MyObfuscate.starts_with(unescaped, '<script>')) {
unescaped = unescaped.substr(8, unescaped.length - 8);
}
if (MyObfuscate.ends_with(unescaped, '</script>')) {
unescaped = unescaped.substr(0, unescaped.length - 9);
}
unpacked = unescaped;
}
// throw to terminate the script
unpacked = "// Unpacker warning: be careful when using myobfuscate.com for your projects:\n" +
"// scripts obfuscated by the free online version may call back home.\n" +
"\n//\n" + unpacked;
throw unpacked;
};
__eval(str); // should throw
} catch (e) {
// well, it failed. we'll just return the original, instead of crashing on user.
if (typeof e === "string") {
str = e;
}
}
eval = __eval;
}
return str;
},
starts_with: function (str, what) {
return str.substr(0, what.length) === what;
},
ends_with: function (str, what) {
return str.substr(str.length - what.length, what.length) === what;
},
run_tests: function (sanity_test) {
var t = sanity_test || new SanityTest();
return t;
}
};

View File

@ -1,80 +0,0 @@
//
// Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier
// written by Einar Lielmanis <einar@jsbeautifier.org>
//
// Coincidentally, it can defeat a couple of other eval-based compressors.
//
// usage:
//
// if (P_A_C_K_E_R.detect(some_string)) {
// var unpacked = P_A_C_K_E_R.unpack(some_string);
// }
//
//
var P_A_C_K_E_R = {
detect: function (str) {
return (P_A_C_K_E_R.get_chunks(str).length > 0);
},
get_chunks: function(str) {
var chunks = str.match(/eval\(\(?function\(.*?(,0,\{\}\)\)|split\('\|'\)\)\))($|\n)/g);
return chunks ? chunks : [];
},
unpack: function (str) {
var chunks = P_A_C_K_E_R.get_chunks(str),
chunk;
for(var i = 0; i < chunks.length; i++) {
chunk = chunks[i].replace(/\n$/, '');
str = str.split(chunk).join( P_A_C_K_E_R.unpack_chunk(chunk) );
}
return str;
},
unpack_chunk: function (str) {
var unpacked_source = '';
var __eval = eval;
if (P_A_C_K_E_R.detect(str)) {
try {
eval = function (s) { unpacked_source += s; return unpacked_source; };
__eval(str);
if (typeof unpacked_source == 'string' && unpacked_source) {
str = unpacked_source;
}
} catch (e) {
// well, it failed. we'll just return the original, instead of crashing on user.
}
}
eval = __eval;
return str;
},
run_tests: function (sanity_test) {
var t = sanity_test || new SanityTest(),
pk1 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'var||a'.split('|'),0,{}))",
unpk1 = 'var a=1',
pk2 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'foo||b'.split('|'),0,{}))",
unpk2 = 'foo b=1',
pk_broken = "eval(function(p,a,c,k,e,r){BORKBORK;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'var||a'.split('|'),0,{}))";
pk3 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1{}))',3,3,'var||a'.split('|'),0,{}))",
unpk3 = 'var a=1{}))',
t.test_function(P_A_C_K_E_R.detect, "P_A_C_K_E_R.detect");
t.expect('', false);
t.expect('var a = b', false);
t.test_function(P_A_C_K_E_R.unpack, "P_A_C_K_E_R.unpack");
t.expect(pk_broken, pk_broken);
t.expect(pk1, unpk1);
t.expect(pk2, unpk2);
t.expect(pk3, unpk3);
var filler = '\nfiller\n';
t.expect(filler + pk1 + "\n" + pk_broken + filler + pk2 + filler, filler + unpk1 + "\n" + pk_broken + filler + unpk2 + filler);
return t;
}
};

View File

@ -1,73 +0,0 @@
/*global unescape */
/*jshint curly: false, scripturl: true */
//
// trivial bookmarklet/escaped script detector for the javascript beautifier
// written by Einar Lielmanis <einar@jsbeautifier.org>
//
// usage:
//
// if (Urlencoded.detect(some_string)) {
// var unpacked = Urlencoded.unpack(some_string);
// }
//
//
var isNode = (typeof module !== 'undefined' && module.exports);
if (isNode) {
var SanityTest = require(__dirname + '/../../test/sanitytest');
}
var Urlencoded = {
detect: function (str) {
// the fact that script doesn't contain any space, but has %20 instead
// should be sufficient check for now.
if (str.indexOf(' ') == -1) {
if (str.indexOf('%2') != -1) return true;
if (str.replace(/[^%]+/g, '').length > 3) return true;
}
return false;
},
unpack: function (str) {
if (Urlencoded.detect(str)) {
if (str.indexOf('%2B') != -1 || str.indexOf('%2b') != -1) {
// "+" escaped as "%2B"
return unescape(str.replace(/\+/g, '%20'));
} else {
return unescape(str);
}
}
return str;
},
run_tests: function (sanity_test) {
var t = sanity_test || new SanityTest();
t.test_function(Urlencoded.detect, "Urlencoded.detect");
t.expect('', false);
t.expect('var a = b', false);
t.expect('var%20a+=+b', true);
t.expect('var%20a=b', true);
t.expect('var%20%21%22', true);
t.expect('javascript:(function(){var%20whatever={init:function(){alert(%22a%22+%22b%22)}};whatever.init()})();', true);
t.test_function(Urlencoded.unpack, 'Urlencoded.unpack');
t.expect('javascript:(function(){var%20whatever={init:function(){alert(%22a%22+%22b%22)}};whatever.init()})();',
'javascript:(function(){var whatever={init:function(){alert("a"+"b")}};whatever.init()})();'
);
t.expect('', '');
t.expect('abcd', 'abcd');
t.expect('var a = b', 'var a = b');
t.expect('var%20a=b', 'var a=b');
t.expect('var%20a=b+1', 'var a=b+1');
t.expect('var%20a=b%2b1', 'var a=b+1');
return t;
}
};
if (isNode) {
module.exports = Urlencoded;
}

View File

@ -1,325 +0,0 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
@-moz-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@-webkit-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
/* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
height: 100%;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
border-right: none;
width: 0;
}
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror ::selection { background: #d7d4f0; }
.CodeMirror ::-moz-selection { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
.cm-s-colorforth.CodeMirror { background: #000000; color: #f8f8f8; }
.cm-s-colorforth .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
.cm-s-colorforth .CodeMirror-guttermarker { color: #FFBD40; }
.cm-s-colorforth .CodeMirror-guttermarker-subtle { color: #78846f; }
.cm-s-colorforth .CodeMirror-linenumber { color: #bababa; }
.cm-s-colorforth .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-colorforth span.cm-comment { color: #ededed; }
.cm-s-colorforth span.cm-def { color: #ff1c1c; font-weight:bold; }
.cm-s-colorforth span.cm-keyword { color: #ffd900; }
.cm-s-colorforth span.cm-builtin { color: #00d95a; }
.cm-s-colorforth span.cm-variable { color: #73ff00; }
.cm-s-colorforth span.cm-string { color: #007bff; }
.cm-s-colorforth span.cm-number { color: #00c4ff; }
.cm-s-colorforth span.cm-atom { color: #606060; }
.cm-s-colorforth span.cm-variable-2 { color: #EEE; }
.cm-s-colorforth span.cm-variable-3 { color: #DDD; }
.cm-s-colorforth span.cm-property {}
.cm-s-colorforth span.cm-operator {}
.cm-s-colorforth span.cm-meta { color: yellow; }
.cm-s-colorforth span.cm-qualifier { color: #FFF700; }
.cm-s-colorforth span.cm-tag { color: lime; }
.cm-s-colorforth span.cm-bracket { color: green; }
.cm-s-colorforth span.cm-attribute { color: #FFF700; }
.cm-s-colorforth span.cm-error { color: #f00; }
.cm-s-colorforth .CodeMirror-selected { background: #333d53 !important; }
.cm-s-colorforth span.cm-compilation { background: rgba(255, 255, 255, 0.12); }
.cm-s-colorforth .CodeMirror-activeline-background {background: #253540 !important;}

View File

@ -1,33 +0,0 @@
.cm-s-colorforth.CodeMirror { background: #000000; color: #f8f8f8; }
.cm-s-colorforth .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
.cm-s-colorforth .CodeMirror-guttermarker { color: #FFBD40; }
.cm-s-colorforth .CodeMirror-guttermarker-subtle { color: #78846f; }
.cm-s-colorforth .CodeMirror-linenumber { color: #bababa; }
.cm-s-colorforth .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-colorforth span.cm-comment { color: #ededed; }
.cm-s-colorforth span.cm-def { color: #ff1c1c; font-weight:bold; }
.cm-s-colorforth span.cm-keyword { color: #ffd900; }
.cm-s-colorforth span.cm-builtin { color: #00d95a; }
.cm-s-colorforth span.cm-variable { color: #73ff00; }
.cm-s-colorforth span.cm-string { color: #007bff; }
.cm-s-colorforth span.cm-number { color: #00c4ff; }
.cm-s-colorforth span.cm-atom { color: #606060; }
.cm-s-colorforth span.cm-variable-2 { color: #EEE; }
.cm-s-colorforth span.cm-variable-3 { color: #DDD; }
.cm-s-colorforth span.cm-property {}
.cm-s-colorforth span.cm-operator {}
.cm-s-colorforth span.cm-meta { color: yellow; }
.cm-s-colorforth span.cm-qualifier { color: #FFF700; }
.cm-s-colorforth span.cm-bracket { color: #cc7; }
.cm-s-colorforth span.cm-tag { color: #FFBD40; }
.cm-s-colorforth span.cm-attribute { color: #FFF700; }
.cm-s-colorforth span.cm-error { color: #f00; }
.cm-s-colorforth .CodeMirror-selected { background: #333d53 !important; }
.cm-s-colorforth span.cm-compilation { background: rgba(255, 255, 255, 0.12); }
.cm-s-colorforth .CodeMirror-activeline-background {background: #253540 !important;}

View File

@ -1,754 +0,0 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("css", function(config, parserConfig) {
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
var indentUnit = config.indentUnit,
tokenHooks = parserConfig.tokenHooks,
documentTypes = parserConfig.documentTypes || {},
mediaTypes = parserConfig.mediaTypes || {},
mediaFeatures = parserConfig.mediaFeatures || {},
propertyKeywords = parserConfig.propertyKeywords || {},
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
fontProperties = parserConfig.fontProperties || {},
counterDescriptors = parserConfig.counterDescriptors || {},
colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {},
allowNested = parserConfig.allowNested;
var type, override;
function ret(style, tp) { type = tp; return style; }
// Tokenizers
function tokenBase(stream, state) {
var ch = stream.next();
if (tokenHooks[ch]) {
var result = tokenHooks[ch](stream, state);
if (result !== false) return result;
}
if (ch == "@") {
stream.eatWhile(/[\w\\\-]/);
return ret("def", stream.current());
} else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
return ret(null, "compare");
} else if (ch == "\"" || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
} else if (ch == "#") {
stream.eatWhile(/[\w\\\-]/);
return ret("atom", "hash");
} else if (ch == "!") {
stream.match(/^\s*\w*/);
return ret("keyword", "important");
} else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
} else if (ch === "-") {
if (/[\d.]/.test(stream.peek())) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
} else if (stream.match(/^-[\w\\\-]+/)) {
stream.eatWhile(/[\w\\\-]/);
if (stream.match(/^\s*:/, false))
return ret("variable-2", "variable-definition");
return ret("variable-2", "variable");
} else if (stream.match(/^\w+-/)) {
return ret("meta", "meta");
}
} else if (/[,+>*\/]/.test(ch)) {
return ret(null, "select-op");
} else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
return ret("qualifier", "qualifier");
} else if (/[:;{}\[\]\(\)]/.test(ch)) {
return ret(null, ch);
} else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
(ch == "d" && stream.match("omain(")) ||
(ch == "r" && stream.match("egexp("))) {
stream.backUp(1);
state.tokenize = tokenParenthesized;
return ret("property", "word");
} else if (/[\w\\\-]/.test(ch)) {
stream.eatWhile(/[\w\\\-]/);
return ret("property", "word");
} else {
return ret(null, null);
}
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && !escaped) {
if (quote == ")") stream.backUp(1);
break;
}
escaped = !escaped && ch == "\\";
}
if (ch == quote || !escaped && quote != ")") state.tokenize = null;
return ret("string", "string");
};
}
function tokenParenthesized(stream, state) {
stream.next(); // Must be '('
if (!stream.match(/\s*[\"\')]/, false))
state.tokenize = tokenString(")");
else
state.tokenize = null;
return ret(null, "(");
}
// Context management
function Context(type, indent, prev) {
this.type = type;
this.indent = indent;
this.prev = prev;
}
function pushContext(state, stream, type) {
state.context = new Context(type, stream.indentation() + indentUnit, state.context);
return type;
}
function popContext(state) {
state.context = state.context.prev;
return state.context.type;
}
function pass(type, stream, state) {
return states[state.context.type](type, stream, state);
}
function popAndPass(type, stream, state, n) {
for (var i = n || 1; i > 0; i--)
state.context = state.context.prev;
return pass(type, stream, state);
}
// Parser
function wordAsValue(stream) {
var word = stream.current().toLowerCase();
if (valueKeywords.hasOwnProperty(word))
override = "atom";
else if (colorKeywords.hasOwnProperty(word))
override = "keyword";
else
override = "variable";
}
var states = {};
states.top = function(type, stream, state) {
if (type == "{") {
return pushContext(state, stream, "block");
} else if (type == "}" && state.context.prev) {
return popContext(state);
} else if (/@(media|supports|(-moz-)?document)/.test(type)) {
return pushContext(state, stream, "atBlock");
} else if (/@(font-face|counter-style)/.test(type)) {
state.stateArg = type;
return "restricted_atBlock_before";
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
return "keyframes";
} else if (type && type.charAt(0) == "@") {
return pushContext(state, stream, "at");
} else if (type == "hash") {
override = "builtin";
} else if (type == "word") {
override = "tag";
} else if (type == "variable-definition") {
return "maybeprop";
} else if (type == "interpolation") {
return pushContext(state, stream, "interpolation");
} else if (type == ":") {
return "pseudo";
} else if (allowNested && type == "(") {
return pushContext(state, stream, "parens");
}
return state.context.type;
};
states.block = function(type, stream, state) {
if (type == "word") {
var word = stream.current().toLowerCase();
if (propertyKeywords.hasOwnProperty(word)) {
override = "property";
return "maybeprop";
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
override = "string-2";
return "maybeprop";
} else if (allowNested) {
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
return "block";
} else {
override += " error";
return "maybeprop";
}
} else if (type == "meta") {
return "block";
} else if (!allowNested && (type == "hash" || type == "qualifier")) {
override = "error";
return "block";
} else {
return states.top(type, stream, state);
}
};
states.maybeprop = function(type, stream, state) {
if (type == ":") return pushContext(state, stream, "prop");
return pass(type, stream, state);
};
states.prop = function(type, stream, state) {
if (type == ";") return popContext(state);
if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
if (type == "}" || type == "{") return popAndPass(type, stream, state);
if (type == "(") return pushContext(state, stream, "parens");
if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
override += " error";
} else if (type == "word") {
wordAsValue(stream);
} else if (type == "interpolation") {
return pushContext(state, stream, "interpolation");
}
return "prop";
};
states.propBlock = function(type, _stream, state) {
if (type == "}") return popContext(state);
if (type == "word") { override = "property"; return "maybeprop"; }
return state.context.type;
};
states.parens = function(type, stream, state) {
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == ")") return popContext(state);
if (type == "(") return pushContext(state, stream, "parens");
if (type == "interpolation") return pushContext(state, stream, "interpolation");
if (type == "word") wordAsValue(stream);
return "parens";
};
states.pseudo = function(type, stream, state) {
if (type == "word") {
override = "variable-3";
return state.context.type;
}
return pass(type, stream, state);
};
states.atBlock = function(type, stream, state) {
if (type == "(") return pushContext(state, stream, "atBlock_parens");
if (type == "}") return popAndPass(type, stream, state);
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
if (type == "word") {
var word = stream.current().toLowerCase();
if (word == "only" || word == "not" || word == "and" || word == "or")
override = "keyword";
else if (documentTypes.hasOwnProperty(word))
override = "tag";
else if (mediaTypes.hasOwnProperty(word))
override = "attribute";
else if (mediaFeatures.hasOwnProperty(word))
override = "property";
else if (propertyKeywords.hasOwnProperty(word))
override = "property";
else if (nonStandardPropertyKeywords.hasOwnProperty(word))
override = "string-2";
else if (valueKeywords.hasOwnProperty(word))
override = "atom";
else
override = "error";
}
return state.context.type;
};
states.atBlock_parens = function(type, stream, state) {
if (type == ")") return popContext(state);
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
return states.atBlock(type, stream, state);
};
states.restricted_atBlock_before = function(type, stream, state) {
if (type == "{")
return pushContext(state, stream, "restricted_atBlock");
if (type == "word" && state.stateArg == "@counter-style") {
override = "variable";
return "restricted_atBlock_before";
}
return pass(type, stream, state);
};
states.restricted_atBlock = function(type, stream, state) {
if (type == "}") {
state.stateArg = null;
return popContext(state);
}
if (type == "word") {
if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
(state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
override = "error";
else
override = "property";
return "maybeprop";
}
return "restricted_atBlock";
};
states.keyframes = function(type, stream, state) {
if (type == "word") { override = "variable"; return "keyframes"; }
if (type == "{") return pushContext(state, stream, "top");
return pass(type, stream, state);
};
states.at = function(type, stream, state) {
if (type == ";") return popContext(state);
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == "word") override = "tag";
else if (type == "hash") override = "builtin";
return "at";
};
states.interpolation = function(type, stream, state) {
if (type == "}") return popContext(state);
if (type == "{" || type == ";") return popAndPass(type, stream, state);
if (type == "word") override = "variable";
else if (type != "variable" && type != "(" && type != ")") override = "error";
return "interpolation";
};
return {
startState: function(base) {
return {tokenize: null,
state: "top",
stateArg: null,
context: new Context("top", base || 0, null)};
},
token: function(stream, state) {
if (!state.tokenize && stream.eatSpace()) return null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style && typeof style == "object") {
type = style[1];
style = style[0];
}
override = style;
state.state = states[state.state](type, stream, state);
return override;
},
indent: function(state, textAfter) {
var cx = state.context, ch = textAfter && textAfter.charAt(0);
var indent = cx.indent;
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
if (cx.prev &&
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "restricted_atBlock") ||
ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
ch == "{" && (cx.type == "at" || cx.type == "atBlock"))) {
indent = cx.indent - indentUnit;
cx = cx.prev;
}
return indent;
},
electricChars: "}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
fold: "brace"
};
});
function keySet(array) {
var keys = {};
for (var i = 0; i < array.length; ++i) {
keys[array[i]] = true;
}
return keys;
}
var documentTypes_ = [
"domain", "regexp", "url", "url-prefix"
], documentTypes = keySet(documentTypes_);
var mediaTypes_ = [
"all", "aural", "braille", "handheld", "print", "projection", "screen",
"tty", "tv", "embossed"
], mediaTypes = keySet(mediaTypes_);
var mediaFeatures_ = [
"width", "min-width", "max-width", "height", "min-height", "max-height",
"device-width", "min-device-width", "max-device-width", "device-height",
"min-device-height", "max-device-height", "aspect-ratio",
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
"max-color", "color-index", "min-color-index", "max-color-index",
"monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid"
], mediaFeatures = keySet(mediaFeatures_);
var propertyKeywords_ = [
"align-content", "align-items", "align-self", "alignment-adjust",
"alignment-baseline", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-fill-mode",
"animation-iteration-count", "animation-name", "animation-play-state",
"animation-timing-function", "appearance", "azimuth", "backface-visibility",
"background", "background-attachment", "background-clip", "background-color",
"background-image", "background-origin", "background-position",
"background-repeat", "background-size", "baseline-shift", "binding",
"bleed", "bookmark-label", "bookmark-level", "bookmark-state",
"bookmark-target", "border", "border-bottom", "border-bottom-color",
"border-bottom-left-radius", "border-bottom-right-radius",
"border-bottom-style", "border-bottom-width", "border-collapse",
"border-color", "border-image", "border-image-outset",
"border-image-repeat", "border-image-slice", "border-image-source",
"border-image-width", "border-left", "border-left-color",
"border-left-style", "border-left-width", "border-radius", "border-right",
"border-right-color", "border-right-style", "border-right-width",
"border-spacing", "border-style", "border-top", "border-top-color",
"border-top-left-radius", "border-top-right-radius", "border-top-style",
"border-top-width", "border-width", "bottom", "box-decoration-break",
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
"caption-side", "clear", "clip", "color", "color-profile", "column-count",
"column-fill", "column-gap", "column-rule", "column-rule-color",
"column-rule-style", "column-rule-width", "column-span", "column-width",
"columns", "content", "counter-increment", "counter-reset", "crop", "cue",
"cue-after", "cue-before", "cursor", "direction", "display",
"dominant-baseline", "drop-initial-after-adjust",
"drop-initial-after-align", "drop-initial-before-adjust",
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
"float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
"font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
"font-stretch", "font-style", "font-synthesis", "font-variant",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
"grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
"grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
"grid-template", "grid-template-areas", "grid-template-columns",
"grid-template-rows", "hanging-punctuation", "height", "hyphens",
"icon", "image-orientation", "image-rendering", "image-resolution",
"inline-box-align", "justify-content", "left", "letter-spacing",
"line-break", "line-height", "line-stacking", "line-stacking-ruby",
"line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin",
"margin-bottom", "margin-left", "margin-right", "margin-top",
"marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
"nav-left", "nav-right", "nav-up", "object-fit", "object-position",
"opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"page", "page-break-after", "page-break-before", "page-break-inside",
"page-policy", "pause", "pause-after", "pause-before", "perspective",
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
"presentation-level", "punctuation-trim", "quotes", "region-break-after",
"region-break-before", "region-break-inside", "region-fragment",
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
"ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
"shape-outside", "size", "speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color",
"text-emphasis-position", "text-emphasis-style", "text-height",
"text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
"text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
"text-wrap", "top", "transform", "transform-origin", "transform-style",
"transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "unicode-bidi",
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
"word-spacing", "word-wrap", "z-index",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
"glyph-orientation-vertical", "text-anchor", "writing-mode"
], propertyKeywords = keySet(propertyKeywords_);
var nonStandardPropertyKeywords_ = [
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
"scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
"searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
"searchfield-results-decoration", "zoom"
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
var fontProperties_ = [
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
"font-stretch", "font-weight", "font-style"
], fontProperties = keySet(fontProperties_);
var counterDescriptors_ = [
"additive-symbols", "fallback", "negative", "pad", "prefix", "range",
"speak-as", "suffix", "symbols", "system"
], counterDescriptors = keySet(counterDescriptors_);
var colorKeywords_ = [
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
"whitesmoke", "yellow", "yellowgreen"
], colorKeywords = keySet(colorKeywords_);
var valueKeywords_ = [
"above", "absolute", "activeborder", "additive", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "attr", "auto", "avoid", "avoid-column", "avoid-page",
"avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
"bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
"both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
"col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
"content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
"cross", "crosshair", "currentcolor", "cursive", "cyclic", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari",
"disc", "discard", "disclosure-closed", "disclosure-open", "document",
"dot-dash", "dot-dot-dash",
"dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
"ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
"italic", "japanese-formal", "japanese-informal", "justify", "kannada",
"katakana", "katakana-iroha", "keep-all", "khmer",
"korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
"landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
"lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d",
"media-controls-background", "media-current-time-display",
"media-fullscreen-button", "media-mute-button", "media-play-button",
"media-return-to-realtime-button", "media-rewind-button",
"media-seek-back-button", "media-seek-forward-button", "media-slider",
"media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
"media-volume-slider-container", "media-volume-sliderthumb", "medium",
"menu", "menulist", "menulist-button", "menulist-text",
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
"mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
"painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
"pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
"progress", "push-button", "radial-gradient", "radio", "read-only",
"read-write", "read-write-plaintext-only", "rectangle", "region",
"relative", "repeat", "repeating-linear-gradient",
"repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
"rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
"rotateZ", "round", "row-resize", "rtl", "run-in", "running",
"s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ",
"scroll", "scrollbar", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration",
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
"simp-chinese-formal", "simp-chinese-informal", "single",
"skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "spell-out", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
"subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"tamil",
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"trad-chinese-formal", "trad-chinese-informal",
"translate", "translate3d", "translateX", "translateY", "translateZ",
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
"window", "windowframe", "windowtext", "words", "x-large", "x-small", "xor",
"xx-large", "xx-small"
], valueKeywords = keySet(valueKeywords_);
var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(propertyKeywords_)
.concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
CodeMirror.registerHelper("hintWords", "css", allWords);
function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == "/") {
state.tokenize = null;
break;
}
maybeEnd = (ch == "*");
}
return ["comment", "comment"];
}
CodeMirror.defineMIME("text/css", {
documentTypes: documentTypes,
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
fontProperties: fontProperties,
counterDescriptors: counterDescriptors,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
tokenHooks: {
"/": function(stream, state) {
if (!stream.eat("*")) return false;
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
},
name: "css"
});
CodeMirror.defineMIME("text/x-scss", {
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
":": function(stream) {
if (stream.match(/\s*\{/))
return [null, "{"];
return false;
},
"$": function(stream) {
stream.match(/^[\w-]+/);
if (stream.match(/^\s*:/, false))
return ["variable-2", "variable-definition"];
return ["variable-2", "variable"];
},
"#": function(stream) {
if (!stream.eat("{")) return false;
return [null, "interpolation"];
}
},
name: "css",
helperType: "scss"
});
CodeMirror.defineMIME("text/x-less", {
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
"@": function(stream) {
if (stream.eat("{")) return [null, "interpolation"];
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
stream.eatWhile(/[\w\\\-]/);
if (stream.match(/^\s*:/, false))
return ["variable-2", "variable-definition"];
return ["variable-2", "variable"];
},
"&": function() {
return ["atom", "atom"];
}
},
name: "css",
helperType: "less"
});
});

View File

@ -1,121 +0,0 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
var htmlMode = CodeMirror.getMode(config, {name: "xml",
htmlMode: true,
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
var cssMode = CodeMirror.getMode(config, "css");
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
mode: CodeMirror.getMode(config, "javascript")});
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
var conf = scriptTypesConf[i];
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
}
scriptTypes.push({matches: /./,
mode: CodeMirror.getMode(config, "text/plain")});
function html(stream, state) {
var tagName = state.htmlState.tagName;
if (tagName) tagName = tagName.toLowerCase();
var style = htmlMode.token(stream, state.htmlState);
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
// Script block: mode to change to depends on type attribute
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
scriptType = scriptType ? scriptType[1] : "";
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
for (var i = 0; i < scriptTypes.length; ++i) {
var tp = scriptTypes[i];
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
if (tp.mode) {
state.token = script;
state.localMode = tp.mode;
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
}
break;
}
}
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
state.token = css;
state.localMode = cssMode;
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
}
return style;
}
function maybeBackup(stream, pat, style) {
var cur = stream.current();
var close = cur.search(pat);
if (close > -1) stream.backUp(cur.length - close);
else if (cur.match(/<\/?$/)) {
stream.backUp(cur.length);
if (!stream.match(pat, false)) stream.match(cur);
}
return style;
}
function script(stream, state) {
if (stream.match(/^<\/\s*script\s*>/i, false)) {
state.token = html;
state.localState = state.localMode = null;
return null;
}
return maybeBackup(stream, /<\/\s*script\s*>/,
state.localMode.token(stream, state.localState));
}
function css(stream, state) {
if (stream.match(/^<\/\s*style\s*>/i, false)) {
state.token = html;
state.localState = state.localMode = null;
return null;
}
return maybeBackup(stream, /<\/\s*style\s*>/,
cssMode.token(stream, state.localState));
}
return {
startState: function() {
var state = htmlMode.startState();
return {token: html, localMode: null, localState: null, htmlState: state};
},
copyState: function(state) {
if (state.localState)
var local = CodeMirror.copyState(state.localMode, state.localState);
return {token: state.token, localMode: state.localMode, localState: local,
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
},
token: function(stream, state) {
return state.token(stream, state);
},
indent: function(state, textAfter) {
if (!state.localMode || /^\s*<\//.test(textAfter))
return htmlMode.indent(state.htmlState, textAfter);
else if (state.localMode.indent)
return state.localMode.indent(state.localState, textAfter);
else
return CodeMirror.Pass;
},
innerMode: function(state) {
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
}
};
}, "xml", "javascript", "css");
CodeMirror.defineMIME("text/html", "htmlmixed");
});

View File

@ -1,701 +0,0 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// TODO actually recognize syntax of TypeScript constructs
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("javascript", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var statementIndent = parserConfig.statementIndent;
var jsonldMode = parserConfig.jsonld;
var jsonMode = parserConfig.json || jsonldMode;
var isTS = parserConfig.typescript;
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
// Tokenizer
var keywords = function(){
function kw(type) {return {type: type, style: "keyword"};}
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
var jsKeywords = {
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
"var": kw("var"), "const": kw("var"), "let": kw("var"),
"function": kw("function"), "catch": kw("catch"),
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
"in": operator, "typeof": operator, "instanceof": operator,
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
};
// Extend the 'normal' keywords with the TypeScript language extensions
if (isTS) {
var type = {type: "variable", style: "variable-3"};
var tsKeywords = {
// object-like things
"interface": kw("interface"),
"extends": kw("extends"),
"constructor": kw("constructor"),
// scope modifiers
"public": kw("public"),
"private": kw("private"),
"protected": kw("protected"),
"static": kw("static"),
// types
"string": type, "number": type, "bool": type, "any": type
};
for (var attr in tsKeywords) {
jsKeywords[attr] = tsKeywords[attr];
}
}
return jsKeywords;
}();
var isOperatorChar = /[+\-*&%=<>!?|~^]/;
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
function readRegexp(stream) {
var escaped = false, next, inSet = false;
while ((next = stream.next()) != null) {
if (!escaped) {
if (next == "/" && !inSet) return;
if (next == "[") inSet = true;
else if (inSet && next == "]") inSet = false;
}
escaped = !escaped && next == "\\";
}
}
// Used as scratch variables to communicate multiple values without
// consing up tons of objects.
var type, content;
function ret(tp, style, cont) {
type = tp; content = cont;
return style;
}
function tokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
return ret("number", "number");
} else if (ch == "." && stream.match("..")) {
return ret("spread", "meta");
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
return ret(ch);
} else if (ch == "=" && stream.eat(">")) {
return ret("=>", "operator");
} else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
} else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
return ret("number", "number");
} else if (ch == "/") {
if (stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
} else if (stream.eat("/")) {
stream.skipToEnd();
return ret("comment", "comment");
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
readRegexp(stream);
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
return ret("regexp", "string-2");
} else {
stream.eatWhile(isOperatorChar);
return ret("operator", "operator", stream.current());
}
} else if (ch == "`") {
state.tokenize = tokenQuasi;
return tokenQuasi(stream, state);
} else if (ch == "#") {
stream.skipToEnd();
return ret("error", "error");
} else if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return ret("operator", "operator", stream.current());
} else if (wordRE.test(ch)) {
stream.eatWhile(wordRE);
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
ret("variable", "variable", word);
}
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next;
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
state.tokenize = tokenBase;
return ret("jsonld-keyword", "meta");
}
while ((next = stream.next()) != null) {
if (next == quote && !escaped) break;
escaped = !escaped && next == "\\";
}
if (!escaped) state.tokenize = tokenBase;
return ret("string", "string");
};
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return ret("comment", "comment");
}
function tokenQuasi(stream, state) {
var escaped = false, next;
while ((next = stream.next()) != null) {
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
state.tokenize = tokenBase;
break;
}
escaped = !escaped && next == "\\";
}
return ret("quasi", "string-2", stream.current());
}
var brackets = "([{}])";
// This is a crude lookahead trick to try and notice that we're
// parsing the argument patterns for a fat-arrow function before we
// actually hit the arrow token. It only works if the arrow is on
// the same line as the arguments and there's no strange noise
// (comments) in between. Fallback is to only notice when we hit the
// arrow, and not declare the arguments as locals for the arrow
// body.
function findFatArrow(stream, state) {
if (state.fatArrowAt) state.fatArrowAt = null;
var arrow = stream.string.indexOf("=>", stream.start);
if (arrow < 0) return;
var depth = 0, sawSomething = false;
for (var pos = arrow - 1; pos >= 0; --pos) {
var ch = stream.string.charAt(pos);
var bracket = brackets.indexOf(ch);
if (bracket >= 0 && bracket < 3) {
if (!depth) { ++pos; break; }
if (--depth == 0) break;
} else if (bracket >= 3 && bracket < 6) {
++depth;
} else if (wordRE.test(ch)) {
sawSomething = true;
} else if (/["'\/]/.test(ch)) {
return;
} else if (sawSomething && !depth) {
++pos;
break;
}
}
if (sawSomething && !depth) state.fatArrowAt = pos;
}
// Parser
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
function JSLexical(indented, column, type, align, prev, info) {
this.indented = indented;
this.column = column;
this.type = type;
this.prev = prev;
this.info = info;
if (align != null) this.align = align;
}
function inScope(state, varname) {
for (var v = state.localVars; v; v = v.next)
if (v.name == varname) return true;
for (var cx = state.context; cx; cx = cx.prev) {
for (var v = cx.vars; v; v = v.next)
if (v.name == varname) return true;
}
}
function parseJS(state, style, type, content, stream) {
var cc = state.cc;
// Communicate our context to the combinators.
// (Less wasteful than consing up a hundred closures on every call.)
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
if (!state.lexical.hasOwnProperty("align"))
state.lexical.align = true;
while(true) {
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
if (combinator(type, content)) {
while(cc.length && cc[cc.length - 1].lex)
cc.pop()();
if (cx.marked) return cx.marked;
if (type == "variable" && inScope(state, content)) return "variable-2";
return style;
}
}
}
// Combinator utils
var cx = {state: null, column: null, marked: null, cc: null};
function pass() {
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
}
function cont() {
pass.apply(null, arguments);
return true;
}
function register(varname) {
function inList(list) {
for (var v = list; v; v = v.next)
if (v.name == varname) return true;
return false;
}
var state = cx.state;
if (state.context) {
cx.marked = "def";
if (inList(state.localVars)) return;
state.localVars = {name: varname, next: state.localVars};
} else {
if (inList(state.globalVars)) return;
if (parserConfig.globalVars)
state.globalVars = {name: varname, next: state.globalVars};
}
}
// Combinators
var defaultVars = {name: "this", next: {name: "arguments"}};
function pushcontext() {
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
cx.state.localVars = defaultVars;
}
function popcontext() {
cx.state.localVars = cx.state.context.vars;
cx.state.context = cx.state.context.prev;
}
function pushlex(type, info) {
var result = function() {
var state = cx.state, indent = state.indented;
if (state.lexical.type == "stat") indent = state.lexical.indented;
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
indent = outer.indented;
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
};
result.lex = true;
return result;
}
function poplex() {
var state = cx.state;
if (state.lexical.prev) {
if (state.lexical.type == ")")
state.indented = state.lexical.indented;
state.lexical = state.lexical.prev;
}
}
poplex.lex = true;
function expect(wanted) {
function exp(type) {
if (type == wanted) return cont();
else if (wanted == ";") return pass();
else return cont(exp);
};
return exp;
}
function statement(type, value) {
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
if (type == "{") return cont(pushlex("}"), block, poplex);
if (type == ";") return cont();
if (type == "if") {
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
cx.state.cc.pop()();
return cont(pushlex("form"), expression, statement, poplex, maybeelse);
}
if (type == "function") return cont(functiondef);
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
if (type == "variable") return cont(pushlex("stat"), maybelabel);
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
block, poplex, poplex);
if (type == "case") return cont(expression, expect(":"));
if (type == "default") return cont(expect(":"));
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
statement, poplex, popcontext);
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
if (type == "class") return cont(pushlex("form"), className, poplex);
if (type == "export") return cont(pushlex("form"), afterExport, poplex);
if (type == "import") return cont(pushlex("form"), afterImport, poplex);
return pass(pushlex("stat"), expression, expect(";"), poplex);
}
function expression(type) {
return expressionInner(type, false);
}
function expressionNoComma(type) {
return expressionInner(type, true);
}
function expressionInner(type, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) {
var body = noComma ? arrowBodyNoComma : arrowBody;
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
}
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
if (type == "function") return cont(functiondef, maybeop);
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") { return pass(quasi, maybeop); }
return cont();
}
function maybeexpression(type) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expression);
}
function maybeexpressionNoComma(type) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expressionNoComma);
}
function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression);
return maybeoperatorNoComma(type, value, false);
}
function maybeoperatorNoComma(type, value, noComma) {
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
var expr = noComma == false ? expression : expressionNoComma;
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
if (type == "operator") {
if (/\+\+|--/.test(value)) return cont(me);
if (value == "?") return cont(expression, expect(":"), expr);
return cont(expr);
}
if (type == "quasi") { return pass(quasi, me); }
if (type == ";") return;
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
if (type == ".") return cont(property, me);
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
}
function quasi(type, value) {
if (type != "quasi") return pass();
if (value.slice(value.length - 2) != "${") return cont(quasi);
return cont(expression, continueQuasi);
}
function continueQuasi(type) {
if (type == "}") {
cx.marked = "string-2";
cx.state.tokenize = tokenQuasi;
return cont(quasi);
}
}
function arrowBody(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expression);
}
function arrowBodyNoComma(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expressionNoComma);
}
function maybelabel(type) {
if (type == ":") return cont(poplex, statement);
return pass(maybeoperatorComma, expect(";"), poplex);
}
function property(type) {
if (type == "variable") {cx.marked = "property"; return cont();}
}
function objprop(type, value) {
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property";
if (value == "get" || value == "set") return cont(getterSetter);
return cont(afterprop);
} else if (type == "number" || type == "string") {
cx.marked = jsonldMode ? "property" : (cx.style + " property");
return cont(afterprop);
} else if (type == "jsonld-keyword") {
return cont(afterprop);
} else if (type == "[") {
return cont(expression, expect("]"), afterprop);
}
}
function getterSetter(type) {
if (type != "variable") return pass(afterprop);
cx.marked = "property";
return cont(functiondef);
}
function afterprop(type) {
if (type == ":") return cont(expressionNoComma);
if (type == "(") return pass(functiondef);
}
function commasep(what, end) {
function proceed(type) {
if (type == ",") {
var lex = cx.state.lexical;
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
return cont(what, proceed);
}
if (type == end) return cont();
return cont(expect(end));
}
return function(type) {
if (type == end) return cont();
return pass(what, proceed);
};
}
function contCommasep(what, end, info) {
for (var i = 3; i < arguments.length; i++)
cx.cc.push(arguments[i]);
return cont(pushlex(end, info), commasep(what, end), poplex);
}
function block(type) {
if (type == "}") return cont();
return pass(statement, block);
}
function maybetype(type) {
if (isTS && type == ":") return cont(typedef);
}
function typedef(type) {
if (type == "variable"){cx.marked = "variable-3"; return cont();}
}
function vardef() {
return pass(pattern, maybetype, maybeAssign, vardefCont);
}
function pattern(type, value) {
if (type == "variable") { register(value); return cont(); }
if (type == "[") return contCommasep(pattern, "]");
if (type == "{") return contCommasep(proppattern, "}");
}
function proppattern(type, value) {
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
register(value);
return cont(maybeAssign);
}
if (type == "variable") cx.marked = "property";
return cont(expect(":"), pattern, maybeAssign);
}
function maybeAssign(_type, value) {
if (value == "=") return cont(expressionNoComma);
}
function vardefCont(type) {
if (type == ",") return cont(vardef);
}
function maybeelse(type, value) {
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
}
function forspec(type) {
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
}
function forspec1(type) {
if (type == "var") return cont(vardef, expect(";"), forspec2);
if (type == ";") return cont(forspec2);
if (type == "variable") return cont(formaybeinof);
return pass(expression, expect(";"), forspec2);
}
function formaybeinof(_type, value) {
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
return cont(maybeoperatorComma, forspec2);
}
function forspec2(type, value) {
if (type == ";") return cont(forspec3);
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
return pass(expression, expect(";"), forspec3);
}
function forspec3(type) {
if (type != ")") cont(expression);
}
function functiondef(type, value) {
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
if (type == "variable") {register(value); return cont(functiondef);}
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
}
function funarg(type) {
if (type == "spread") return cont(funarg);
return pass(pattern, maybetype);
}
function className(type, value) {
if (type == "variable") {register(value); return cont(classNameAfter);}
}
function classNameAfter(type, value) {
if (value == "extends") return cont(expression, classNameAfter);
if (type == "{") return cont(pushlex("}"), classBody, poplex);
}
function classBody(type, value) {
if (type == "variable" || cx.style == "keyword") {
if (value == "static") {
cx.marked = "keyword";
return cont(classBody);
}
cx.marked = "property";
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
return cont(functiondef, classBody);
}
if (value == "*") {
cx.marked = "keyword";
return cont(classBody);
}
if (type == ";") return cont(classBody);
if (type == "}") return cont();
}
function classGetterSetter(type) {
if (type != "variable") return pass();
cx.marked = "property";
return cont();
}
function afterModule(type, value) {
if (type == "string") return cont(statement);
if (type == "variable") { register(value); return cont(maybeFrom); }
}
function afterExport(_type, value) {
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
return pass(statement);
}
function afterImport(type) {
if (type == "string") return cont();
return pass(importSpec, maybeFrom);
}
function importSpec(type, value) {
if (type == "{") return contCommasep(importSpec, "}");
if (type == "variable") register(value);
if (value == "*") cx.marked = "keyword";
return cont(maybeAs);
}
function maybeAs(_type, value) {
if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
}
function maybeFrom(_type, value) {
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
}
function arrayLiteral(type) {
if (type == "]") return cont();
return pass(expressionNoComma, maybeArrayComprehension);
}
function maybeArrayComprehension(type) {
if (type == "for") return pass(comprehension, expect("]"));
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
return pass(commasep(expressionNoComma, "]"));
}
function comprehension(type) {
if (type == "for") return cont(forspec, comprehension);
if (type == "if") return cont(expression, comprehension);
}
function isContinuedStatement(state, textAfter) {
return state.lastType == "operator" || state.lastType == "," ||
isOperatorChar.test(textAfter.charAt(0)) ||
/[,.]/.test(textAfter.charAt(0));
}
// Interface
return {
startState: function(basecolumn) {
var state = {
tokenize: tokenBase,
lastType: "sof",
cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars,
context: parserConfig.localVars && {vars: parserConfig.localVars},
indented: 0
};
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
state.globalVars = parserConfig.globalVars;
return state;
},
token: function(stream, state) {
if (stream.sol()) {
if (!state.lexical.hasOwnProperty("align"))
state.lexical.align = false;
state.indented = stream.indentation();
findFatArrow(stream, state);
}
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
if (type == "comment") return style;
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
return parseJS(state, style, type, content, stream);
},
indent: function(state, textAfter) {
if (state.tokenize == tokenComment) return CodeMirror.Pass;
if (state.tokenize != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
// Kludge to prevent 'maybelse' from blocking lexical scope pops
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
var c = state.cc[i];
if (c == poplex) lexical = lexical.prev;
else if (c != maybeelse) break;
}
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "form") return lexical.indented + indentUnit;
else if (type == "stat")
return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
else return lexical.indented + (closing ? 0 : indentUnit);
},
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
blockCommentStart: jsonMode ? null : "/*",
blockCommentEnd: jsonMode ? null : "*/",
lineComment: jsonMode ? null : "//",
fold: "brace",
closeBrackets: "()[]{}''\"\"``",
helperType: jsonMode ? "json" : "javascript",
jsonldMode: jsonldMode,
jsonMode: jsonMode
};
});
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
CodeMirror.defineMIME("text/javascript", "javascript");
CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
CodeMirror.defineMIME("application/x-javascript", "javascript");
CodeMirror.defineMIME("application/ecmascript", "javascript");
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
});

View File

@ -1,120 +0,0 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
(document.documentMode == null || document.documentMode < 8);
var Pos = CodeMirror.Pos;
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
function findMatchingBracket(cm, where, strict, config) {
var line = cm.getLineHandle(where.line), pos = where.ch - 1;
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
if (!match) return null;
var dir = match.charAt(1) == ">" ? 1 : -1;
if (strict && (dir > 0) != (pos == where.ch)) return null;
var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
if (found == null) return null;
return {from: Pos(where.line, pos), to: found && found.pos,
match: found && found.ch == match.charAt(0), forward: dir > 0};
}
// bracketRegex is used to specify which type of bracket to scan
// should be a regexp, e.g. /[[\]]/
//
// Note: If "where" is on an open bracket, then this bracket is ignored.
//
// Returns false when no bracket was found, null when it reached
// maxScanLines and gave up
function scanForBracket(cm, where, dir, style, config) {
var maxScanLen = (config && config.maxScanLineLength) || 10000;
var maxScanLines = (config && config.maxScanLines) || 1000;
var stack = [];
var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
: Math.max(cm.firstLine() - 1, where.line - maxScanLines);
for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
var line = cm.getLine(lineNo);
if (!line) continue;
var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
if (line.length > maxScanLen) continue;
if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
for (; pos != end; pos += dir) {
var ch = line.charAt(pos);
if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
var match = matching[ch];
if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
else stack.pop();
}
}
}
return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
}
function matchBrackets(cm, autoclear, config) {
// Disable brace matching in long lines, since it'll cause hugely slow updates
var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
var marks = [], ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
}
}
if (marks.length) {
// Kludge to work around the IE bug from issue #1193, where text
// input stops going to the textare whever this fires.
if (ie_lt8 && cm.state.focused) cm.focus();
var clear = function() {
cm.operation(function() {
for (var i = 0; i < marks.length; i++) marks[i].clear();
});
};
if (autoclear) setTimeout(clear, 800);
else return clear;
}
}
var currentlyHighlighted = null;
function doMatchBrackets(cm) {
cm.operation(function() {
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
});
}
CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
if (old && old != CodeMirror.Init)
cm.off("cursorActivity", doMatchBrackets);
if (val) {
cm.state.matchBrackets = typeof val == "object" ? val : {};
cm.on("cursorActivity", doMatchBrackets);
}
});
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){
return findMatchingBracket(this, pos, strict, config);
});
CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
return scanForBracket(this, pos, dir, style, config);
});
});

View File

@ -1,384 +0,0 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true, 'menuitem': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: true,
caseFold: true
} : {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false,
caseFold: false
};
var alignCDATA = parserConfig.alignCDATA;
// Return variables for tokenizers
var type, setStyle;
function inText(stream, state) {
function chain(parser) {
state.tokenize = parser;
return parser(stream, state);
}
var ch = stream.next();
if (ch == "<") {
if (stream.eat("!")) {
if (stream.eat("[")) {
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
else return null;
} else if (stream.match("--")) {
return chain(inBlock("comment", "-->"));
} else if (stream.match("DOCTYPE", true, true)) {
stream.eatWhile(/[\w\._\-]/);
return chain(doctype(1));
} else {
return null;
}
} else if (stream.eat("?")) {
stream.eatWhile(/[\w\._\-]/);
state.tokenize = inBlock("meta", "?>");
return "meta";
} else {
type = stream.eat("/") ? "closeTag" : "openTag";
state.tokenize = inTag;
return "tag bracket";
}
} else if (ch == "&") {
var ok;
if (stream.eat("#")) {
if (stream.eat("x")) {
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
} else {
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
}
} else {
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
}
return ok ? "atom" : "error";
} else {
stream.eatWhile(/[^&<]/);
return null;
}
}
function inTag(stream, state) {
var ch = stream.next();
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
state.tokenize = inText;
type = ch == ">" ? "endTag" : "selfcloseTag";
return "tag bracket";
} else if (ch == "=") {
type = "equals";
return null;
} else if (ch == "<") {
state.tokenize = inText;
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
return next ? next + " tag error" : "tag error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();
return state.tokenize(stream, state);
} else {
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
return "word";
}
}
function inAttribute(quote) {
var closure = function(stream, state) {
while (!stream.eol()) {
if (stream.next() == quote) {
state.tokenize = inTag;
break;
}
}
return "string";
};
closure.isInAttribute = true;
return closure;
}
function inBlock(style, terminator) {
return function(stream, state) {
while (!stream.eol()) {
if (stream.match(terminator)) {
state.tokenize = inText;
break;
}
stream.next();
}
return style;
};
}
function doctype(depth) {
return function(stream, state) {
var ch;
while ((ch = stream.next()) != null) {
if (ch == "<") {
state.tokenize = doctype(depth + 1);
return state.tokenize(stream, state);
} else if (ch == ">") {
if (depth == 1) {
state.tokenize = inText;
break;
} else {
state.tokenize = doctype(depth - 1);
return state.tokenize(stream, state);
}
}
}
return "meta";
};
}
function Context(state, tagName, startOfLine) {
this.prev = state.context;
this.tagName = tagName;
this.indent = state.indented;
this.startOfLine = startOfLine;
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
this.noIndent = true;
}
function popContext(state) {
if (state.context) state.context = state.context.prev;
}
function maybePopContext(state, nextTagName) {
var parentTagName;
while (true) {
if (!state.context) {
return;
}
parentTagName = state.context.tagName;
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext(state);
}
}
function baseState(type, stream, state) {
if (type == "openTag") {
state.tagStart = stream.column();
return tagNameState;
} else if (type == "closeTag") {
return closeTagNameState;
} else {
return baseState;
}
}
function tagNameState(type, stream, state) {
if (type == "word") {
state.tagName = stream.current();
setStyle = "tag";
return attrState;
} else {
setStyle = "error";
return tagNameState;
}
}
function closeTagNameState(type, stream, state) {
if (type == "word") {
var tagName = stream.current();
if (state.context && state.context.tagName != tagName &&
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
popContext(state);
if (state.context && state.context.tagName == tagName) {
setStyle = "tag";
return closeState;
} else {
setStyle = "tag error";
return closeStateErr;
}
} else {
setStyle = "error";
return closeStateErr;
}
}
function closeState(type, _stream, state) {
if (type != "endTag") {
setStyle = "error";
return closeState;
}
popContext(state);
return baseState;
}
function closeStateErr(type, stream, state) {
setStyle = "error";
return closeState(type, stream, state);
}
function attrState(type, _stream, state) {
if (type == "word") {
setStyle = "attribute";
return attrEqState;
} else if (type == "endTag" || type == "selfcloseTag") {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
maybePopContext(state, tagName);
} else {
maybePopContext(state, tagName);
state.context = new Context(state, tagName, tagStart == state.indented);
}
return baseState;
}
setStyle = "error";
return attrState;
}
function attrEqState(type, stream, state) {
if (type == "equals") return attrValueState;
if (!Kludges.allowMissing) setStyle = "error";
return attrState(type, stream, state);
}
function attrValueState(type, stream, state) {
if (type == "string") return attrContinuedState;
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
setStyle = "error";
return attrState(type, stream, state);
}
function attrContinuedState(type, stream, state) {
if (type == "string") return attrContinuedState;
return attrState(type, stream, state);
}
return {
startState: function() {
return {tokenize: inText,
state: baseState,
indented: 0,
tagName: null, tagStart: null,
context: null};
},
token: function(stream, state) {
if (!state.tagName && stream.sol())
state.indented = stream.indentation();
if (stream.eatSpace()) return null;
type = null;
var style = state.tokenize(stream, state);
if ((style || type) && style != "comment") {
setStyle = null;
state.state = state.state(type || style, stream, state);
if (setStyle)
style = setStyle == "error" ? style + " error" : setStyle;
}
return style;
},
indent: function(state, textAfter, fullLine) {
var context = state.context;
// Indent multi-line strings (e.g. css).
if (state.tokenize.isInAttribute) {
if (state.tagStart == state.indented)
return state.stringStartCol + 1;
else
return state.indented + indentUnit;
}
if (context && context.noIndent) return CodeMirror.Pass;
if (state.tokenize != inTag && state.tokenize != inText)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
// Indent the starts of attribute names.
if (state.tagName) {
if (multilineTagIndentPastTag)
return state.tagStart + state.tagName.length + 2;
else
return state.tagStart + indentUnit * multilineTagIndentFactor;
}
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
if (tagAfter && tagAfter[1]) { // Closing tag spotted
while (context) {
if (context.tagName == tagAfter[2]) {
context = context.prev;
break;
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
context = context.prev;
} else {
break;
}
}
} else if (tagAfter) { // Opening tag spotted
while (context) {
var grabbers = Kludges.contextGrabbers[context.tagName];
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
context = context.prev;
else
break;
}
}
while (context && !context.startOfLine)
context = context.prev;
if (context) return context.indent + indentUnit;
else return 0;
},
electricInput: /<\/[\s\w:]+>$/,
blockCommentStart: "<!--",
blockCommentEnd: "-->",
configuration: parserConfig.htmlMode ? "html" : "xml",
helperType: parserConfig.htmlMode ? "html" : "xml"
};
});
CodeMirror.defineMIME("text/xml", "xml");
CodeMirror.defineMIME("application/xml", "xml");
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
});

5
web/dep/jquery.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,73 +0,0 @@
jsQuery = (function(){
if(!window || !window.jQuery){
console.log("jQuery Required!");
}
var $ = window.jQuery;
function jsQuery(js){
if(typeof js === 'string'){
js = jsQuery.dom(js);
}
return js;
}
var jsq = jsQuery;
jsq.dom = function(text, env){
return (function recurse(tree, dom, prev){
dom = dom || $('<div>'); prev = '';
$.each(tree, function(i, code){
if($.isArray(code)){
var div = recurse(code);
if(0 <= prev.indexOf('function')){
div.addClass('function');
} else
if(0 <= prev.indexOf('if') || 0 <= prev.indexOf('else')){
div.addClass('if');
}
dom.append(div);
} else
if(code){
dom.append($("<span>").text(code));
}
prev = code;
});
return dom;
})(nestrecurse(text || "", ['{','}']));
}
function nestrecurse(text){
text = text || "";
var args = Array.prototype.slice.call(arguments, 1);
var env = {i: -1, text: text, at: [], start: {}, end: {}, count: {}};
var i = -1, l = text.length; while(++i < l){
env.c = env.text[++env.i];
var ii = -1, ll = args.length, s = '', e = ''; while(!(s || e) && ++ii < ll){
var nest = args[ii], s = (typeof nest === "string");
var start = s? nest : nest[0], end = s? nest : nest[1];
var c = (start.length === 1? env.c : env.text.slice(env.i, start.length));
if(start === c){
if(env.count[start] == env.count[end] || 0){
s = start;
}
env.count[start] = (env.count[start] || 0) + 1;
} else
if(end === c){
env.count[end] = (env.count[end] || 0) + 1;
if(env.count[end] == env.count[start] || 0){
e = end;
}
}
}
if(s){
env.at.push(env.text.slice(0, env.i + s.length));
env.text = env.text.slice(env.i + s.length); env.i = -1;
}
if(e){
env.at.push(nestrecurse.apply(nestrecurse, [env.text.slice(0, env.i)].concat(args)));
env.text = env.text.slice(env.i); env.i = e.length -1;
}
}
if(env.text){
env.at.push(env.text);
}
return env.at;
}
return jsQuery
}());

View File

@ -1,19 +0,0 @@
<h2>Introduction to Data</h2>
<p>Your thoughts are information. Conversation explore interactions of ideas amongst yourself and others. We communicate by creating art via writing, drawing, or composing. Experiences are shared by recording reality.</p>
<p>All these things can be represented by data. If you want to build a tool that enriches any of these, you have to care about data. Specifically, you need a system that can store and move information.</p>
<p>You came to the right place, we will explain how to make a web app for each kind. Starting with the simplest and progressing to ever more complicated projects. It is important to know that everything we use will be based on free and open technology, including this tutorial itself.</p>
<a href="./think.html">Let us begin.</a>
Think
Converse
Contact
Find
Write
Draw
Compose
Record
Automate

View File

@ -1,67 +0,0 @@
<html>
<body>
<link rel="stylesheet" href="./dep/codemirror/codemirror.css">
<link rel="stylesheet" href="./dep/codemirror/colorforth.css">
<style>
.edit {
border: 1px dashed;
overflow: hidden;
}
.CodeMirror {
float: left;
padding: .5em;
height: auto;
width: 49%;
}
iframe {
float: left;
width: 49%;
border: none;
}
</style>
<textarea style="height: 15em"></textarea>
<iframe></iframe>
<script src="./dep/jquery.js"></script>
<script src="./dep/jsquery.js"></script>
<script src="./dep/codemirror/codemirror.js"></script>
<script src="./dep/codemirror/xml.js"></script>
<script src="./dep/codemirror/javascript.js"></script>
<script src="./dep/codemirror/css.js"></script>
<script src="./dep/codemirror/htmlmixed.js"></script>
<script src="./dep/codemirror/matchbrackets.js"></script>
<script src="./dep/beautify/beautify.js"></script>
<script src="./dep/beautify/beautify-css.js"></script>
<script src="./dep/beautify/beautify-html.js"></script>
<script src="./dep/beautify/unpackers/javascriptobfuscator_unpacker.js"></script>
<script src="./dep/beautify/unpackers/urlencode_unpacker.js"></script>
<script src="./dep/beautify/unpackers/p_a_c_k_e_r_unpacker.js"></script>
<script src="./dep/beautify/unpackers/myobfuscate_unpacker.js"></script>
<script>
var editor = CodeMirror.fromTextArea($('textarea')[0], {
theme: 'colorforth',
//lineNumbers: true,
matchBrackets: true,
mode: "text/html",
tabSize: 2
});
editor.live = function(cb){ editor.cb = cb || editor.cb }
editor.on("change", function change() {
clearTimeout(change.throttle);
change.throttle = setTimeout(live, 100);
});
function live() {
var frame = $('iframe').height($('.CodeMirror').height() * .95)[0];
frame = frame.contentDocument || frame.contentWindow.document;
frame.open();
frame.write(editor.getValue());
(editor.cb || function(){})(frame);
frame.close();
}
setTimeout(live, 100);
</script>
</html>
</body>

View File

@ -1,18 +0,0 @@
NOTES FROM FORREST:
-3. `gun.path('players').path(id).set({x:0, y:0});` doesn't trigger `gun.path('players').on()`
-2. gun.on() needs to be chainable with map and stuff.
-1. Maybe make the map module core to gun?
1 make raw HTTP work and document it (DONE), document that attach needs to be BEFORE listen. (talk to AJ)
2 make sure you SUPPRESS your comments, Mark. (DONE)
3 .get doesn't work on subsequent closures. WHYYY??
4 HOW DO I DELETE? Mark: delete the actual field from the data, but not the stream/meta.
5 security ideas: have gun KEY regexs that are whitelist/blacklist. Off the keys.
6 Forrest says, "arrays". (LISTS!)
7 get VAL without gun meta-data.
8 make it work with just Gun('/gun');
gun.js
gun-bundle.js

View File

@ -1 +0,0 @@
ways to explain HAM? I need to get a succinct explanation.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="2000"
height="1406"
id="svg2"
inkscape:version="0.48.2 r9819"
sodipodi:docname="gun.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="878"
id="namedview7"
showgrid="false"
showborder="false"
inkscape:showpageshadow="false"
inkscape:zoom="0.40435156"
inkscape:cx="1000"
inkscape:cy="703"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<path
d="m 35.071834,1240.0518 c -1.42496,-2.3932 148.756876,-520.76353 152.744496,-527.21562 2.57471,-4.16596 200.31931,-4.17968 202.89382,-0.0133 1.05989,1.71499 -21.35339,83.00061 -49.80731,180.63473 -28.45391,97.63411 -51.0098,179.40479 -50.12421,181.71269 2.25018,5.8638 66.3061,5.8939 70.80488,0.033 4.96272,-6.4651 127.76277,-432.31713 125.65007,-435.73554 -1.07485,-1.74 -59.86073,-3.03032 -138.02088,-3.03032 -74.88171,0 -136.88538,-1.19214 -137.78588,-2.64924 -0.90055,-1.45679 27.88573,-102.98884 63.96946,-225.6265 l 65.60681,-222.97753 241.19898,-0.85465 c 132.65945,-0.47004 242.32732,0.27941 243.70639,1.66514 1.37907,1.3859 -37.88355,141.14289 -87.25029,310.57111 -49.36674,169.42822 -117.68733,403.96351 -151.82354,521.18953 -34.13618,117.226 -63.40366,215.7608 -65.03879,218.9662 -2.79008,5.4695 -17.8082,5.828 -244.10489,5.828 -132.62255,0 -241.801136,-1.1239 -242.619116,-2.4977 z M 538.11989,469.09092 c 3.74787,-4.8351 34.22187,-109.03987 34.22187,-117.0205 0,-4.59159 -4.99556,-5.36745 -34.56022,-5.36745 -23.74427,0 -35.54819,1.30281 -37.71717,4.16285 -3.73998,4.93162 -34.29171,109.162 -34.29171,116.98967 0,4.63073 4.91393,5.39829 34.56023,5.39829 23.70699,0 35.57353,-1.3073 37.787,-4.16286 z m 212.9689,164.8708 c -0.82954,-1.3857 28.02714,-102.92751 64.12599,-225.64849 l 65.63428,-223.12906 99.46354,-0.88309 c 54.7049,-0.48569 100.7761,0.42951 102.3803,2.03377 1.669,1.66894 -14.2671,61.3192 -37.2486,139.42569 -22.0911,75.07987 -40.1655,139.02942 -40.1655,142.1101 0,4.97205 4.2087,5.4955 37.4657,4.65963 l 37.4657,-0.94163 41.6285,-140.03773 c 22.8957,-77.02076 42.841,-141.83642 44.3229,-144.03481 3.0449,-4.51736 197.2118,-5.97379 199.8897,-1.49936 0.8221,1.37374 -28.0411,102.90579 -64.1404,225.62678 l -65.6353,223.12906 -241.83929,0.85428 c -133.0116,0.46984 -242.51798,-0.27941 -243.34752,-1.66514 z m 532.83211,-0.0233 c -0.8222,-1.37375 28.0411,-102.90579 64.1404,-225.62678 l 65.6353,-223.12906 241.028,-0.85465 c 132.5656,-0.47003 242.0923,0.27941 243.3931,1.66514 1.3008,1.3859 -27.1907,102.92787 -63.3147,225.64886 l -65.6798,223.12906 -99.4636,0.88309 c -54.705,0.48569 -100.7761,-0.42951 -102.3803,-2.03377 -1.6692,-1.66894 14.2669,-61.3192 37.2485,-139.42569 22.0912,-75.07987 40.1656,-139.02942 40.1656,-142.1101 0,-4.97205 -4.2088,-5.4955 -37.4657,-4.65964 l -37.4657,0.94324 -41.6286,140.03773 c -22.8957,77.02076 -42.8411,141.83642 -44.3227,144.0348 -3.0449,4.51737 -197.2119,5.9738 -199.8898,1.49937 z m 602.7909,-147.50779 c -14.1367,-11.11999 -14.16,-23.52543 -0.1398,-75.0486 9.6994,-35.6477 14.7038,-48.47905 21.6541,-55.52077 17.0521,-17.27602 46.8695,-8.3331 51.3201,15.39208 3.255,17.35071 -20.6651,101.12079 -32.2162,112.82387 -11.1305,11.27665 -28.028,12.25572 -40.6168,2.35342 z"
id="path2987"
style="opacity:0.95;fill:#000000;fill-opacity:1;stroke:none" />
<path
d="m 829.4375,684.8125 c -31.89589,-0.094 -50.49526,2.47012 -71.09375,24.03125 -29.96144,31.36165 -36.96735,83.31677 -25.625,119.78125 15.91099,41.59563 61.0881,55.47861 80.78125,64.46875 C 764.52825,853.52458 782.25864,773.54509 833.3125,736 l 41.65625,0 c 93.64236,-0.0905 87.74314,-8.71425 89.03457,56.23079 l 0.42659,0 c 1.79887,-91.68611 0.24372,-105.34052 -81.80491,-107.16829 -21.43176,0.4003 -38.68937,-0.20728 -53.1875,-0.25 z m 161.5312,182.90625 c -9.42548,59.54298 -45.7758,66.38613 -115.99995,66.1875 -0.0598,-0.003 -0.07,-0.0282 -0.0625,-0.0312 l -211.09375,0 -19.625,66.18745 216.65625,0 c 0,0 0.66038,0 0.71875,0 78.9182,-1.7019 117.70495,-66.2132 129.4062,-132.3437 z"
id="path2989-1"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.95;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:50;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" />
</svg>

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

View File

@ -1,32 +0,0 @@
<html>
<head>
<title>gun</title>
<meta name="viewport" content="width=device-width, minimum-scale=0.1">
</head>
<body>
<style>
.screen {
background: url(./gun-logo.png) no-repeat 50% 50%;
top: 0; left: 0;
right: 0; bottom: 0;
height: 100%;
width: 100%;
-webkit-animation: fade 7s;
-moz-animation: fade 7s;
animation: fade 7s;
}
@-webkit-keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
} @-moz-keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
} @keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
}
</style>
<div class="screen"></div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -1,737 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script>
</head>
<body>
<style>
@import url(https://fonts.googleapis.com/css?family=Dosis|Poiret+One|Oxygen);
html, body {
margin: 0;
padding: 0;
height: 100%;
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.center {
text-align: center;
}
.lean {
font-family: 'Poiret One', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.clean {
font-family: 'Dosis', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.crisp {
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.svg {
background: white url('./img/devices.svg') no-repeat 50% 50%;
height: 40em;
}
.GUN {
background: transparent url('./img/gun.svg') no-repeat 50% 50%;
background-size: 60%;
}
.dull {
background-color: #EEE;
-webkit-transition: background-color 600ms linear;
-moz-transition: background-color 600ms linear;
transition: background-color 600ms linear;
}
.blue {
background-color: skyblue;
-webkit-transition: background-color 600ms linear;
-moz-transition: background-color 600ms linear;
transition: background-color 600ms linear;
}
.red {
background-color: red;
-webkit-transition: background-color 600ms linear;
-moz-transition: background-color 600ms linear;
transition: background-color 600ms linear;
}
.green {
background-color: MediumSpringGreen;
-webkit-transition: background-color 600ms linear;
-moz-transition: background-color 600ms linear;
transition: background-color 600ms linear;
}
.fold {
width: 100%;
position: relative;
overflow: hidden;
}
.behold {
margin-top: 8%;
padding:0;
text-align: center;
}
.grid {
display: inline-block;
}
@media (max-width: 760px) {
body {
font-size: 8pt;
}
}
@media (max-width: 1279px) {
.wide {
display: none;
}
}
.screen {
position: relative;
overflow: hidden;
}
.mouse {
display: block;
position: absolute;
top: 60%;
left: -6%;
}
</style>
<div class="fold">
<div class="behold">
<div class="graphic grid" style="min-width: 300px; max-width: 600px; height: 400px; position: relative; margin:0 auto; padding:0;">
<img src="./img/server.png" class="server" style="position: absolute; top: 2%; left: 35%; wid-th: 50%;">
<div class="desktop" style="height: 10em; width: 17em; position: absolute; top: 36%; left: 3%;">
<div class="monitor" style="height: 100%; width: 100%; background: #222; padding: .75em; margin-left: -.75em; border-radius: 1em;">
<div class="dull screen GUN" style="height: 100%; width: 100%;">
<img class="mouse" src="./img/mouse.png">
</div>
</div>
<div class="stand" style="margin: 1px auto 0px;
border-bottom: 2.75em solid #888;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
height: 0;
width: 3.2em;">
</div>
<div class="stand" style="width: 6em; height: .5em; background: #888; margin: 0px auto"></div>
</div>
<div class="laptop" style="height: 7em; width: 12em; position: absolute; top: 60%; left: 48%;">
<div class="lid" style="height: 100%; width: 100%; background: #222; padding: .6em; margin-left: -.6em; border-radius: .6em .6em 0em 0em;">
<div class="dull screen GUN" style="height: 100%; width: 100%;">
</div>
</div>
<div class="case" style="height: .75em; width: 140%; margin-left: -20%; background: #999; border-radius: 0em 0em 5em 5em;">
</div>
</div>
<div class="phone" style="height: 3.75em; width: 2.25em; position: absolute; top: 35%; left: 70%;">
<div class="case" style="height: 100%; width: 100%; background: #222; padding: .5em .2em; margin-left: -.2em; border-radius: 0.25em;">
<div class="dull screen GUN" style="height: 100%; width: 100%;">
</div>
</div>
</div>
<div class="arrow desktop-server" style="width: 52px; height: 52px; border: dashed 0px FireBrick; border-radius: 50px 0 0 0;
position: absolute; left: 20%; top: 15%; border-width: 3px 0px 0px 3px;">
<div class="rarr" style="position: absolute; top: -.59em; right: -.7em;
width: 0;
height: 0;
border-top: .5em solid transparent;
border-left: 1em solid FireBrick;
border-bottom: .5em solid transparent;">
</div>
<div class="darr" style="position: absolute; bottom: -.75em; left: -.59em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-top: 1em solid FireBrick;">
</div>
</div>
<div class="arrow phone-server" style="width: 26px; height: 52px; border: dashed 0px FireBrick; border-radius: 0 0 50px 0;
position: absolute; left: 80%; top: 35%; border-width: 0px 3px 3px 0px;">
<div class="uarr" style="position: absolute; top: -.9em; right: -.59em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-bottom: 1em solid FireBrick;">
</div>
<div class="larr" style="position: absolute; bottom: -.55em; left: -.59em;
width: 0;
height: 0;
border-top: .5em solid transparent;
border-right: 1em solid FireBrick;
border-bottom: .5em solid transparent;">
</div>
</div>
<div class="arrow updown laptop-server" style="height: 50px; border: dashed 0px FireBrick; border-radius: 0;
position: absolute; left: 60%; top: 40%; border-width: 0px 3px 0px 0px;">
<div class="uarr" style="position: absolute; top: -1em; left: -.45em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-bottom: 1em solid FireBrick;">
</div>
<div class="darr" style="position: absolute; bottom: -1em; left: -.45em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-top: 1em solid FireBrick;">
</div>
</div>
<span style="color: transparent">Distributed embedded graph database engine. The no pain, no cost, no backend, NoDB database, gun.</span>
</div>
<div class="graphic wide grid" style="min-width: 300px; max-width: 600px; height: 400px;
position: relative; margin:0 auto; padding:0;">
<div class="arrow server-server" style="width: 100px; height: 0px; border: dashed 0px FireBrick; border-radius: 0;
position: absolute; left: -9%; top: 15%; border-width: 3px 0px 0px 0px;">
<div class="rarr" style="position: absolute; top: -.59em; left: -.5em;
width: 0;
height: 0;
border-top: .5em solid transparent;
border-right: 1em solid FireBrick;
border-bottom: .5em solid transparent;">
</div>
<div class="larr" style="position: absolute; top: -.59em; right: -.6em;
width: 0;
height: 0;
border-left: 1em solid FireBrick;
border-bottom: .5em solid transparent;
border-top: .5em solid transparent;">
</div>
</div>
<img src="./img/server.png" class="server" style="position: absolute; top: 2%; right: 35%;">
<div class="desktop" style="height: 10em; width: 17em; position: absolute; top: 36%; right: 3%;">
<div class="monitor" style="height: 100%; width: 100%; background: #222; padding: .75em; margin-left: -.75em; border-radius: 1em;">
<div class="dull screen GUN" style="height: 100%; width: 100%;">
</div>
</div>
<div class="stand" style="margin: 1px auto 0px;
border-bottom: 2.75em solid #888;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
height: 0;
width: 3.2em;">
</div>
<div class="stand" style="width: 6em; height: .5em; background: #888; margin: 0px auto"></div>
</div>
<div class="laptop" style="height: 7em; width: 12em; position: absolute; top: 60%; right: 48%;">
<div class="lid" style="height: 100%; width: 100%; background: #222; padding: .6em; margin-left: -.6em; border-radius: .6em .6em 0em 0em;">
<div class="dull screen GUN" style="height: 100%; width: 100%;">
</div>
</div>
<div class="case" style="height: .75em; width: 140%; margin-left: -20%; background: #999; border-radius: 0em 0em 5em 5em;">
</div>
</div>
<div class="phone" style="height: 3.75em; width: 2.25em; position: absolute; top: 35%; right: 70%;">
<div class="case" style="height: 100%; width: 100%; background: #222; padding: .5em .2em; margin-left: -.2em; border-radius: 0.25em;">
<div class="dull screen GUN" style="height: 100%; width: 100%;">
</div>
</div>
</div>
<div class="arrow desktop-server" style="width: 52px; height: 52px; border: dashed 0px FireBrick; border-radius: 0 50px 0 0;
position: absolute; right: 20%; top: 15%; border-width: 3px 3px 0px 0px;">
<div class="rarr" style="position: absolute; top: -.59em; left: -.5em;
width: 0;
height: 0;
border-top: .5em solid transparent;
border-right: 1em solid FireBrick;
border-bottom: .5em solid transparent;">
</div>
<div class="darr" style="position: absolute; bottom: -.75em; right: -.59em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-top: 1em solid FireBrick;">
</div>
</div>
<div class="arrow phone-server" style="width: 26px; height: 52px; border: dashed 0px FireBrick; border-radius: 0 0 0px 50px;
position: absolute; right: 80.3%; top: 34.3%; border-width: 0px 0px 3px 3px;">
<div class="uarr" style="position: absolute; top: -.8em; left: -.59em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-bottom: 1em solid FireBrick;">
</div>
<div class="rarr" style="position: absolute; bottom: -.55em; right: -.7em;
width: 0;
height: 0;
border-top: .5em solid transparent;
border-left: 1em solid FireBrick;
border-bottom: .5em solid transparent;">
</div>
</div>
<div class="arrow updown laptop-server" style="height: 50px; border: dashed 0px FireBrick; border-radius: 0;
position: absolute; right: 60%; top: 40%; border-width: 0px 3px 0px 0px;">
<div class="uarr" style="position: absolute; top: -1em; left: -.45em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-bottom: 1em solid FireBrick;">
</div>
<div class="darr" style="position: absolute; bottom: -1em; left: -.45em;
width: 0;
height: 0;
border-left: .5em solid transparent;
border-right: .5em solid transparent;
border-top: 1em solid FireBrick;">
</div>
</div>
<span style="color: transparent">Distributed embedded graph database engine. The no pain, no cost, no backend, NoDB database, gun.</span>
</div>
<script>
$(function(){
var c = ['dull', 'blue', 'green']
, a = 'dull blue red green', n = 0, to;
$(".screen").click(function(){
c.push(c.shift());
to = to || c[0];
$(this).removeClass(a).addClass(to);
$('.screen').not(this).each(function(){
var t = $(this); n++;
setTimeout(function(){
t.removeClass(a).addClass(to);
if(!(--n)){ to = null }
}, rand(400,700));
});
});
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
});
</script>
<script>
$(function(){
var mouse = $('.mouse');
function show(i){
function to(){
mouse.animate({top: "60%", left: "55%"}, {
duration: 500,
specialEasing: {top: 'easeInQuad', left: 'easeOutQuad'},
complete: click
});
}
function click(){
mouse.delay(230).animate({width: mouse.width() / 2}, {
duration: 60,
complete: function(){
mouse.closest('.screen').trigger('click');
mouse.animate({width: mouse.width() * 2}, {
duration: 120,
complete: fro
});
}
});
}
function fro(){
mouse.delay(900).animate({top: "87%", left: "110%"}, {
duration: 700,
specialEasing: {top: 'easeOutQuad', left: 'easeInQuad'},
complete: function(){
setTimeout(show, 4 * 1000);
}
});
}
if(!i && $('.graphic').filter(function() { return $(this).is(":hover"); }).length){
setTimeout(show, 2000);
} else {
to();
}
};
mouse.delay(1200).animate({top: "70%", left: "20%"}, {
duration: 400,
specialEasing: {top: 'easeOutQuad', left: 'easeInQuad'},
complete: function(){ show(true) }
});
});
</script>
<div class="center" style="margin: 2% 0;">
<div class="lean" style="font-size: 400%;">Easiest Database Ever</div>
<div class="lean" style="font-size: 225%;">Sync state in a cinch at a distributed system scale.</div>
</div>
</div>
</div> <!-- END FOLD -->
<a href="https://github.com/amark/gun" target="_blank"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
<!-- BEGIN TUTORIAL -->
<div class="tutorial">
<script src="https://gunjs.herokuapp.com/gun.js"></script>
<link id="style" rel="stylesheet" href="https://yandex.st/highlightjs/8.0/styles/ir_black.min.css">
<script src="https://yandex.st/highlightjs/8.0/highlight.min.js"></script>
<style>
@import url(https://fonts.googleapis.com/css?family=Dosis|Poiret+One|Oxygen);
.tutorial {
margin: 0;
padding: 0;
he-ight: 100%;
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
background: #222;
color: #eee;
overflow: auto;
}
.center {
text-align: center;
}
.lean {
font-family: 'Poiret One', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.clean {
font-family: 'Dosis', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.crisp {
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
pre {
background-color: black;
border: 1px dashed white;
color: white;
line-height: 1.5em;
padding: .5em;
margin: 0em;
overflow: auto;
}
button {
border: none;
color: white;
background: skyblue;
padding: 1em;
cursor: pointer;
}
.hide {
display: none;
}
.show {
display: block;
}
.grid {
text-align: center;
}
.unit {
display: inline-block;
}
.main {
min-width: 250px;
max-width: 1024px;
width: 90%;
margin: 0% auto;
padding: 2% 5%;
}
div {
position: relative;
}
.left { float: left;}
.teft { text-align: left; }
.middle {
vertical-align: middle;
}
.full {
width: 100%;
}
</style>
<div class="main">
<div style="font-size: 18pt; margin: 0 0 .75em;">Try it now</div>
<div class="step show step1">
<div class="full grid">
<div class="middle unit teft">
<pre style="max-width: 30.1em; margin: 0 1em 1em 0;">var gun = Gun('https://gunjs.herokuapp.com/gun');
gun.set({hello: "world"}).key('<span class="your-key">example/tutorial</span>');</pre>
</div>
<div class="middle unit teft" style="min-width: 20em; max-width: 28em; margin-bottom: 1em;">
<a href="#step2"><button class="left" style="margin-right: 1em;"><big>Run!</big></button></a>
In this <b>1 minute</b> tutorial, we will connect to a gun peer, create an object, and sync data in realtime.
</div>
</div>
</div>
<div class="step hide step2">
<div class="full grid">
<div class="middle unit teft">
<pre style="max-width: 30.1em; margin: 0 1em 1em 0;">var ref = gun.load('<span class="your-key">example/tutorial</span>');
ref.on(function(data){
$('body').text(JSON.stringify(data));
});</pre>
</div>
<div class="middle unit teft" style="min-width: 34em; max-width: 28em; margin-bottom: 1em;">
<a href="#step3"><button class="left" style="margin-right: 1em; background: MediumSpringGreen;"><big>Next</big></button></a>
Congratulations! You just made an object and saved a reference to it.
In two tabs, we'll load that key to open a shared reference.
</div>
</div>
</div>
<div class="step hide step3">
<div class="full grid">
<style>
.browser {
background: white;
border-radius: .25em;
width: 250px;
//height: 300px;
color: #222;
margin: .5em;
overflow: hidden;
}
.b-bar {
background: #EEE;
border-radius: .25em .25em 0 0;
}
.b-but {
float: left;
width: 1em;
height: 1em;
}
.browser a {
text-decoration: none;
background: white;
border-radius: .4em;
padding: 0 1em;
color: #555;
}
.browser iframe { border: none; }
</style>
<div class="browser unit teft">
<div class="b-bar">
<div class="b-but">&larr;</div>
<div class="b-but">&rarr;</div>
<div class="b-but"><small>&#8635;</small></div>
<small><small><span>
<a href="https://gunjs.herokuapp.com/" target="_blank">https://gunjs.herokuapp.com/</a>
</span></small></small>
<small class="center" style="position: relative; top: -.14em;">x</small>
<span class="center">&equiv;<span>
</div>
<iframe></iframe>
</div>
<div class="browser unit teft">
<div class="b-bar">
<div class="b-but">&larr;</div>
<div class="b-but">&rarr;</div>
<div class="b-but"><small>&#8635;</small></div>
<small><small><span>
<a href="https://gunjs.herokuapp.com/" target="_blank">https://gunjs.herokuapp.com/</a>
</span></small></small>
<small class="center" style="position: relative; top: -.14em;">x</small>
<span class="center">&equiv;<span>
</div>
<iframe></iframe>
</div>
</div>
<form action="#step3" onsubmit="return false;">
<style>
#step3 input {
width: 6em;
}
</style>
<div class="grid">
<div class="middle unit teft">
<pre style="max-width: 40em; margin: 0 1em 1em 0;">ref.path('<input id="try-path" value="hello">').set("<input id="try-sync" value="sync">");</pre>
</div>
<div class="middle unit teft" style="min-width: 20em; max-width: 30em; margin-bottom: 1em;">
<button type="submit" class="left" style="margin-right: 1em;"><big>Update!</big></button>
Let's update the "hello" field with a different value.
We can path into any field, and set it directly.
</div>
</div>
</form>
</div>
<script>
$(function(){
var gun, key = "random/" + Gun.text.random(9),
hili = function(){
$("pre").each(function(){
hljs.highlightBlock(this);
})
}
$(".your-key").text(key);
hili();
location.hash = 'step1';
$(window).on('hashchange', function(){
$('.step').removeClass('show').addClass('hide')
$(location.hash.replace('#','.')).addClass('show');
});
$(".step1").find('button').on('click', function(e){
if(gun){ return }
gun = Gun('https://gunjs.herokuapp.com/gun');
gun.set({hello: "world"}).key(key);
});
$(".step2").find('button').on('click', function(e){
$(".browser").find("iframe").attr("src", "./tabs.html?key=" + key);
});
$(".step3").find('form').on('submit', function(e){
var val = $("#try-sync").val() || null;
var path = $("#try-path").val();
gun.load(key).path(path).set(val);
});
})
</script>
</div>
</div>
<!-- BEGIN TUTORIAL -->
<! OLD BLOG POST HERE -->
<style>
#main {
min-width: 250px;
max-width: 700px;
width: 75%;
margin: 7% auto;
padding: 2% 5%;
background: white;
background: rgba(100%,100%,100%,.6);
font-family: Arial;
font-size: 18pt;
text-shadow: 0px 0px 7px #DDD;
line-height: 20pt;
}
#main p {
text-indent: 2em;
}
</style>
<div id="main">
<h3>The blog that started it all...</h3>
<p>
Gun is a persisted distributed cache, part of a NoDB movement.
It requires zero maintenance and runs on your own infrastructure.
Think of it as <i>"Dropbox for Databases"</i> or a <i>"Self-hosted Firebase"</i>.
This is an early preview, so check out the <a href="https://github.com/amark/gun" target="_blank">github</a> and read on.
</p>
<p>
Everything gets cached, so your users experience lightning fast response times.
Since gun can be embedded anywhere javascript can run,
that cache can optionally be right inside your user's browser using localstorage fallbacks.
Updates are then pushed up to the servers when the network is available.
</p>
<p>
All conflict resolution happens locally in each peer using a deterministic algorithm.
Such that eventual consistency is guaranteed across all writes within the mesh,
with fault tolerant retries built in at each step. Data integrity is now a breeze.
</p>
<p>
Gun also establishes and repairs server to server communication across geographically separated machines,
with just the help of an initial IP from you.
It bridges the distance with a realtime connection,
so updates propagate at the speed of the raw pipes linking them.
However each server is intelligent enough to only subscribe to the necessary subsection of your data set that is in its working memory,
keeping things nimble for its connected users.
</p>
<p>
Data is then persisted to any S3 like service,
allowing you to save a truly webscale amount of "big data" without breaking your wallet.
Consistency across concurrency is achieved at this layer
by each parallel snapshot going through an idempotent transformation that is agreed upon.
The granularity and frequency of these snapshots can be tweaked by you,
easily tailor fitting it to your data needs and budget concerns.
</p>
<p>
<b>In summary,</b> this marks an important progression in web technologies.
Memory is getting cheap enough that we can now front load each connected user's active data
right into the application layer and manipulate it directly.
Networks are fast enough that if we get too many connected users we can just horizontally
redistribute them across different machines.
Conflict resolution algorithms are sophisticated enough to handle things immediately
in the majority of data cases, with the remaining few as transactions performed ontop.
<p>
This is will be a win for both developers and users,
because it makes things easier to build and faster to respond.
We are excited about this and working hard to finish the first release.
</p>
<p>
If you would like to learn more, email <a href="mailto:hi@gunDB.io">hi@gunDB.io</a> -
or join the <a href="http://groups.google.com/forum/#!forum/g-u-n" target="_blank">Google Group</a>.
Plus we're hiring, so contact us!
</p>
<h2>FAQ</h2>
<h4>Why did you build this thing?</h4>
<p>
1. I love databases, especially new ones that keep the working set in memory.
But I was horrified to realize that if I use a Database as a Service (DaaS)
then I would have to rely on a network call to get that data, which is horribly slow.
I wanted something faster, and if possible, cheaper - because they start charging you
outrageous prices if you get past their incredibly tiny free tier.
</p>
<p>
2. Hosting your own database is a pain because you have to maintain the hard drives.
Even the basic setup and configuration is nasty...
having to create a bunch of EBS volumes, attaching them, then mounting, formatting,
MDADM and LVM, striping, mirroring, and keeping fstab from locking on boot.
This is ignoring having to figure out how to resize them.
Even with SSDs you have problems that they are bound to one instance and
you get charged for the total volume size, not the amount used.
</p>
<p>
I wanted something easy, needing no maintenance and be extremely portable
- allowing me to spin up an ephemeral server anywhere, on any cloud,
and my data "just work" there.
</p>
<h4>How are you different from every other database that is trying to reinvent the wheel?</h4>
<p>
1. Because gun is not a database (NoDB), it is a persisted distributed cache.
The fatal flaw with databases is that they assume some centralized authority.
While this may be the case initially when you are small,
it always ceases to be true when you become large enough that concurrency is unavoidable.
No amount of leader election and consensus algorithms can patch this
without facing an unjustified amount of complexity.
Gun resolves all this by biting the bullet -
it solves the hard problems first, not last.
It gets data synchronization and conflict resolution right from the beginning,
so it never has to rely on vulnerable leader election or consensus locking.
</p>
<p>
2. Plus it embeds directly into your application,
so you can do your own custom queries with just pure programming logic.
Meaning you never have to learn some silly separate query language again.
A query language which just attempts to be some DSL to RPC another machine
into doing the same query you could have already written in half the time
it took to learn the query language. Because face it, any sufficiently capable
query language has to be Turing complete, and at that point -
why aren't you just writing your entire application logic in it?
Your app is nothing without your data.
</p>
</div>
<!-- END OLD BLOG POST -->
</body>
</html>

View File

@ -1,65 +0,0 @@
<div class="center fold stretch" style="background: url(./img/knockout.jpg) no-repeat 50% 50%; background-size: 100%;">
<div class="stretch stick" style="top: 50%; margin-top: -2.25em; font-family: arial;">
<div style="font-size: 4em; color: white; text-shadow: black 0px 0px 1em;">GAME OVER</div>
<button style="color: #400; font-size: 1.5em; background: red; padding: .75em; box-shadow: inset 0px 0px 2em 0px maroon; border: 1px solid #444;">
play again
</button>
<span>?</span>
</div>
</div>
<div style="float: left; max-width: 750px; width: 100%; padding: 2em; line-height: 1.25em; color: #ddd;">
<p>"You don't remember what happened, do you?"</p>
<p>Violence is a jarring thing. Imagine waking up and having no memory. No notion of who you are, where you came from, or why you were chosen.</p>
<p>Your identity, <i>erased</i>. This is your story, and you are about to discover how.</p>
<h2>Hi, I'm Plublious. Let me be your guide.</h2>
<p>"You've got a dreadful case of amnesia. I guess you're just gonna have to trust me."</p>
<p>"So hey, what's your name?"</p>
<div id="namethee"><button id="whoami">I don't know</button> or <input id="myname"> <button id="iam">is my name</button>.</div>
<p class="none" id="benamedbob">"You don't know? Well then, let's call you Bob."</p>
<p class="none" id="benamed">"Hi, <span class="name"></span>!"</p>
<div class="none" id="discover">
<p>"What is this all about?" <span class="name"></span> asks.
<div><button id="answers">Find out the answer</button> or <button class="upset">Be upset your questions are being written for you</button>.</div>
<div class="none" id="distributed">
<p>"Distributed systems."</p>
<p>"What?" <span class="name"></span> gawks.
<p>"Distributed systems."</p>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(function(){
$("#whoami").click(function(){ $("#namethee").addClass('none'); named("Bob"); });
$("#iam").click(function(){ $("#namethee").addClass('none'); named($('#myname').val()); });
function named(name){ $(".name").text(name); $("#benamed, #discover").removeClass('none'); };
$("#answers").click(function(){ $(this).closest('div').addClass('none'); $("#distributed").removeClass('none') })
})
</script>
<style>
html, body {
margin: 0;
padding: 0;
font-size: 16pt;
font-family: 'Palatino Linotype', Verdana;
background: black;
color: white;
}
.center {
text-align: center;
}
.fold {
height: 100%;
}
.stretch {
width: 100%;
}
.stick {
position: absolute;
}
.none {
display: none;
}
</style>

View File

@ -1,127 +0,0 @@
Alice comes online and does
`var todo = gun.get('todo')`
However she is the first peer, objectively, to be around.
Therefore, very quickly her query returns empty. So when she
`todo.put({first: "buy groceries"}).key('todo')`
the put has to generate a soul and GUN is instructed to associate 'todo' with that soul.
A few hours later, Bob comes online and does
`var todo = gun.get('todo')`
and thankfully he was connected to Alice so he gets her soul and node. So when he
`todo.put({last: "sell leftovers"}).key('todo')`
this was the expected and intended result, producing the following graph:
```{
'ASDF': {
_: {'#': 'ASDF', '>': {
first: 1,
last: 2
}},
first: "buy groceries",
last: "sell leftovers"
}
}```
For purposes of clarity, we are using states as if they were linearizable (this is not actually the case though).
Then Carl comes online and tries to
`var todo = gun.get('todo')`
But since he is not connected to Alice or Bob, gets an empty result.
Carl does nothing with it, meaning no mutation, no soul, no generation.
Then Dave comes online and does the same as everyone else:
`var todo = gun.get('todo')`
But Dave is only connected to Carl as a peer, therefore his get is empty. Like Alice, he then
`todo.put({remember: "eat food!", last: "no leftovers!"}).key('todo')`
Which unfortunately causes a new soul to be generated. Meanwhile, everybody then does the following:
`todo.on(function(val){ console.log(val) })`
Alice and Bob immediately get:
```{
_: {'#': 'ASDF', '>': {
first: 1,
last: 2
}},
first: "buy groceries",
last: "sell leftovers"
}```
But Carl and Dave immediately get:
```{
_: {'#': 'FDSA', '>': {
remember: 3,
last: 3
}},
remember: "eat food!",
last: "no leftovers!"
}```
However, a few hours later everybody gets connected. This is the graph everyone then has:
```{
'ASDF': {
_: {'#': 'ASDF', '>': {
first: 1,
last: 2
}},
first: "buy groceries",
last: "sell leftovers"
},
'FDSA': {
_: {'#': 'FDSA', '>': {
remember: 3,
last: 3
}},
remember: "eat food!",
last: "no leftovers!"
}
}```
But their `on` function triggers again, with the following `val` locally for everyone:
```{
first: "buy groceries",
remember: "eat food!",
last: "no leftovers!"
}```
GUN merges all the nodes with matching keys into a temporary in-memory object.
This way it is safe to get empty results and still put data into it,
Everyone will see a unified view of the data when they do get connected, as intended.
This solves the null, singular, and plural problems for get all together.
However, if we intentionally do not want to see a potentially conflicting unified view, any peer can:
`var todos = gun.all('todo')`
And have the discrete data via:
`todos.map(function(todo, soul){ console.log(todo) })`
Which would currently get called twice, with the distinct nodes of 'ASDF' and 'FDSA'.
The only thing that this does not address is how write operations (put/key) would effect `get` nodes.
However, I feel like finding the answer to that question will be much easier than trying to solve `get` in any other way.

View File

@ -1,32 +0,0 @@
OrderID CustomerID OrderDate
10308 2 1996-09-18
10309 37 1996-09-19
10310 77 1996-09-20
CustomerID CustomerName ContactName Country
1 Alfreds Futterkiste Maria Anders Germany
2 Ana Trujillo Emparedados y helados Ana Trujillo Mexico
3 Antonio Moreno Taquería Antonio Moreno Mexico
{
Orders: {
10308: {OrderID: 10308, Customer: {#: 2}, OrderDate: '1996-09-18' }
10309: {OrderID: 10309, Customer: {#: 3}, OrderDate: '1996-09-19' }
10310: {OrderID: 10310, Customer: {#: 77}, OrderDate: '1996-09-20' }
}
Customers: {
1: {CustomerID: 1, CustomerName: "Alfreds Futterkiste", ContactName: "Maria Anders", Country: "Germany" }
2: {CustomerID: 2, CustomerName: "Ana Trujillo Emparedados y helados", ContactName: "Ana Trujillo", Country: "Mexico" }
3: {CustomerID: 3, CustomerName: "Antonio Moreno Taquería", ContactName: "Antonio Moreno", Country: "Mexico" }
}
}
gun.sql().select('OrderID', 'Customers.CustomerName', 'OrderDate').from('Orders').join('Cutomers').on('Customer'); // ignore /\s*=/ig and beyond
^compatibility. // select should accept 1 string that is /\,\s*/ig separated, arguments of strings, an array of strings.
// unfortunately for compatibility mode, you might have to match&strip any string that has a '.' in it with a subsequent .join/.on
better:
gun.sql().select('OrderID', OrderDate').from('Orders').join.on('Customer').select('CustomerName').run().get(function(row){
console.log(row); // {OrderID: 10308, CustomerName: "Ana Trujillo Emparedados y helados", OrderDate: "1996-09-18" }
});

View File

@ -1,135 +0,0 @@
HOOKS:
- TRANSPORT:
Has to basically re-implement set/get/key/all over some transport.
REMEMBER that you have to subscribe on all set/get/key/all (especially key).
Notes:
Messaging
Every message has who/what/when/where/why/how metadata.
Who is information that identifies the potential keys or locations a reply should be made to, such that a user can receive it no matter where they are
What is the message/delta itself
When is when the message was sent, this may have no relation to a timestamp on a delta transmission
Where is the destination that the message is trying to get to, and the paths it has taken to get there
Why is any arbitrary comment
How is the transformation that caused the message, and potentially the expected transformation to happen
Data
Because data can be in more than one place at a time, its identifier should not be mixed with any whereabouts even if you are planning on only using it within your walled garden.
Instead, the data itself should express its particular locality - information about a statue in Rome should not be identified a being Roman, but express it is Roman.
Therefore, preferrably the identifier for a thing should be globally unique, in case it is ever shared by multiple services - that way conflict won't happen.
This is important because that way any service is forced to do a scan on its own dataset to match with this service's own identifier and link them together - or start fresh if no match exists.
Information is not deleted, mostly just dereferenced - which may eventually cause cold storage, and loss of data as every system has physical limitations.
Arrays cannot be supported because cardinality is actually an expression of the data, not an identifier - for if it were, it would cause concurrency problems resulting in divergence.
Identifiers
Reality seems to be lacking any true identifiers because we perceive things in incredibly mutable states.
Often times attributes that may appear to be static are in fact not - take for instance the color of a car.
One generally assumes that the color will not change, since it is not observed much - however the lifetime of a program may outlive the developer. Even the sun will go dark one day.
This is the power of graphs, particularly in a functional setting - they are searchable, potentially timelessly.
As such identifiers should only be created in response to an attempt to match incoming unfound data with data stored.
If successful, the service is free and should make as many extra identifiers to reference and link that data again as to avoid doing slow scans again.
The most likely candidate for that identifier is the identifier that was given to the service, as there is high probability that the requester will make such requests again.
Throught his means, an identifier can spread like a virus through multiple services, where if it exists it can be retrieved immediately.
Thus, no one identifier should potentially conflict with any other identifier, as that would produce an erroneous lookup and a faulty response.
Do identifiers point to subsets or nodes, or both? Where do identifiers live? Ever in the graph itself? A developer of course would want an identifier to point to both.
However this is a little tricky, because a single node by itself is fairly useless (hermeneutics) because it has no context, especially if it is composed of many parts.
So an identifier referencing a "single node" should technically pull in its relations as well, into the subset. But what then do we return to the developer? The subset or the node?
If you assume the node, then identifiers "point" to different types of data - unless we allow the node the same methods as the subset, where map returns itself.
If we return the subset, it is inconvenient that you then have to scan for the thing you were already identifying, unless the map method also accepts traversal strings.
Identifiers are suppose to intentionally allow humans to think in a document based perspective, however there is no guarantee that the pieces in their system will remain that way.
Take for example a car, you'd assume that the wheel is part of the car and should be referenced as such. But what happens when the tire pops? It is removed and then used as a swing.
Now tell me, the "belongingness" of the tire is now in the hierarchy of the tree that it was hung on. Hierarchy is imposed by directional relations, not as static structures.
So there must be a way to evolve the system, for if we assume the identifier now references the subset, giving context to the original node, we need all of them to be uniquely referenced.
The unique references are the system's internal IDs, not the human friendly identifiers, these must be system-wide guaranteed to be unique.
But if everything has one, no matter how small, then that increases the odds quite substantially of conflicts. Meaning larger IDs need to be generated, which is never pretty.
This also then causes scanning issues, cause now countless tiny nodes are floating around in the system that will get mapped over, that is unpleasant for the developer.
Unless of course there are really good tools that allow them to map with string traversals (known paths) and value traversal (matching structures), in addition to the callback.
Meaning everything should be its own object, but really good search tools should be available to make this easy.
If this is the case, enforce the many-solution, that you alway have a subset and never a single node - a single node is just a subset of one.
Or is it? Or is it the subset of the things that compose the node? Do you hide these from the developer? Expose them?
It seems like subset of one works fine when you already have the larger subset, but not when you are using the initial identifier.
So can we mitigate that by providing really good priority loading tools?
Special Characters
These are reserved for gun, to include meta-data on the data itself.
/ is used as a delimiter in service specific identifiers
# is used to define the transition from a graph identifier, into the nodes themselves
. represents walking the path through a node's scope
_ represents non-human data in the graph that the amnesia machine uses to process stuff
> and < are dedicated to comparing timestamp states, timelessly to avoid malicious abuse (this should always come last, because requests will be rejected without it)
~ is who
* relates to key prefixes
*> lexical constraint
*< lexical constraint
@ is where it should be delivered to.
@> is where it has been or will be rebroadcasted through.
% is for byte constraints.
: is time
$ is value
' is for escaping characters contained within '
{
who: {}
,what: {'#": 'email/hi@example.com'}
,when: {'>': 1406184438192 }
,where: {}
,how: '*'
}
{
_: {
#: 'email/hi@example.com'
>: 1406184438192
}
}
Stream
If we receive a message with data at a symbolic scope that doesn't exist we should still save it.
However if we attempt to read it, we should be unable to access it because the symbols haven't been connected.
That way idempotently, when the symbols are connected, it'll then be readable if they haven't already been overwritten.
Grouping of symbols always inherit and merge, if all of them need to be dereferenced you must explicitly dereference it.
How do we do memory management / clean up then of old dead bad data?
Init
You initialize with a node(s) you want to connect to.
DISK
We might want to compact everything into a journal, with this type of format:
#'ASDF'.'hello'>12743921$"world"
Over the wire though it would include more information, like the ordering of where it has/will-be traversed through.
@>'random','gunjs.herokuapp.com','127.0.0.1:8080':7894657#'ASDF'.'hello'>12743921$"world"
What about ACKs?
@'random':7894657#'ASDF'.'hello'>12743921
There is a limited amount of space on a machine, where we assume it is considered ephemeral as a user viewing device.
Such machines are the default requiring no configuration, machines that are permanent nodes can configure caps.
For instance, the browser would be a looping ephemeral device, where the 5mb localStorage gets recycled.
The localhost server of that device would be permanent and not loop, but halt when storage runs out.
By thus virtue of this, clients should be able to throttle (backpressure) their data intake.
The size of primitive values is fundamentally outside our control and left to the developer or multiparting.
If they decide to have a string that exceeds memory or local disk then their app will always fail regardless of multiparting.
However it is our duty to make sure that the rest of the structured data is streamable, including JSON.
Therefore networks and snapshotting should throttle to a size limit specified by the requesting agent.
Resuming these requests will be based soley on a lexical cursor included in the delivery, to avoid remembering state.
The asynchronicity of these lexical cursor could pose potential concurrency issues, and have to be considered ad hoc.
That is to say, if you are dealing with a large data set, you should always subscribe to updates it and never merely "get" it.
For the edge case of the singleton "get", the lexical cursor will progress until it receives the same or no cursor back from the server and terminate.
total over a range of time: {"alice", "bob", "carl", "david", "ed", "fred", "gary", "harry", "ian", "jake", "kim"}
client requests "users" at limit of 30 characters, server replies with (rounded down) {"alice", "bob", "carl"}.
after a while the client has processed this and goes for the next step, requesting /users?*>=carl&%=30 and {"david", "ed", "fred", "gary"} is returned.
then again /user?*>gary&%=30 with {"harry", "ian", "jake", "kim"} response.
then again /user?*>kim&%=30 with {} response. No subsequent cursor is possible, end.
Note: I do not know yet if the lexical cursor should be open-closed boundary, open-open, closed-closed, or closed-open - decide later.

View File

@ -1,21 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://gunjs.herokuapp.com/gun.js"></script>
</head>
<body style="white-space: pre;">
loading...
<script>
var key = decodeURIComponent((location.search.match(/key\=(.*?)(\&|$)/i)||[])[1]||'') || alert("Please provide a key in a query parameter, such as `?key=example/tutorial`.");
var gun = Gun('https://gunjs.herokuapp.com/gun');
var ref = gun.get(key);
ref.on(function(data){
delete data._;
$('body').text(JSON.stringify(data,0,2));
});
</script>
</body>
</html>

View File

@ -1,406 +0,0 @@

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./dep/jquery.js"></script>
</head>
<body>
<p>Before we can start building anything interesting, we should have a way to jot down our thoughts. Therefore the first thing we will build is a tool to keep track of what needs to be done. The infamous To-Do app, allowing us to keep temporary notes.</p>
<p>So what are the requirements? The ability to add a note, read our notes, and to clear them off. We will also need a space to keep these notes in, and a web page to access them through. Let's start with the page! You can edit the code below, which will update the live preview.</p>
<div class="edit">... loading editor and preview ...
<textarea style="height: 13em"><html>
<body>
<h1>Title</h1>
<form>
<input><button>Add</button>
</form>
<ul></ul>
</body>
</html></textarea>
</div>
<script>
var code = $('.edit').load('./editor.html', function(){setTimeout(function(){
var editor = $('.CodeMirror')[0].CodeMirror;
editor.live(function(frame){
$('body', frame).on('submit', 'form', function(e){e.preventDefault()});
});
editor.setValue(code);
},1)}).find('textarea').text();
</script>
<style>
.none { display: none }
.step-at { display: block }
textarea { border: none; width: 100%; }
</style>
<div id="step-1" class="step">
<p>What does this do? HTML is how we code the layout of a web page.</p>
<ul>
<li>We first must wrap all our code in an open and closing <u>html</u> tag so our computer knows it is a web page.</li>
<li>The <u>body</u> tag tells it to display the contents enclosed within.</li>
<li><u>h1</u> is one of many semantic tags for declaring a title, others include <u>h2</u>, <u>h3</u> and so on of different sizes.</li>
<li>A <u>form</u> is a container for getting information from a user.</li>
<li>Forms have <u>input</u>s which let the user type data in, it is a self-closing tag.</li>
<li>The <u>button</u> can be pressed, causing an action that we code to happen.</li>
<li><u>ul</u> is an unordered list which we will display our thoughts inside of.</li>
</ul>
<p>Now, try changing the <u>h1</u> text in the editor from "Title" to the name of our app, "Thoughts".</p>
<button class="none">I've done it!</button>
<textarea id="code-1" class="none" style="height: 14em"><html>
<body>
<h2>Thoughts</h2>
<form>
<input><button>Add</button>
</form>
<ul></ul>
<!-- Replace this Comment Line with the Code in the Step below! -->
</body>
</html></textarea>
</div>
<div id="step-2" class="step">
<p>HTML controls the layout, but how do we control what happens when a user presses the 'add' button? This is done with javascript. But using raw javascript quickly becomes verbose, so to keep things concise we will use a popular tool called jQuery. We also need a tool to store data, so we will include GUN as well.</p>
<p>Insert the following between the ending <u>ul</u> tag and the ending <u>body</u> tag, replacing the comment line:</p>
<textarea style="height: 6em;">
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://rawgit.com/amark/gun/master/gun.js"></script>
<script>
alert("Good job! You'll replace this line in the next step!");
</script></textarea>
<ul>
<li>The <u>script</u> tag tells the browser to use some javascript code, and <u>src</u> is where to load it from.</li>
<li>We can then test to see if our code worked with an <u>alert</u> message, which pops up and forces you to press ok.</li>
<li>In javascript, we denote text by wrapping it inside quotation marks, double <u>""</u> or single <u>''</u>.</li>
<li>We instruct the computer to notify us with that text by calling the <u>alert</u> function using parenthesis <u>()</u>.</li>
<li>A function is just a fancy word for a reusable piece of code that does something when we call its name, such as <u>alert</u>.</u>
<li>A semicolon <u>;</u> marks the end of a javascript sentence in the same way a period marks the end of a sentence.</li>
</ul>
<button class="none">It worked.</button>
<textarea id="code-2" class="none" style="height: 14em"><html>
<body>
<h2>Thoughts</h2>
<form>
<input><button>Add</button>
</form>
<ul></ul>
</script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</script src="https://rawgit.com/amark/gun/master/gun.js"></script>
</script>
alert("Good job! You'll replace this line in the next step!");
</script>
</body>
</html></textarea>
</div>
<div id="step-3" class="step">
<p>Wonderful! You should have gotten the alert message, this means writing code works! Let's replace the alert line entirely with code that responds to user input.</p>
<textarea style="height: 5em;">
$('form').on('submit', function(event){
event.preventDefault();
alert("We got your thought! " + $('input').val());
});</textarea>
<p>What's going on here?</p>
<ul>
<li>jQuery is a function like <u>alert</u>, its name is <u>$</u> which can be called with parenthesis <u>()</u>.</li>
<li>Calling <u>$</u> with <u>'form'</u> as the input gives us a reference to the corresponding HTML form tag.</li>
<li>We then call <u>on</u> with two inputs. First the text name of an <u>event</u> we want to react to, and then a <u>function</u> we create.
<ul>
<li>Events are predefined ways we can interact with a user, such as <u>'mousemove'</u> or a <u>'keypress'</u>.</li>
<li>We use <u>'submit'</u> because it responds to both a button <u>'click'</u> and hitting enter on a form.</li>
<li>Our <u>function</u> will get called with the <u>event</u> every time the user does that action, allowing us to react to their input.</li>
</ul>
<li>The default behavior of a form is to cause the browser to change pages which is annoying, we prevent that by calling <u>preventDefault</u> on the <u>event</u>.</li>
<li>Finally, calling <u>$</u> with <u>'input'</u> will reference the HTML input tag which we then call <u>val</u> on, giving us the text the user typed in.</li>
</ul>
<button class="none">Got it.</button>
<textarea id="code-3" class="none" style="height: 14em"><html>
<body>
<h2>Thoughts</h2>
<form>
<input><button>Add</button>
</form>
<ul></ul>
</script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</script src="https://rawgit.com/amark/gun/master/gun.js"></script>
</script>
$('form').on('submit', function(event){
event.preventDefault();
alert("We got your thought! " + $('input').val());
});
</script>
</body>
</html></textarea>
</div>
<div id="step-4" class="step">
<p>Now that users can jot down their thoughts, we need a place to save them. Let's start using GUN for just that.</p>
<textarea style="height: 1em;">
var gun = Gun().get('thoughts');</textarea>
<ul>
<li>The <u>var</u>iable keyword tells javascript that we want to create a reference named <u>gun</u> that we can reuse.</li>
<li>We call <u>Gun</u> to start the database, which only needs to be done once per page load.</li>
<li>Now we want to open up a reference to some data, so we call <u>get</u> with the name of the data we want.</li>
<li>However, no data has been saved to <u>'thoughts'</u> yet! Let's fix that in the next step by using <u>gun</u>.</li>
</ul>
<button class="none">Let's do it!</button>
<textarea id="code-4" class="none" style="height: 14em"><html>
<body>
<h2>Thoughts</h2>
<form>
<input><button>Add</button>
</form>
<ul></ul>
</script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</script src="https://rawgit.com/amark/gun/master/gun.js"></script>
</script>
var gun = Gun().get('thoughts').set();
$('form').on('submit', function(event){
event.preventDefault();
alert("We got your thought! " + $('input').val());
});
</script>
</body>
</html></textarea>
</div>
<div id="step-5" class="step">
<p>Replace the alert line in the submit function with the following:</p>
<textarea style="height: 2.5em;">
gun.set($('input').val());
$('input').val("");</textarea>
<ul>
<li>We're telling gun to add the value of the input as an item in a <u>set</u> of thoughts.</li>
<li>Then we also want the input's <u>val</u>ue to become empty text, so we can add new thoughts later.</li>
</ul>
<button class="none">Show me the data!</button>
<textarea id="code-5" class="none" style="height: 14em"><html>
<body>
<h2>Thoughts</h2>
<form>
<input><button>Add</button>
</form>
<ul></ul>
</script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</script src="https://rawgit.com/amark/gun/master/gun.js"></script>
</script>
var gun = Gun().get('thoughts').set();
$('form').on('submit', function(event){
event.preventDefault();
gun.set($('input').val());
$('input').val("");
});
</script>
</body>
</html></textarea>
</div>
<div id="step-6" class="step">
<p>Fantastic! Now that we can successfully store data, we want show the data! Replace the comment line in the editor with the following:</p>
<textarea style="height: 9em;">
gun.on().map(function(thought, id){
var li = $('#' + id).get(0) || $('<li>').attr('id', id).appendTo('ul');
if(thought){
$(li).text(thought);
} else {
$(li).hide();
}
});</textarea>
<ul>
<li>In the same way $'s <u>on</u> reacts to events, so does gun. It responds to any update on 'thoughts'.</li>
<li><u>map</u> calls the <u>function</u> you input into it for each item in the set, one at a time.</li>
<li>We get the <u>thought</u> value itself and a unique <u>id</u>entifier for the item in the set.</li>
<li>This next line looks scary, but read it like this, "make <u>var</u>iable <u>li</u> equal to X or Y".
<ul>
<li>The X part asks <u>$</u> to find the <u>id</u> in the HTML and <u>get</u> it.</li>
<li>In javascript, <u>||</u> means 'or', such that javascript will use X if it exist or it will use Y.</li>
<li>The Y part asks <u>$</u> to create a new <u>&lt;li&gt;</u> HTML tag, set its <u>id</u> <u>attr</u>ibute to our id and <u>append</u> it to the end of the HTML <u>ul</u> list.</li>
</ul></li>
<li>Finally, the javascript <u>if</u> statement either asks <u>$</u> to make <u>thought</u> be the text of the <u>li</u> if thought exists, <u>else</u> hide the <u>li</u> from being displayed.</li>
<li>Altogether it says "Create or reuse the HTML list item and make sure it is in the HTML list, then update the text or hide the item if there is no text".</li>
</ul>
<button class="none">I've tried adding a thought!</button>
<textarea id="code-6" class="none" style="height: 14em"><html>
<body>
<h2>Thoughts</h2>
<form>
<input><button>Add</button>
</form>
<ul></ul>
</script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</script src="https://rawgit.com/amark/gun/master/gun.js"></script>
</script>
var gun = Gun().get('thoughts').set();
$('form').on('submit', function(event){
event.preventDefault();
gun.set($('input').val());
$('input').val("");
});
gun.on().map(function(thought, id){
var li = $('#' + id).get(0) || $('<li>').attr('id', id).appendTo('ul');
if(thought){
$(li).text(thought);
} else {
$(li).hide();
}
});
</script>
</body>
</html></textarea>
</div>
<div id="step-7" class="step">
<p>Finally we want to be able to clear off our thoughts when we are done with them. The interface for this could be done in many different ways, but for simplicity we will use a double tap as the gesture to clear it off. Replace the comment line in the editor with this code.</p>
<textarea style="height: 4em;">
$('body').on('dblclick', 'li', function(event){
gun.path(this.id).put(null);
});</textarea>
<ul>
<li>In order to react to any <u>'dblclick'</u> event rather than a specific one, we call <u>on</u> on the page's <u>'body'</u> as a whole.</li>
<li>But we want to filter the events to ones that happened only on any <u>'li'</u> tag. Fortunately, we can call <u>on</u> with an optional second input of <u>'li'</u> which does just that.</li>
<li>Inside a <u>function</u> we get a special <u>this</u> keyword in javascript, which <u>$</u> uses as a reference to the original HTML tag that caused the event.</li>
<li>Calling <u>path</u> tells <u>gun</u> to filter its data to just the <u>id</u> of the thought we want to clear off.</li>
<li>Then calling <u>put</u> on that tells gun to update that thought to <u>null</u>, so we no longer have the thought.</li>
<li>And whenever an update happens, <u>gun</u>'s <u>on</u> function from the previous step gets called again, which then hides the corresponding HTML list item.</u>
</ul>
<button class="none">Done!</button>
<textarea id="code-7" class="none" style="height: 14em"><html>
<body>
<h2>Thoughts</h2>
<form>
<input><button>Add</button>
</form>
<ul></ul>
</script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</script src="https://rawgit.com/amark/gun/master/gun.js"></script>
</script>
var gun = Gun().get('thoughts').set();
$('form').on('submit', function(event){
event.preventDefault();
gun.set($('input').val());
$('input').val("");
});
gun.on().map(function(thought, id){
var li = $('#' + id).get(0) || $('<li>').attr('id', id).appendTo('ul');
if(thought){
$(li).text(thought);
} else {
$(li).hide();
}
});
$('body').on('dblclick', 'li', function(event){
$(this).remove();
gun.path(this.id).put(null);
});
</script>
</body>
</html></textarea>
</div>
<div id="step-8" class="step">
<p>Congratulations! You are all done, you have built your first GUN app!</p>
<p>In the next tutorial we will use GUN to synchronize data in realtime across multiple devices. We'll start by copying the app we made here and modifying it to become a chat app.</p>
<a href="./converse.html">Next Tutorial: Converse</a>
</div>
<script>
$('.step').addClass('none').first().addClass('step-at');
$('button').on('click', next).removeClass('none');
function next(){
$('.step-at').removeClass('step-at');
$('#step-' + (++next.at)).addClass('step-at');
(next.step[next.at] || function(){})();
}
next.at = 1;
next.comment = /\s*\/\*(.*?)\*\/\s*/i;
next.unwrap = /\s*<\/?(html|body)>\s*\s*/ig;
next.wrap = function(c){ return '<html>\n\t<body>\n\t\t' + c + '\n\t</body>\n</html>' }
next.code = function(){ return $('<div>' + next.mir.getValue().replace(next.wrap, '') + '</div>') }
next.step = [null, null, function(){
next.mir = $('.CodeMirror')[0].CodeMirror;
var code = next.code();
if(code.find('h1').text().toLowerCase() == 'title'){
code.find('h1').text('Thoughts');
}
next.mir.setValue(next.wrap($.trim(code.html()) + "\n<!-- Replace this Comment Line with the Code in the Step below! -->"));
}, function(){
var code = next.code();
var ctx = {$: true, gun: true, alert: true};
code.find('script').each(function(){
var src = ($(this).attr('src') || '').toLowerCase();
if(src.indexOf('jquery')){ ctx.$ = false }
if(src.indexOf('gun')){ ctx.gun = false }
if(($(this).text()||'').indexOf('alert')){ ctx.alert = false }
});
code.contents().filter(function(){ return this.nodeType == 8 }).remove();
var ul = code.find('ul');
if(ctx.alert){ ul.after($('<script>').text('\n\t\t\talert("Good job! Our code will go in this script tag!");\n\t\t')) }
if(ctx.gun){ ul.after($('<script>').attr('src', 'https://rawgit.com/amark/gun/master/gun.js')) }
if(ctx.$){ ul.after($('<script>').attr('src','https://code.jquery.com/jquery-1.11.3.min.js')) }
if(ctx.alert || ctx.gun || ctx.$){ next.mir.setValue(next.wrap($.trim(code.html().replace(/<script/ig, '\n\t\t<script')))) }
}, function(){
var code = next.code();
var script = code.find('script').last();
if(0 > script.text().indexOf('.on')){
script.text('\n' + script.text().replace(/\s*alert.*\n/i, $('#step-3').find('textarea').first().text() + '\n'));
}
script.text('\n/* Replace this Comment Line with the Code in the Step below! */' + script.text());
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
script.text(script.text().replace(next.comment, ''));
if(0 > script.text().indexOf('Gun')){
script.text('\n' + $('#step-4').find('textarea').first().text() + "\n\t\t\t" + script.text());
}
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
if(0 < script.text().indexOf('alert')){
script.text(script.text().replace(/\s*alert.*\n/i, '\n' + $('#step-5').find('textarea').first().text() + '\n'));
}
script.text(script.text() + '\n/* Replace this Comment Line with the Code in the Step below! */\n\t\t');
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
if(0 > script.text().indexOf('.map')){
script.text(script.text().replace(/\s*.*replace.*\n/i, '\n' + $('#step-6').find('textarea').first().text()));
}
script.text(script.text() + '\n/* Replace this Comment Line with the Code in the Step below! */\n\t\t');
next.mir.setValue(next.wrap($.trim(code.html())));
}, function(){
var code = next.code();
var script = code.find('script').last();
if(0 > script.text().indexOf('gun.path')){
script.text(script.text().replace(/\s*.*replace.*\n/i, '\n' + $('#step-7').find('textarea').first().text() + '\n'));
}
next.mir.setValue(next.wrap($.trim(code.html())));
}]
</script>
</body>
</html>

View File

@ -1,232 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://dl.dropboxusercontent.com/u/4374976/random/phrase.js"></script>
</head>
<body class="tutorial">
<script src="https://gunjs.herokuapp.com/gun.js"></script>
<link id="style" rel="stylesheet" href="https://yandex.st/highlightjs/8.0/styles/ir_black.min.css">
<script src="https://yandex.st/highlightjs/8.0/highlight.min.js"></script>
<style>
@import url(https://fonts.googleapis.com/css?family=Dosis|Poiret+One|Oxygen);
.tutorial {
margin: 0;
padding: 0;
he-ight: 100%;
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
background: #222;
color: #eee;
overflow: auto;
}
.center {
text-align: center;
}
.lean {
font-family: 'Poiret One', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.clean {
font-family: 'Dosis', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.crisp {
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
pre {
background-color: black;
border: 1px dashed white;
color: white;
line-height: 1.5em;
padding: .5em;
margin: 0em;
overflow: auto;
}
button {
border: none;
color: white;
background: skyblue;
padding: 1em;
cursor: pointer;
}
.hide {
display: none;
}
.show {
display: block;
}
.grid {
text-align: center;
}
.unit {
display: inline-block;
}
.main {
min-width: 250px;
max-width: 1024px;
width: 90%;
margin: 0% auto;
padding: 2% 5%;
}
div {
position: relative;
}
.left { float: left;}
.teft { text-align: left; }
.middle {
vertical-align: middle;
}
.full {
width: 100%;
}
</style>
<div class="main">
<div style="font-size: 18pt; margin: 0 0 .75em;">Try it now</div>
<div class="step show step1">
<div class="full grid">
<div class="middle unit teft">
<pre style="max-width: 30.1em; margin: 0 1em 1em 0;">var gun = Gun('https://gunjs.herokuapp.com/gun');
gun.put({hello: "world"}).key('<span class="your-key">example/tutorial</span>');</pre>
</div>
<div class="middle unit teft" style="min-width: 20em; max-width: 28em; margin-bottom: 1em;">
<a href="#step2"><button class="left" style="margin-right: 1em;"><big>Run!</big></button></a>
In this <b>1 minute</b> tutorial, we will connect to a gun peer, create an object, and sync data in realtime.
</div>
</div>
</div>
<div class="step hide step2">
<div class="full grid">
<div class="middle unit teft">
<pre style="max-width: 30.1em; margin: 0 1em 1em 0;">var ref = gun.get('<span class="your-key">example/tutorial</span>');
ref.on(function(data){
$('body').text(JSON.stringify(data));
});</pre>
</div>
<div class="middle unit teft" style="min-width: 34em; max-width: 28em; margin-bottom: 1em;">
<a href="#step3"><button class="left" style="margin-right: 1em; background: MediumSpringGreen;"><big>Next</big></button></a>
Congratulations! You just made an object and saved a reference to it.
In two tabs, we'll load that key to open a shared reference.
</div>
</div>
</div>
<div class="step hide step3">
<div class="full grid">
<style>
.browser {
background: white;
border-radius: .25em;
width: 250px;
//height: 300px;
color: #222;
margin: .5em;
overflow: hidden;
}
.b-bar {
background: #EEE;
border-radius: .25em .25em 0 0;
}
.b-but {
float: left;
width: 1em;
height: 1em;
}
.browser a {
text-decoration: none;
background: white;
border-radius: .4em;
padding: 0 1em;
color: #555;
}
.browser iframe { border: none; }
</style>
<div class="browser unit teft">
<div class="b-bar">
<div class="b-but">&larr;</div>
<div class="b-but">&rarr;</div>
<div class="b-but"><small>&#8635;</small></div>
<small><small><span>
<a href="https://gunjs.herokuapp.com/" target="_blank">https://gunjs.herokuapp.com/</a>
</span></small></small>
<small class="center" style="position: relative; top: -.14em;">x</small>
<span class="center">&equiv;<span>
</div>
<iframe></iframe>
</div>
<div class="browser unit teft">
<div class="b-bar">
<div class="b-but">&larr;</div>
<div class="b-but">&rarr;</div>
<div class="b-but"><small>&#8635;</small></div>
<small><small><span>
<a href="https://gunjs.herokuapp.com/" target="_blank">https://gunjs.herokuapp.com/</a>
</span></small></small>
<small class="center" style="position: relative; top: -.14em;">x</small>
<span class="center">&equiv;<span>
</div>
<iframe></iframe>
</div>
</div>
<form action="#step3" onsubmit="return false;">
<style>
#step3 input {
width: 6em;
}
</style>
<div class="grid">
<div class="middle unit teft">
<pre style="max-width: 40em; margin: 0 1em 1em 0;">ref.path('<input id="try-path" value="hello">').put("<input id="try-sync" value="sync">");</pre>
</div>
<div class="middle unit teft" style="min-width: 20em; max-width: 30em; margin-bottom: 1em;">
<button type="submit" class="left" style="margin-right: 1em;"><big>Update!</big></button>
Let's update the "hello" field with a different value.
We can path into any field, and update it directly.
</div>
</div>
</form>
</div>
<script>
$(function(){
var gun, key = "random/" + Gun.text.random(9),
hili = function(){
$("pre").each(function(){
hljs.highlightBlock(this);
})
}
$(".your-key").text(key);
hili();
location.hash = 'step1';
$(window).on('hashchange', function(){
$('.step').removeClass('show').addClass('hide')
$(location.hash.replace('#','.')).addClass('show');
});
$(".step1").find('button').on('click', function(e){
if(gun){ return }
gun = Gun('https://gunjs.herokuapp.com/gun');
gun.put({hello: "world"}).key(key);
});
$(".step2").find('button').on('click', function(e){
$(".browser").find("iframe").attr("src", "./tabs.html?key=" + key);
});
$(".step3").find('form').on('submit', function(e){
var val = $("#try-sync").val() || null;
var path = $("#try-path").val();
gun.get(key).path(path).put(val);
});
})
</script>
</div>
</body>
</html>

View File

@ -1,65 +0,0 @@
WIRE PROTOCOL
put/save/set/create/post/delete/update/change/mutate
get/open/load/call/location/address
key/name/reference/index/point
/gun {data: 'yay', #: "soul"}
/gun/key {#: 'soul'}
/gun/key
/gun/key?*=/&*<=a&*>=c
Reads are a GET and do not contain a body.
Writes have a body.
Reads may call the callback multiple times, and will end with an empty object.
Reads are either a singular pathname or pound query to get a key or soul's individual node.
Or a read is to retrieve information on many key's and their corresponding soul.
Query formats are allowed as:
?
* = /
star means the peer should reply with all the KEYS it has up to the character in the value of the query.
Ex. "/users/?*=/" would return {"users/marknadal": {"#": "ASDF"}, "users/ambernadal": {"#": "FDSA"}}
If there is no up to character, then all subkeys would be returned as well.
The peer does not have to reply with all of its keys, however if there are more keys for the receiving peer, it should give it a lexical cursor. (how?)
Ordering is not guaranteed, however if there is ordering, it should be lexical. Therefore things like limit or skip do not necessarily apply.
*> = a
*< = c
star greater than and star less than are lexical constraints on returning all peers KEYS.
Ex. "/users/?*=/&*>=a&*<=c" asks the peer to return users that start and end between 'a' and 'c',
thus {"users/alice": {"#": "DSAF"}, "users/bob": {"#": "DAFS"}, "user/carl": {"#": "SAFD"}}
# = ASDF
pound means the peer should reply with a graph node that has this exact soul. There should be no key prefixed path on this type of request. A special case of "#=*" indicates to literally dump the entire graph, as is, to the client. Lexical carets are okay.
% = 30
percent means byte constraint requested by the peer asking for data.
> = 1426007247399
< = 1426007248941
greater than and less than are time/state constraints, allowing a peer to request historical data or future data.
the peer processing the request ought to reply with such state data if it has it, but has no requirement to keep such data (but is encouraged to do so).
Using query constraints is generally not advised, as it is better to do all computation at the point of data, or have all data at the point of computation, not inbetween.
This protocol should work over HTTP, or the JSONP fallback specification, and emulated over WS or WebRTC.
On a separate note, it might be advantageous to chunk node objects into pieces as well, in case they grow too big or especially contain too many field/value pairs. If this was built into the behavior, to handle better streaming and lower memory use cases, it would also become ideal for groups of data without any extra logic or behavior.
There are three types of grouped related data:
1. Dependent Causality (videos, audio, etc.)
2. Relative Ordering (age, height, users, etc.)
3. Independent
Obviously independent data is fairly uninteresting, as the HAM can handle convergence just on states alone. Relative ordering requires only application specific logic to sort data for the view, or computing averages and such. They can always be streamed in efficiently by creating indices on the desired properties and then doing lexical loading. Any conflict in ordering on one property can be handled by cascading into other properties, like from sort order to then creation date. By this means, all data should be explicitly recorded, not implicit.
Dependent Causality is the most interesting, and unfortunately not conducive towards efficient means of streaming. This means the data must be sorted in a particular direction, and even if you receive a "later" chunk, you should not reveal it until all earlier chunks have been digested. Which might means you have to discard it from memory if space runs out, and then pull it back in again at the right time. Let's look at some differences here with some concrete examples.
If we have 4 people in the back room, and we want to sort them by height as they come on to stage, then order in which they come out from behind does not matter. Say their heights are 4, 5, 6, and 7 feet tall. When the first one comes out we do not need to do anything, where the 6 is the first one. Then the second one comes out and is 4, so we put them to the left of the first. Then third comes out the 7, and we put them to the right of the first. Finally, the fourth comes out as the 5, and we put them inbetween the first and second. This method allows us to incrementally sort and always see the correct ordering without waiting.
However, lets say we have collaborative text. We have the initial text of "Hello" and an editor named Alice adds ", World!" in which each letter (' ', ',', 'W', 'o', 'r', 'l', 'd', '!') is streamed, potentially out of order, to Bob. We are going to assert that relative ordering does not work because, for the sake of explanation, any individual letter could be lost in the mail as they are sent. The last thing we want is Bob receiving the three characters 'old', which has correct relative ordering but wrong dependency, and thinking Alice is insulting him for being senile. Therefore every letter should specify the message that comes before it, the letter that it depends upon.