mirror of
https://github.com/arfct/itty-bitty.git
synced 2026-03-11 08:54:33 +00:00
rename v1
This commit is contained in:
parent
19762bef52
commit
a7f5be7f1f
18 changed files with 573 additions and 33 deletions
23
docs/data.js
23
docs/data.js
|
|
@ -45,19 +45,16 @@ function decompressDataURI(dataURI, preamble, callback) {
|
|||
|
||||
function zipToString(data, callback) {
|
||||
var array = base64ToByteArray(data);
|
||||
if (array[0] == 31) { // Handle Brotli
|
||||
var script= document.createElement('script');
|
||||
script.type = "module"
|
||||
script.innerHTML = `import {BrotliDecode} from "./js/brotli/decode.js";console.log("yo");window.brotli = BrotliDecode;`;
|
||||
document.head.appendChild(script);
|
||||
setTimeout(() => {
|
||||
return callback((window.brotli(array)));
|
||||
},100);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// if (array[0] == 31) { // Handle Brotli
|
||||
// var script= document.createElement('script');
|
||||
// script.type = "module"
|
||||
// script.innerHTML = `import {BrotliDecode} from "./js/brotli/decode.js";console.log("yo");window.brotli = BrotliDecode;`;
|
||||
// document.head.appendChild(script);
|
||||
// setTimeout(() => {
|
||||
// return callback((window.brotli(array)));
|
||||
// },100);
|
||||
// return;
|
||||
// }
|
||||
|
||||
LZMA.decompress(array, function(result, error) {
|
||||
if (!(typeof result === 'string')) result = new Uint8Array(result)
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
<link id="favicon" rel=icon href=''>
|
||||
<script src="/js/lzma/lzma-d-min.js"></script>
|
||||
<script src="/data.js"></script>
|
||||
<script src="/index.js"></script>
|
||||
<script src="/render.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/index.css">
|
||||
<link rel="stylesheet" href="/render.css">
|
||||
<noscript>To use itty.bitty, please enable JavaScript.</noscript>
|
||||
<div id="toast">itty.bitty is experimental technology that renders linked content from outside sources. <a href="http://toast.bitty.site" target="_blank">Learn more</a>.
|
||||
<br><br>This content is only as trustworthy as its source, and it should be treated with the caution
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
1
docs/v1/base.css
Normal file
1
docs/v1/base.css
Normal file
|
|
@ -0,0 +1 @@
|
|||
body{margin:0 auto;padding:12vmin 10vmin;max-width:35em;line-height:1.5em;font-family: -apple-system,BlinkMacSystemFont,sans-serif;word-wrap: break-word;}
|
||||
223
docs/v1/edit.css
Normal file
223
docs/v1/edit.css
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
body {
|
||||
margin: 0 auto;
|
||||
padding: 12vh 10vmin;
|
||||
max-width: 35em;
|
||||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
line-height: 1.5em;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 400;
|
||||
}
|
||||
h2 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0070e0;
|
||||
}
|
||||
|
||||
*[contenteditable="true"] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
body.loaded:not(.edited) #placeholder {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#placeholder {
|
||||
display: none;
|
||||
font-style: italic;
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
body.drag #content {
|
||||
outline: 3px dashed #ccc;
|
||||
background-color: #fafafa;
|
||||
border-radius: 1em;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
#content,
|
||||
#placeholder {
|
||||
margin: -1em;
|
||||
padding: 1em;
|
||||
min-height: 7em;
|
||||
}
|
||||
|
||||
#content {
|
||||
width: 100%;
|
||||
outline: none;
|
||||
}
|
||||
#content:focus {
|
||||
outline-color: #ccc;
|
||||
}
|
||||
|
||||
#doc-title {
|
||||
outline: none;
|
||||
min-width: 180px;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
padding: 0.5em 0;
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
body.edited #doc-title:empty:before,
|
||||
#doc-title:focus:empty:before {
|
||||
content: "untitled";
|
||||
color: rgba(0, 0, 0, 0.333);
|
||||
}
|
||||
|
||||
#doc-title:focus {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
#doc-title:empty:before {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#content:empty:before {
|
||||
content: attr(placeholder);
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
background: transparent;
|
||||
}
|
||||
#doc-file {
|
||||
border-radius: 1em;
|
||||
background: #ebeff9;
|
||||
padding: 0.25em 1em;
|
||||
font-size: smaller;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
#doc-file:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#ib-info {
|
||||
pointer-events: all;
|
||||
}
|
||||
#ib-info:hover {
|
||||
pointer-events: all;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/*#toolbar a#copy {
|
||||
transition: transform 1s;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#copy:active {
|
||||
transform:translate(0, -0.5em);
|
||||
transition: transform 100ms;
|
||||
color:red;
|
||||
}
|
||||
*/
|
||||
|
||||
#sharehint {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
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 {
|
||||
vertical-align: baseline;
|
||||
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#toolbar a.invalid {
|
||||
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;
|
||||
}
|
||||
|
||||
#copy-message {
|
||||
background: #2d2d2d;
|
||||
color: white;
|
||||
top: 0.5em;
|
||||
right: 0.5em;
|
||||
position: absolute;
|
||||
padding: 0.5em 1em;
|
||||
z-index: 100;
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
body:not(.copied) #copy-message {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
.menu {
|
||||
width: auto;
|
||||
display: none;
|
||||
}
|
||||
#toolbar.menu-visible .menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#toolbar.menu-visible #menu {
|
||||
opacity: 0.54;
|
||||
}
|
||||
|
||||
.menu hr {
|
||||
border: none;
|
||||
}
|
||||
39
docs/v1/edit.html
Normal file
39
docs/v1/edit.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; connect-src https://codepen.io; style-src 'unsafe-inline' 'self'">
|
||||
<title>itty.bitty</title>
|
||||
<script src="js/lzma/lzma_worker-min.js"></script>
|
||||
<script src="js/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="doc-title" contenteditable="true" placeholder="itty.bitty"></div>
|
||||
<div id="doc-file"></div>
|
||||
|
||||
<div id="placeholder">
|
||||
itty bitty things<br>
|
||||
can be conveyed in a link.<br>
|
||||
type here – and then share!<p><a id="ib-info" href="http://about.bitty.site" target="_blank">about itty bitty</a><br>
|
||||
</div>
|
||||
<div id="copy-message">Link copied to clipboard.</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> <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> -->
|
||||
|
||||
----<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>
|
||||
296
docs/v1/edit.js
Normal file
296
docs/v1/edit.js
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
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_BXZE = "data:text/html;charset=utf-8;bxze64,";
|
||||
|
||||
var b = document.documentElement.setAttribute(
|
||||
"data-useragent",
|
||||
navigator.userAgent
|
||||
);
|
||||
|
||||
var importedFileData = undefined;
|
||||
|
||||
var content = undefined;
|
||||
window.onload = function() {
|
||||
window.onpopstate = function(e) {
|
||||
setContent(e.state);
|
||||
};
|
||||
window.onhashchange = function(e) {
|
||||
console.log("hash", e);
|
||||
location.reload();
|
||||
};
|
||||
document.body.onclick = function(e) {
|
||||
if (e.target == document.body) content.focus();
|
||||
};
|
||||
content = document.getElementById("content");
|
||||
content.ondragenter = function(e) {
|
||||
document.body.classList.add("drag");
|
||||
};
|
||||
content.ondragleave = function(e) {
|
||||
document.body.classList.remove("drag");
|
||||
};
|
||||
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);
|
||||
QS("#qrcode").onclick = makeQRCode;
|
||||
QS("#twitter").onclick = tweetLink;
|
||||
QS("#copy").onclick = copyLink;
|
||||
QS("#menu").onclick = toggleMenu;
|
||||
var hash = window.location.hash.substring(1);
|
||||
|
||||
if (hash.length) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
updateBodyClass();
|
||||
}
|
||||
};
|
||||
|
||||
function setContent(html) {
|
||||
content.innerHTML = html;
|
||||
updateBodyClass();
|
||||
}
|
||||
|
||||
function setFileName(name) {
|
||||
QS("#doc-file").innerText = name;
|
||||
if (name.length) {
|
||||
setContent("");
|
||||
document.body.classList.add("edited");
|
||||
}
|
||||
}
|
||||
|
||||
function updateBodyClass() {
|
||||
var length = content.innerText.length;
|
||||
if (length || importedFileData) {
|
||||
document.body.classList.add("edited");
|
||||
} else {
|
||||
document.body.classList.remove("edited");
|
||||
}
|
||||
document.body.classList.add("loaded");
|
||||
}
|
||||
|
||||
function handleDrop(e) {
|
||||
e.preventDefault();
|
||||
if (e.dataTransfer.files) {
|
||||
var file = e.dataTransfer.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.addEventListener(
|
||||
"load",
|
||||
function() {
|
||||
var url = reader.result;
|
||||
url = url.replace(DATA_PREFIX, DATA_PREFIX_8);
|
||||
compressDataURI(url, function(url2) {
|
||||
var ratio = url2.length / url.length;
|
||||
console.log("Compressed to", ratio);
|
||||
if (e.ctrlKey)
|
||||
decompressDataURI(url2, undefined, function(url3) {
|
||||
console.log("Verified", url == url3);
|
||||
});
|
||||
if (ratio > 0.95) url2 = url;
|
||||
if (e.altKey) url2 = url2.replace(DATA_PREFIX_BXZE, "!");
|
||||
|
||||
importedFileData = url2;
|
||||
updateLink(url2, file.name, true);
|
||||
setFileName("📄" + file.name);
|
||||
});
|
||||
},
|
||||
false
|
||||
);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
document.body.classList.remove("drag");
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (e.metaKey && e.altKey) {
|
||||
handled = true;
|
||||
if (code == "1".charCodeAt(0)) {
|
||||
document.execCommand("formatBlock", true, "<h1>");
|
||||
} else if (code == "2".charCodeAt(0)) {
|
||||
document.execCommand("formatBlock", true, "<h2>");
|
||||
} else if (code == 220) {
|
||||
// \
|
||||
document.execCommand("removeFormat");
|
||||
} else if (code == "0".charCodeAt(0)) {
|
||||
document.execCommand("formatBlock", true, "");
|
||||
} else {
|
||||
handled = false;
|
||||
}
|
||||
} else if (e.metaKey) {
|
||||
if (code == "K".charCodeAt(0)) {
|
||||
handled = true;
|
||||
var url = prompt("Add a link", "");
|
||||
if (url) {
|
||||
document.execCommand("createLink", true, url);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (handled) e.preventDefault();
|
||||
}
|
||||
|
||||
var codepenRE = /(https:\/\/codepen\.io\/[\w]+\/(\w+)\/(\w+))/;
|
||||
function handlePaste(e) {
|
||||
var clipboard = window.clipboardData || e.clipboardData;
|
||||
var text = clipboard.getData("Text") || clipboard.getData("text/plain");
|
||||
if ((match = text.match(codepenRE))) {
|
||||
fetchCodepen(match[0]);
|
||||
}
|
||||
}
|
||||
|
||||
var TEMPLATE_MARKER = "/*use-itty-bitty-template*/";
|
||||
function fetchCodepen(url) {
|
||||
var h, c, j;
|
||||
$.when(
|
||||
$.get({ url: url + ".html", cache: false }, function(html) {
|
||||
h = html;
|
||||
}),
|
||||
$.get({ url: url + ".css", cache: false }, function(css) {
|
||||
c = css;
|
||||
}),
|
||||
$.get({ url: url + ".js", cache: false }, function(js) {
|
||||
j = js;
|
||||
})
|
||||
).then(function() {
|
||||
var useTemplate = c.indexOf(TEMPLATE_MARKER) >= 0;
|
||||
var string =
|
||||
'<style type="text/css">' +
|
||||
c +
|
||||
"</style>" +
|
||||
h +
|
||||
'<script type="text/javascript">' +
|
||||
j +
|
||||
"</script>";
|
||||
stringToZip(string, function(zip) {
|
||||
setFileName("✒️" + url);
|
||||
var title = QS("#doc-title").innerText;
|
||||
setTimeout(function() {
|
||||
var data = (useTemplate ? "" : DATA_PREFIX_BXZE) + zip;
|
||||
importedFileData = data;
|
||||
updateLink(data, title);
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleInput(e) {
|
||||
updateBodyClass();
|
||||
var text = content.innerText;
|
||||
var title = QS("#doc-title").innerText;
|
||||
|
||||
var rawHTML = text.indexOf("</") > 0;
|
||||
if (rawHTML) {
|
||||
text = text.replace(/[ |\t]+/g, " ").replace(/> +</g, "> <");
|
||||
} else {
|
||||
text = content.innerHTML;
|
||||
}
|
||||
|
||||
if (text.trim().length) {
|
||||
stringToZip(text, function(zip) {
|
||||
if (rawHTML) {
|
||||
updateLink(DATA_PREFIX_BXZE + zip, title);
|
||||
} else {
|
||||
updateLink("?" + zip, title);
|
||||
}
|
||||
});
|
||||
setFileName("");
|
||||
} else if (importedFileData) {
|
||||
updateLink(importedFileData, title);
|
||||
} else {
|
||||
updateLink("");
|
||||
}
|
||||
}
|
||||
|
||||
var maxLengths = {
|
||||
// "#twitter": 4088,
|
||||
// "#bitly": 2048,
|
||||
"#qrcode": 2953
|
||||
};
|
||||
|
||||
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);
|
||||
} else {
|
||||
window.history.replaceState(content.innerHTML, null, url);
|
||||
}
|
||||
var length = location.href.length;
|
||||
|
||||
QS("#length").innerText = length + " bytes";
|
||||
QS("#length").href = url;
|
||||
for (var key in maxLengths) {
|
||||
var maxLength = maxLengths[key];
|
||||
if (length > maxLength) {
|
||||
QS(key).classList.add("invalid");
|
||||
} else {
|
||||
QS(key).classList.remove("invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeQRCode() {
|
||||
var url =
|
||||
"https://zxing.org/w/chart?cht=qr&chs=548x548&chld=L|1&choe=UTF-8&chl=" +
|
||||
encodeURIComponent(location.href);
|
||||
this.href = url;
|
||||
}
|
||||
|
||||
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");
|
||||
document.body.appendChild(dummy);
|
||||
dummy.value = text;
|
||||
dummy.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(dummy);
|
||||
|
||||
document.body.classList.add("copied");
|
||||
setTimeout(function() {
|
||||
document.body.classList.remove("copied");
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function saveLink() {
|
||||
var url = "/" + location.hash;
|
||||
window.history.pushState(null, null, url);
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function tweetLink() {
|
||||
var url =
|
||||
"https://twitter.com/intent/tweet?url=" + encodeURIComponent(location.href);
|
||||
window.open(url, "_blank");
|
||||
return false;
|
||||
}
|
||||
BIN
docs/v1/favicon.ico
Normal file
BIN
docs/v1/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
2
docs/v1/manifest.appcache
Normal file
2
docs/v1/manifest.appcache
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CACHE MANIFEST
|
||||
# v27
|
||||
Loading…
Reference in a new issue