Embed scripts

This commit is contained in:
Nicholas Jitkoff 2018-06-10 09:41:58 -05:00
parent 936a918ec8
commit d1f51f0da3
9 changed files with 279 additions and 76 deletions

1
data.min.js vendored Normal file
View file

@ -0,0 +1 @@
var BASE64_MARKER=";base64,";var LZMA64_MARKER=";bxze64,";function compressDataURI(dataURI,callback){var base64Index=dataURI.indexOf(BASE64_MARKER);var base64=dataURI.substring(base64Index+BASE64_MARKER.length);stringToZip(base64ToByteArray(base64),function(result){callback(dataURI.substring(0,base64Index)+LZMA64_MARKER+result)})}function base64ToByteArray(base64){var raw=window.atob(base64);var rawLength=raw.length;var array=new Uint8Array(new ArrayBuffer(rawLength));for(i=0;i<rawLength;i++){array[i]=raw.charCodeAt(i)}return array}function stringToZip(string,callback){LZMA.compress(string,9,function(result,error){if(error)console.error(error);var base64String=btoa(String.fromCharCode.apply(null,new Uint8Array(result)));return callback(base64String)})}function decompressDataURI(dataURI,preamble,callback){var base64Index=dataURI.indexOf(LZMA64_MARKER);if(base64Index>0){var base64=dataURI.substring(base64Index+LZMA64_MARKER.length);zipToString(base64,function(result){stringToData(result,function(data){if(!data)return callback(undefined);callback(dataURI.substring(0,base64Index)+BASE64_MARKER+(preamble||"")+data.split(",")[1])})})}else{callback(dataURI)}}function zipToString(data,callback){var array=base64ToByteArray(data);LZMA.decompress(array,function(result,error){if(!(typeof result==="string"))result=new Uint8Array(result);if(error)console.error(error);callback(result)})}function stringToData(string,callback){if(!string.length)return callback("");var a=new FileReader;a.onload=function(e){callback(e.target.result.replace())};a.readAsDataURL(new Blob([string],{encoding:"UTF-8",type:"text/html;charset=UTF-8"}))}function dataToString(data,callback){var blob=dataURItoBlob(data);var reader=new FileReader;reader.onload=function(e){callback(reader.result)};reader.readAsText(blob)}function dataURItoBlob(dataURI){var byteString=atob(dataURI.split(",")[1]);var mimeString=dataURI.split(",")[0].split(":")[1].split(";")[0];var arrayBuffer=new ArrayBuffer(byteString.length);var _ia=new Uint8Array(arrayBuffer);for(var i=0;i<byteString.length;i++){_ia[i]=byteString.charCodeAt(i)}var dataView=new DataView(arrayBuffer);var blob=new Blob([dataView.buffer],{type:mimeString});return blob}

116
edit.css
View file

@ -12,7 +12,10 @@ h2 { font-weight:500; }
a {
color:#0070E0;
}
body:not(.edited) #placeholder {
*[contenteditable="true"]{display: inline-block;}
body.loaded:not(.edited) #placeholder {
display:block;
}
@ -32,17 +35,42 @@ body.drag #content {
}
#content, #placeholder{
width:100%;
margin:-1em; padding: 1em;
min-height:2em
}
#content {
width:100%;
outline:none;
}
#content:focus {
outline-color: #ccc;
}
#doc-title {
opacity:0.333;
outline:none;
min-width:180px;
top:0;
position:absolute;
padding:0.5em 0;
font-family:monospace;
font-weight:bold;
}
#doc-title:focus {
opacity:1.0;
border-bottom:1px solid #ccc;
}
#doc-title:empty:before {
background: transparent;
}
#doc-title:focus:empty:before {
color: rgba(0, 0, 0, 0.333);
content: 'title';
}
#content:empty:before {
content: attr(placeholder);
color: rgba(0, 0, 0, 0.2);
@ -56,8 +84,14 @@ body.drag #content {
}
#ib-info {
pointer-events: all
pointer-events: all;
}
#ib-info:hover {
pointer-events: all;
color:black;
}
/*#toolbar a#copy {
transition: transform 1s;
cursor: default;
@ -70,23 +104,28 @@ body.drag #content {
}
*/
body.edited #toolbar {
opacity:1.0;
}
#toolbar {
opacity:0.0;
position:fixed;
top:0;
#sharehint {
display:none;
position:fixed;
bottom:0;
left:0;
right:0;
padding:3px 10px 5px 30px;
text-align:right;
background-color:#f1f1f1;
border-bottom-left-radius:10em;
font-family:monospace;
font-weight:bold;
border
text-align:center;
}
@media only screen and (max-device-width: 480px) {
#twitter, #copy {
display:none;
}
#sharehint {
display:block;
}
#menu-share-hint {
display:none;
}
}
#toolbar button {
@ -99,11 +138,50 @@ body.edited #toolbar {
text-decoration: line-through;
}
#length {opacity:0.54;}
/*body.edited #toolbar {
opacity:1.0;
transform: translateY(0);
}
*/
#toolbar {
position:fixed;
top:0;
right:0;
padding:0.5em 1em;
text-align:right;
font-family:monospace;
font-weight:bold;
/*transform: translateY(-2em);*/
transition: transform 100ms ease-out;
background-color:white;
border-bottom-left-radius: 1em;
cursor:pointer;
}
#toolbar a {font-size:11px; margin-right:0.5em; cursor: pointer; text-decoration:none; color:#333;}
#menus-share-hint {
content:'hello';
}
#toolbar .disabled {
opacity:0.333;
}
#toolbar a {margin-left:0.5em; cursor: pointer; text-decoration:none; color:#333;}
#toolbar a:hover { text-decoration: underline; color:#111;}
*[contenteditable="true"]{display: inline-block;}
.menu {
width:auto;
display:none;
}
#toolbar.menu-visible .menu {
display:block;
}
#toolbar.menu-visible #menu {
opacity:0.54;
}
.menu hr {
border:none;
}

View file

@ -2,25 +2,38 @@
<html>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src https://codepen.io">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src https://codepen.io; style-src 'unsafe-inline' 'self'">
<title>itty.bitty</title>
<script src="src/lzma_worker-min.js"></script>
<script src="jquery-3.3.1.min.js"></script>
<script src="data.js"></script>
<script src="edit.js"></script>
<link rel="stylesheet" type="text/css" href="edit.css">
<body>
<div id="placeholder">
Itty bitty things<br>
can be shared within a link&mdash;<br>
type here to compose.
<p><a id="ib-info" contenteditable=false href="http://about.bitty.site" target="_blank">Learn more</a><br>
itty bitty things<br>
can be conveyed in a link.<br>
type here &ndash; and then share!<p><a id="ib-info" href="http://about.bitty.site" target="_blank">about itty bitty</a><br>
</div>
<div id="doc-title" contenteditable="true" placeholder="itty.bitty"></div>
<div id="content"> </div>
<span id="toolbar">
<a target="_blank" id="length"></a>
<a target="_blank" id="qrcode" href="https://zxing.appspot.com/generator/">QR Code</a>
<button id="copy">Copy Link</button><br>
<a target="_blank" id="length"></a>&nbsp;<a target="_blank" id="menu">menu</a>
<div id="menu-contents" class="menu">
<p><a id="copy">copy link</a><br>
----<br>
<span id="menus-share-hint" class="disabled">share via</span><br>
<a target="_blank" id="twitter" href="https://twitter.com/">twitter</a><br>
<!-- <a target="_blank" id="bitly" href="https://bitly.com/">Bitly</a><br> -->
<a target="_blank" id="qrcode" href="https://zxing.appspot.com/generator/">qr code</a><br>
----<br>
<a id="new" href="/edit">new site</a><br>
<a id="about" target="_blank" href="http://about.bitty.site" id="about">about itty</a>
</div>
</span>
</body>
</html>

90
edit.js
View file

@ -1,9 +1,11 @@
var $ = document.querySelector.bind(document)
var $$ = document.querySelectorAll.bind(document)
var QS = document.querySelector.bind(document)
var QSS = document.querySelectorAll.bind(document)
var DATA_PREFIX = 'data:text/html;base64,'
var DATA_PREFIX_8 = 'data:text/html;charset=utf-8;base64,'
var DATA_PREFIX_BAZE = 'data:text/html;charset=utf-8;baze64,'
var DATA_PREFIX_BXZE = 'data:text/html;charset=utf-8;bxze64,'
var b = document.documentElement.setAttribute('data-useragent', navigator.userAgent);
var content = undefined
window.onload = function() {
@ -15,17 +17,25 @@ window.onload = function() {
content = document.getElementById("content");
content.addEventListener('keydown', handleKey);
content.addEventListener('keyup', handleInput);
QS("#doc-title").addEventListener('keyup', handleInput);
content.addEventListener('drop', handleDrop);
content.addEventListener('paste', handlePaste)
content.contentEditable = 'true';
content.focus();
document.execCommand('selectAll',false,null);
$('#qrcode').onclick = makeQRCode
$('#copy').onclick = copyLink
QS('#qrcode').onclick = makeQRCode
QS('#twitter').onclick = copyThenLink
QS('#copy').onclick = copyLink
QS('#menu').onclick = toggleMenu
var hash = window.location.hash.substring(1)
if (hash.length) {
updateLink(hash)
if (hash.startsWith('!')) {
var slashIndex = hash.indexOf("/");
var title = hash.substring(0, slashIndex)
if (title.length) QS("#doc-title").innerText = document.title = decodeURIComponent(title.replace(/_/g, " "));
hash = hash.substring(slashIndex + 1);
updateLink(hash, title)
if (hash.startsWith('?')) {
hash = hash.substring(1)
zipToString(hash, setContent);
}
@ -46,6 +56,7 @@ function updateBodyClass() {
} else {
document.body.classList.remove("edited")
}
document.body.classList.add("loaded")
}
function handleDrop(e) {
@ -63,8 +74,8 @@ function handleDrop(e) {
console.log("Verified", url == url3,)
})
if (ratio > 0.95) url2 = url;
if (e.altKey) url2 = url2.replace(DATA_PREFIX_BAZE, "!")
updateLink(url2, true)
if (e.altKey) url2 = url2.replace(DATA_PREFIX_BXZE, "!")
updateLink(url2, file.name, true)
setFileContent('📄' + file.name)
})
}, false);
@ -77,6 +88,8 @@ function setFileContent(name) {
setContent('&nbsp;<span class="ib-file" contentEditable="false">' + name + '</span><br><br>');
}
// TODO Command+Shift+T for title (H1), Command+Shift+H for headline (H2), Command+Shift+B for body text (remove any of the above)
function handleKey(e) {
var code = e.which;
var handled = false;
@ -93,7 +106,6 @@ function handleKey(e) {
} else {
handled = false
}
} else if (e.metaKey) {
if (code == 'K'.charCodeAt(0)) {
handled = true;
@ -128,36 +140,37 @@ function fetchCodepen(url) {
stringToZip(string, function(zip) {
setFileContent('✒️' + url)
setTimeout(function() {
updateLink((useTemplate ? "," : DATA_PREFIX_BAZE) + zip)
updateLink((useTemplate ? "" : DATA_PREFIX_BXZE) + zip)
}, 300);
});
});
}
function stripPrefix(url) {
if (url) {
var dataRE = /data:(text\/html[^,]*)(;base64),(.*)/
var match = url.match(dataRE);
if (match) return "!" + match[3];
}
return url;
}
// function stripPrefix(url) {
// if (url) {
// var dataRE = /data:(text\/html[^,]*)(;base64),(.*)/
// var match = url.match(dataRE);
// if (match) return "!" + match[3];
// }
// return url;
// }
function handleInput(e) {
updateBodyClass();
var text = content.innerText
var text = content.innerText;
var title = QS("#doc-title").innerText;
var strip = false;
if (text.indexOf("</") > 0) {
text = text.replace(/[\n|\t]+/g,' ').replace(/> +</g, '> <')
} else {
var title = text.split("\n")[0]
text = content.innerHTML
strip = true
}
if (text.trim().length) {
stringToZip(text, function(zip) {
updateLink("!" + zip)
updateLink("?" + zip, title)
});
} else {
updateLink("")
@ -166,11 +179,18 @@ function handleInput(e) {
}
var maxLengths = {
"#qrcode": 2610,
// "#twitter": 4088,
// "#bitly": 2048,
"#qrcode": 2953,
}
function updateLink(url, push) {
url = "/#" + url
function updateLink(url, title, push) {
if (title) title = encodeURIComponent(title.trim().replace(/\s/g, "_"))
if (url.length) {
url = "/#" + (title || "") + "/" + url
} else {
url = "/edit"
}
var hash = location.hash
if (push || !hash || !hash.length) {
window.history.pushState(content.innerHTML, null, url);
@ -179,14 +199,14 @@ function updateLink(url, push) {
}
var length = location.href.length
$('#length').innerText = length + " bytes"
$('#length').href = url
QS('#length').innerText = length + " bytes"
QS('#length').href = url
for (var key in maxLengths) {
var maxLength = maxLengths[key]
if (length > maxLength) {
$(key).classList.add("invalid")
QS(key).classList.add("invalid")
} else {
$(key).classList.remove("invalid")
QS(key).classList.remove("invalid")
}
};
@ -207,6 +227,13 @@ function makeQRCode() {
//https://developers.google.com/chart/infographics/docs/qr_codes
}
function toggleMenu() {
QS("#toolbar").classList.toggle("menu-visible")
}
function copyThenLink() {
copyLink()
return confirm("Copied your link to the clipboard. Paste it to share.")
}
function copyLink() {
var text = location.href
var dummy = document.createElement("input");
@ -215,6 +242,11 @@ function copyLink() {
dummy.select();
document.execCommand("copy");
document.body.removeChild(dummy);
document.body.addClass("copied")
setTimeout(function() {
document.body.removeClass("copied")
}, 300);
}
function saveLink() {

54
favicon.js Normal file
View file

@ -0,0 +1,54 @@
(function() {
var FavEmoji = function(unicode) {
'use strict';
var
canvas = document.createElement('canvas'),
getContext = function(w) {
canvas.width = canvas.height = w;
context = canvas.getContext('2d');
context.font = 'normal normal normal 32px/' + w + 'px sans';
context.textBaseline = 'middle';
return context;
},
hex2char = function(hex) {
var
result = '',
n = parseInt(hex, 16);
if(n <= 0xFFFF)
result += String.fromCharCode(n);
else if(n <= 0x10FFFF) {
n -= 0x10000
result += String.fromCharCode(0xD800 | (n >> 10)) + String.fromCharCode(0xDC00 | (n & 0x3FF));
}
return result;
},
context = getContext(32),
content = unicode.replace(/[Uu]\+10([A-Fa-f0-9]{4})/g, function(str, match) {
return hex2char('10' + matches);
}).replace(/[Uu]\+([A-Fa-f0-9]{1,5})/g, function(str, match) {
return hex2char(match);
}),
iconWidth,
link = document.createElement('link');
if(!canvas.toDataURL || !document.querySelectorAll)
return;
iconWidth = context.measureText(content).width;
if(iconWidth > canvas.width)
context = getContext(iconWidth);
context.fillText(content, (canvas.width - iconWidth) / 2, canvas.height / 2);
link.setAttribute('rel', 'icon');
link.setAttribute('type', 'image/png');
link.setAttribute('href', canvas.toDataURL('image/png'));
for(var icons = document.querySelectorAll('link[rel*=icon]'), i = 0, l = icons.length; i < l; i++)
icons[i].parentNode.removeChild(icons[i]);
document.getElementsByTagName('head')[0].appendChild(link);
};
if(typeof define !== 'undefined' && define.amd)
define([], function() {
return FavEmoji;
});
else if(typeof module !== 'undefined' && module.exports)
module.exports = FavEmoji;
else
this.FavEmoji = FavEmoji;
})();

View file

@ -5,7 +5,8 @@
"firebase.json",
"**/.*",
"**/node_modules/**",
"samples/**"
"samples/**",
"**/.git/**"
],
"rewrites": [
{

File diff suppressed because one or more lines are too long

16
index.min.html Normal file
View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html xmanifest="manifest.appcache">
<title>itty bitty</title>
<meta name="viewport" content="width=device-width">
<script src="src/lzma-d-min.js"></script>
<script src="data.js"></script>
<style type="text/css">
#iframe {border:none;position:absolute;top:0;left:0;width:100%;height:100%}
#edit {font-family:monospace; color:rgba(0,0,0,0.54); position:absolute;z-index:100;position:absolute;top:10px; right:10px; display:none;}
#edit:not(:hover) {text-decoration:none;}
</style>
<iframe id="iframe"></iframe>
<a id="edit">edit</a>
<script type="text/javascript">function showEdit(t){var n=document.getElementById("edit");n.href="/edit"+location.hash,n.style.display=t?"block":"none"}var HEAD_TAGS="PG1ldGEgY2hhcnNldD0idXRmLTgiPjxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgiPjxiYXNlIHRhcmdldD0iX3RvcCI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj5ib2R5e21hcmdpbjowIGF1dG87cGFkZGluZzoxMnZtaW4gMTB2bWluO21heC13aWR0aDozNWVtO2xpbmUtaGVpZ2h0OjEuNWVtO2ZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLEJsaW5rTWFjU3lzdGVtRm9udCxzYW5zLXNlcmlmO3dvcmQtd3JhcDogYnJlYWstd29yZDt9PC9zdHlsZT4g";window.onhashchange=window.onload=function(){var t=window.location.hash.substring(1);if(t.length){var e=document.getElementById("iframe"),n=document.getElementById("edit"),d=void 0,a="?"==t.charAt(0),o=a||"!"==t.charAt(0);(o||a)&&(t=t.substring(1),d=HEAD_TAGS),0!=t.indexOf("data:")&&(t="data:text/html;charset=utf-8;"+(o?"bxze64,":"base64,")+t),n.onclick=function(){location.href="/edit"+location.hash};var i=navigator.userAgent.match(/rv:11/);decompressDataURI(t,d,function(t){t&&(i?dataToString(t,function(t){var n=e.contentWindow.document;n.open(),n.write(t),n.close()}):t&&(e.src=t))}),showEdit(a)}else location.href="/edit"}</script>
</html>

View file

@ -1,7 +1,4 @@
CACHE MANIFEST
CACHE:
/
/data.js
/favicon.ico
/src/lzma-d-min.js
/