Browse Source

URL support

dev/git-series/gccdum
Matt Godbolt 6 years ago
parent
commit
1c98836ee6
  1. 3
      bower.json
  2. 3
      static/clippy.svg
  3. 12
      static/explorer.css
  4. 26
      static/index.html
  5. 51
      static/main.js
  6. 32
      static/url.js

3
bower.json

@ -24,6 +24,7 @@
"bootstrap": "^3.3.7",
"selectize": "^0.12.2",
"eventEmitter": "^5.1.0",
"lz-string": "^1.4.4"
"lz-string": "^1.4.4",
"clipboard": "^1.5.12"
}
}

3
static/clippy.svg

@ -0,0 +1,3 @@
<svg height="1024" width="896" xmlns="http://www.w3.org/2000/svg">
<path d="M128 768h256v64H128v-64z m320-384H128v64h320v-64z m128 192V448L384 640l192 192V704h320V576H576z m-288-64H128v64h160v-64zM128 704h160v-64H128v64z m576 64h64v128c-1 18-7 33-19 45s-27 18-45 19H64c-35 0-64-29-64-64V192c0-35 29-64 64-64h192C256 57 313 0 384 0s128 57 128 128h192c35 0 64 29 64 64v320h-64V320H64v576h640V768zM128 256h512c0-35-29-64-64-64h-64c-35 0-64-29-64-64s-29-64-64-64-64 29-64 64-29 64-64 64h-64c-35 0-64 29-64 64z" />
</svg>

After

Width:  |  Height:  |  Size: 519 B

12
static/explorer.css

@ -176,7 +176,17 @@ span.icon {
.status.warning {
color: #d7d800;
}
.navbar {
margin-bottom: 2px;
border-radius: 0;
}
}
/* Override the cursor that Bootstrap defines for readonly inputs, as it looks
* very odd on IE (and 'text' makes it clearer that it's copyable everywhere).
*/
.permalink {
cursor: text;
display: inline;
width: 100%;
}

26
static/index.html

@ -15,15 +15,15 @@
<!--<script src="ext/clipboard.min.js"></script>x-->
</head>
<body>
<div class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Compiler Explorer - <span class="language-name"></span></a>
</div>
<div class="navbar-collapse collapse">
<li class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-left">
<li><a href="#">Full link</a></li>
<li><a href="#">Short link</a></li>
<li><a href="#" id="get-link">Get link</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="if-github-enabled">
@ -57,7 +57,7 @@
</ul>
</li>
</ul>
</div>
</li>
</div>
</div>
@ -130,7 +130,23 @@
</div>
</div>
<pre class="template lang c">// Type your code here, or load an example.
<div class="urls template">
<div class="input-group">
<input type="text"
class="form-control input-sm permalink"
placeholder="Loading"
readonly size="1024">
<span class="input-group-btn">
<button class="btn btn-sm btn-default clippy" type="button"
data-clipboard-target=".popover .permalink"
title="Copy to clipboard">
<img src="clippy.svg" class="clippy" width="13px" alt="Copy to clipboard">
</button>
</span>
</div>
</div>
<pre class="template lang c">// Type your code here, or load an example.
int square(int num) {
return num * num;
}</pre>

51
static/main.js

@ -33,7 +33,8 @@ require.config({
sifter: 'ext/sifter/sifter.min',
microplugin: 'ext/microplugin/src/microplugin',
events: 'ext/eventEmitter/EventEmitter',
lzstring: 'ext/lz-string/libs/lz-string'
lzstring: 'ext/lz-string/libs/lz-string',
clipboard: 'ext/clipboard/dist/clipboard'
},
packages: [{
name: "codemirror",
@ -56,6 +57,7 @@ define(function (require) {
var compiler = require('compiler');
var editor = require('editor');
var url = require('url');
var clipboard = require('clipboard');
var Hub = require('hub');
analytics.initialise();
@ -71,8 +73,14 @@ define(function (require) {
};
var root = $("#root");
var config = url.deserialiseState(window.location.hash.substr(1));
if (config) {
// replace anything in the default config with that from the hash
config = _.extend(defaultConfig, config);
}
$(window).bind('hashchange', function () {
window.location.reload(); // punt on hash events and just reload the page
// punt on hash events and just reload the page if there's a hash
if (window.location.hash.substr(1))
window.location.reload();
});
if (!config) {
@ -81,6 +89,7 @@ define(function (require) {
config = savedState !== null ? JSON.parse(savedState) : defaultConfig;
}
console.log(config);
var layout = new GoldenLayout(config, root);
layout.on('stateChanged', function () {
var state = JSON.stringify(layout.toConfig());
@ -97,4 +106,42 @@ define(function (require) {
$(window).resize(sizeRoot);
sizeRoot();
new clipboard('.btn.clippy');
// TODO: promises?
function permalink() {
var config = layout.toConfig();
return window.location.href.split('#')[0] + '#' + url.serialiseState(config);
}
function popover() {
var elem = $(".urls.template").clone();
_.defer(function () {
$(".permalink:visible").val(permalink());
});
return elem.html();
}
var getLink = $("#get-link").popover({
container: 'body',
content: popover,
html: true,
placement: 'bottom',
trigger: 'manual'
}).click(function () {
getLink.popover('show');
});
$(document).on('keyup.editable', function (e) {
if (e.which === 27) {
getLink.popover("hide");
}
});
$(document).on('click.editable', function (e) {
var target = $(e.target);
if (!target.is(getLink) && target.closest('.popover').length === 0)
getLink.popover("hide");
});
});

32
static/url.js

@ -25,6 +25,7 @@
define(function (require) {
"use strict";
var GoldenLayout = require('goldenlayout');
var rison = require('rison');
var $ = require('jquery');
var editor = require('editor');
@ -62,8 +63,9 @@ define(function (require) {
/* falls through */
case 3:
state = convertOldState(state);
break;
break; // no fall through
case 4:
state = GoldenLayout.unminifyConfig(state);
break;
default:
return false;
@ -71,13 +73,25 @@ define(function (require) {
return state;
}
function risonify(obj) {
return rison.quote(rison.encode_object(obj));
}
function unrisonify(text) {
return rison.decode_object(decodeURIComponent(text.replace(/\+/g, '%20')));
}
function deserialiseState(stateText) {
var state;
try {
state = rison.decode_object(decodeURIComponent(stateText.replace(/\+/g, '%20')));
state = unrisonify(stateText);
if (state && state.z) {
state = unrisonify(lzstring.decompressFromBase64(state.z));
}
} catch (ignored) {
}
if (!state) {
try {
state = $.parseJSON(decodeURIComponent(stateText));
@ -88,10 +102,16 @@ define(function (require) {
}
function serialiseState(stateText) {
// convert arrays to objects
// filter out anything barring content from non-leaves
// filter out anything barring type, componentName, componentState from leaves
// compress the whole thing if savings made?
var ctx = GoldenLayout.minifyConfig({content: stateText.content});
ctx.version = 4;
var uncompressed = risonify(ctx);
var compressed = risonify({z: lzstring.compressToBase64(uncompressed)});
var MinimalSavings = 0.20; // at least this ratio smaller
if (compressed.length < uncompressed.length * (1.0 - MinimalSavings)) {
return compressed;
} else {
return uncompressed;
}
}
return {

Loading…
Cancel
Save