mirror of
https://github.com/arfct/itty-bitty.git
synced 2026-03-11 08:54:33 +00:00
split out format bar, add preview
This commit is contained in:
parent
0cc414e307
commit
cff86a16e1
4 changed files with 199 additions and 186 deletions
170
docs/bitty.js
170
docs/bitty.js
|
|
@ -108,10 +108,8 @@ class DataURL {
|
|||
return this;
|
||||
}
|
||||
|
||||
compress = async (format = LZMA_MARKER) => {
|
||||
console.log("data", this.data.length, {data:this.data})
|
||||
let rawData = await base64ToByteArray(this.data);
|
||||
|
||||
compress = async (format = GZIP_MARKER) => {
|
||||
let rawData = this.encoding ? await base64ToByteArray(this.data) : stringToByteArray(this.data);
|
||||
let compressedData = await compressData(rawData, format);
|
||||
var base64String = dataToBase64(compressedData);
|
||||
this.data = base64String;
|
||||
|
|
@ -227,36 +225,16 @@ function infoForDataURL(url) {
|
|||
|
||||
var BASE64_MARKER = 'base64';
|
||||
var LZMA64_MARKER = 'bxze64';
|
||||
var GZIP64_MARKER = 'gzip64';
|
||||
var BROT64_MARKER = 'brot64';
|
||||
|
||||
var BASE_MARKER = 'bs';
|
||||
var LZMA_MARKER = 'xz';
|
||||
var GZIP_MARKER = 'gz';
|
||||
var BROT_MARKER = 'br';
|
||||
|
||||
function compressDataURL(dataURL, callback) {
|
||||
var base64Index = dataURL.indexOf(BASE64_MARKER);
|
||||
var base64 = dataURL.substring(base64Index + BASE64_MARKER.length + 1);
|
||||
compressString(base64ToByteArray(base64), LZMA64_MARKER, function(result) {
|
||||
callback(dataURL.substring(0, base64Index) + LZMA64_MARKER + "," + result)
|
||||
})
|
||||
}
|
||||
|
||||
function base64ToByteArray(base64) {
|
||||
return Uint8Array.from(atob(base64), c => c.charCodeAt(0));
|
||||
}
|
||||
|
||||
// function base64ToByteArray(base64) {
|
||||
// var raw = window.atob(base64);
|
||||
// var rawLength = raw.length;
|
||||
// var array = new Uint8Array(new ArrayBuffer(rawLength));
|
||||
// for(let i = 0; i < rawLength; i++) {
|
||||
// array[i] = raw.charCodeAt(i);
|
||||
// }
|
||||
// return array;
|
||||
// }
|
||||
|
||||
function loadScript(src, callback) {
|
||||
let script = el("script", { src });
|
||||
script.addEventListener('load', function(e) {
|
||||
|
|
@ -273,42 +251,30 @@ function escapeStringForIMessage(str) {
|
|||
return str;
|
||||
}
|
||||
|
||||
function decryptBase64(cipher, base64, callback) {
|
||||
if (!cipher) return callback(base64);
|
||||
// function decompressDataURL(dataURL, preamble, callback) {
|
||||
// let info = infoForDataURL(dataURL);
|
||||
|
||||
loadScript("/js/crypto-js.min.js", () => {
|
||||
let pass = prompt("This page is encrypted. What's the passcode?");
|
||||
if (!pass) return callback(base64);
|
||||
|
||||
let decrypted = CryptoJS[cipher.toUpperCase()].decrypt(base64, pass);
|
||||
return callback(CryptoJS.enc.Base64.stringify(decrypted));
|
||||
})
|
||||
}
|
||||
// let encoding = info.encoding;
|
||||
// let encodingIndex = dataURL.indexOf(encoding);
|
||||
|
||||
function decompressDataURL(dataURL, preamble, callback) {
|
||||
let info = infoForDataURL(dataURL);
|
||||
// if (encoding && encoding != "base64") {
|
||||
// var base64 = dataURL.substring(encodingIndex + LZMA64_MARKER.length + 1);
|
||||
// base64 = base64.replace("=",""); // TODO: apply this elsewhere;
|
||||
|
||||
let encoding = info.encoding;
|
||||
let encodingIndex = dataURL.indexOf(encoding);
|
||||
|
||||
if (encoding && encoding != "base64") {
|
||||
var base64 = dataURL.substring(encodingIndex + LZMA64_MARKER.length + 1);
|
||||
base64 = base64.replace("=",""); // TODO: apply this elsewhere;
|
||||
|
||||
decryptBase64(info.params?.cipher, base64, (base64) => {
|
||||
let bytes = base64ToByteArray(base64);
|
||||
decompressString(bytes, encoding, function(string) {
|
||||
stringToData(string, function(data) {
|
||||
if (!data) return callback();
|
||||
callback(dataURL.substring(0, encodingIndex) + BASE64_MARKER + "," + (preamble || '') + data.split(',')[1], string)
|
||||
})
|
||||
})
|
||||
})
|
||||
// decryptBase64(info.params?.cipher, base64, (base64) => {
|
||||
// let bytes = base64ToByteArray(base64);
|
||||
// decompressString(bytes, encoding, function(string) {
|
||||
// stringToData(string, function(data) {
|
||||
// if (!data) return callback();
|
||||
// callback(dataURL.substring(0, encodingIndex) + BASE64_MARKER + "," + (preamble || '') + data.split(',')[1], string)
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
|
||||
} else {
|
||||
callback(dataURL)
|
||||
}
|
||||
}
|
||||
// } else {
|
||||
// callback(dataURL)
|
||||
// }
|
||||
// }
|
||||
|
||||
async function hashString(string, base = 36) {
|
||||
const arrayBuffer = await(new TextEncoder().encode(string))
|
||||
|
|
@ -328,48 +294,48 @@ async function hashString(string, base = 36) {
|
|||
return hashAsBase64;
|
||||
}
|
||||
|
||||
function compressString(string, encoding = LZMA64_MARKER, callback) {
|
||||
if (encoding == LZMA64_MARKER) {
|
||||
loadScript("/js/lzma/lzma_worker-min.js", () => {
|
||||
LZMA.compress(string, 9, function(result, error) {
|
||||
if (error) console.error(error);
|
||||
var base64String = window.btoa(String.fromCharCode.apply(null, new Uint8Array(result)));
|
||||
return callback(base64String);
|
||||
});
|
||||
})
|
||||
} else if (encoding == BROT64_MARKER) {
|
||||
// import("/js/brotli/decode.js").then((module) => {
|
||||
// console.log("module", module)
|
||||
// return callback(module.BrotliDecode(data));
|
||||
// });
|
||||
} else if (encoding == GZIP64_MARKER) {
|
||||
import("/js/gzip/pako.js").then((module) => {
|
||||
let result = pako.deflate(string, {level:"9"});
|
||||
var base64String = window.btoa(String.fromCharCode.apply(null, new Uint8Array(result)));
|
||||
return callback(base64String);
|
||||
});
|
||||
}
|
||||
}
|
||||
// function compressString(string, encoding = LZMA64_MARKER, callback) {
|
||||
// if (encoding == LZMA64_MARKER) {
|
||||
// loadScript("/js/lzma/lzma_worker-min.js", () => {
|
||||
// LZMA.compress(string, 9, function(result, error) {
|
||||
// if (error) console.error(error);
|
||||
// var base64String = window.btoa(String.fromCharCode.apply(null, new Uint8Array(result)));
|
||||
// return callback(base64String);
|
||||
// });
|
||||
// })
|
||||
// } else if (encoding == BROT64_MARKER) {
|
||||
// // import("/js/brotli/decode.js").then((module) => {
|
||||
// // console.log("module", module)
|
||||
// // return callback(module.BrotliDecode(data));
|
||||
// // });
|
||||
// } else if (encoding == GZIP64_MARKER) {
|
||||
// import("/js/gzip/pako.js").then((module) => {
|
||||
// let result = pako.deflate(string, {level:"9"});
|
||||
// var base64String = window.btoa(String.fromCharCode.apply(null, new Uint8Array(result)));
|
||||
// return callback(base64String);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
function decompressString(data, encoding, callback) {
|
||||
if (encoding == LZMA64_MARKER) {
|
||||
LZMA.decompress(data, function(result, error) {
|
||||
if (!(typeof result === 'string')) result = new Uint8Array(result)
|
||||
if (error) console.error(error);
|
||||
callback(result);
|
||||
});
|
||||
} else if (encoding == BROT64_MARKER) {
|
||||
import("/js/brotli/decode.js").then((module) => {
|
||||
console.log("module", module)
|
||||
return callback(module.BrotliDecode(data));
|
||||
});
|
||||
} else if (encoding == GZIP64_MARKER) {
|
||||
import("/js/gzip/pako.js").then((module) => {
|
||||
let byteArray = pako.inflate(data);
|
||||
return callback(byteArray);
|
||||
});
|
||||
}
|
||||
}
|
||||
// function decompressString(data, encoding, callback) {
|
||||
// if (encoding == LZMA64_MARKER) {
|
||||
// LZMA.decompress(data, function(result, error) {
|
||||
// if (!(typeof result === 'string')) result = new Uint8Array(result)
|
||||
// if (error) console.error(error);
|
||||
// callback(result);
|
||||
// });
|
||||
// } else if (encoding == BROT64_MARKER) {
|
||||
// import("/js/brotli/decode.js").then((module) => {
|
||||
// console.log("module", module)
|
||||
// return callback(module.BrotliDecode(data));
|
||||
// });
|
||||
// } else if (encoding == GZIP64_MARKER) {
|
||||
// import("/js/gzip/pako.js").then((module) => {
|
||||
// let byteArray = pako.inflate(data);
|
||||
// return callback(byteArray);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// echo -n 'hello world' | brotli | base64
|
||||
|
|
@ -488,10 +454,10 @@ export {
|
|||
infoForDataURL,
|
||||
stringToData,
|
||||
dataToString,
|
||||
compressString,
|
||||
decompressString,
|
||||
compressDataURL,
|
||||
decompressDataURL,
|
||||
// compressString,
|
||||
// decompressString,
|
||||
// compressDataURL,
|
||||
// decompressDataURL,
|
||||
hashString,
|
||||
encodePrettyComponent,
|
||||
decodePrettyComponent,
|
||||
|
|
@ -500,8 +466,6 @@ export {
|
|||
parseBittyURL,
|
||||
BASE64_MARKER,
|
||||
LZMA64_MARKER,
|
||||
GZIP64_MARKER,
|
||||
BROT64_MARKER,
|
||||
BASE_MARKER,
|
||||
LZMA_MARKER,
|
||||
GZIP_MARKER,
|
||||
|
|
|
|||
|
|
@ -25,16 +25,37 @@ html {
|
|||
}
|
||||
|
||||
body {
|
||||
margin: 0 auto;
|
||||
padding: 10rem 6vmin 4vmin 6vmin;
|
||||
max-width: 45em;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
line-height: 1.5em;
|
||||
min-height:100vh;
|
||||
display:
|
||||
flex;
|
||||
flex-direction: row-reverse;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
margin: 0 auto;
|
||||
padding: 5rem 6vmin 4vmin 6vmin;
|
||||
max-width: 45em;
|
||||
/* background-color:#0070e0; */
|
||||
box-sizing:
|
||||
border-box;
|
||||
}
|
||||
|
||||
body:not(.preview) #preview-frame {
|
||||
display:none;
|
||||
}
|
||||
#preview-frame {
|
||||
background-color:#fafafa;
|
||||
border:0;
|
||||
/* position:absolute; */
|
||||
right:0;
|
||||
width:50%;
|
||||
bottom:0;
|
||||
height:100vh;
|
||||
background: repeating-conic-gradient(rgba(128,128,128,.10) 0% 25%, transparent 0% 50%) 50% / 4px 4px;
|
||||
}
|
||||
h1 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
|
@ -88,7 +109,7 @@ body.drag #content {
|
|||
outline: none;
|
||||
/* min-width: 180px; */
|
||||
top: 0;
|
||||
position: absolute;
|
||||
/* position: absolute; */
|
||||
padding: 0 1em;
|
||||
font-weight: normal;
|
||||
opacity:0.33;
|
||||
|
|
@ -98,8 +119,9 @@ body.drag #content {
|
|||
margin-left: -1em;
|
||||
line-height: 2.5em;
|
||||
display: inline-block;
|
||||
/* margin-top: -31em; */
|
||||
/* margin-top: -2.5em; */
|
||||
z-index: 100;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#doc-title.open {
|
||||
|
|
@ -193,7 +215,7 @@ input:focus {
|
|||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
width: 50vw;
|
||||
height: 100vh;
|
||||
background-position: center 60px;
|
||||
box-sizing: border-box;
|
||||
|
|
@ -290,7 +312,7 @@ input:focus {
|
|||
padding:0;
|
||||
border:
|
||||
none;
|
||||
background-color:var(--background-color);
|
||||
/* background-color:var(--background-color); */
|
||||
display:
|
||||
flex;
|
||||
align-items: left;
|
||||
|
|
@ -299,6 +321,7 @@ input:focus {
|
|||
flex-wrap: wrap-reverse;
|
||||
/* height: 10rem; */
|
||||
padding-left: 4vmin;
|
||||
z-index:1000;
|
||||
}
|
||||
#menubar > span {
|
||||
display: flex;
|
||||
|
|
@ -529,8 +552,8 @@ label:first-child {
|
|||
cursor:default;
|
||||
}
|
||||
|
||||
#menubar.ql-snow.ql-toolbar button,
|
||||
#menubar.ql-snow.ql-toolbar .ql-picker {
|
||||
#formatbar.ql-snow.ql-toolbar button,
|
||||
#formatbar.ql-snow.ql-toolbar .ql-picker {
|
||||
height: 40px;
|
||||
min-width: 40px;
|
||||
float: none;
|
||||
|
|
@ -538,8 +561,8 @@ label:first-child {
|
|||
text-align: revert;
|
||||
width: 40px;
|
||||
}
|
||||
#menubar.ql-snow.ql-toolbar button,
|
||||
#menubar.ql-snow.ql-toolbar .ql-picker .ql-picker-label {
|
||||
#formatbar.ql-snow.ql-toolbar button,
|
||||
#formatbar.ql-snow.ql-toolbar .ql-picker .ql-picker-label {
|
||||
/* background-size: 24px; */
|
||||
padding: 10px;
|
||||
}
|
||||
|
|
@ -554,7 +577,7 @@ div#editor.ql-container.ql-snow {
|
|||
height: 1.5rem;
|
||||
}
|
||||
|
||||
#menubar.ql-snow .ql-color-picker .ql-picker-options {
|
||||
#formatbar.ql-snow .ql-color-picker .ql-picker-options {
|
||||
width: 11.2rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
|
@ -569,10 +592,10 @@ div#editor.ql-container.ql-snow {
|
|||
}
|
||||
|
||||
|
||||
#menubar .ql-toolbar,
|
||||
#menubar .ql-stroke,
|
||||
#menubar .ql-picker,
|
||||
#menubar.ql-snow a {
|
||||
#formatbar .ql-toolbar,
|
||||
#formatbar .ql-stroke,
|
||||
#formatbar .ql-picker,
|
||||
#formatbar.ql-snow a {
|
||||
color: var(--text-color) ;
|
||||
stroke: var(--text-color) ;
|
||||
}
|
||||
|
|
@ -604,9 +627,9 @@ label:not(:first-child) {
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
.ql-formats {
|
||||
opacity:0.0;
|
||||
}
|
||||
#formatbar .ql-formats {
|
||||
opacity:1.0;
|
||||
margin-right:0;display: contents;}
|
||||
|
||||
body:not(.dragging) #drop-zone {
|
||||
display:none;
|
||||
|
|
@ -625,4 +648,29 @@ body:not(.dragging) #drop-zone {
|
|||
font-family: sans-serif;
|
||||
color: white;
|
||||
line-height: 100vh;
|
||||
opacity:0.2;
|
||||
opacity:0.2;
|
||||
}
|
||||
|
||||
#formatbar {
|
||||
margin-top:-8em;
|
||||
border:
|
||||
none;
|
||||
/* border-bottom:1px solid
|
||||
var(--divider-color); */
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
background-color: var(--background-color);
|
||||
padding: 0;
|
||||
margin: 0 -12px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
opacity:0.25;
|
||||
}
|
||||
#formatbar:hover {
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
body.filecontent #formatbar {
|
||||
display:none;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src data: 'self'; script-src 'self'; connect-src https://codepen.io; font-src https://fonts.gstatic.com; style-src https://fonts.googleapis.com 'unsafe-inline' 'self'">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src data: 'self'; script-src cdnjs.cloudflare.com cdn.quilljs.com 'self'; connect-src https://codepen.io; font-src https://fonts.gstatic.com; style-src https://fonts.googleapis.com cdnjs.cloudflare.com cdn.quilljs.com 'unsafe-inline' 'self'">
|
||||
<meta id="themeColor" name="theme-color" content="#f1f1f1" media="(prefers-color-scheme: light)">
|
||||
<meta id="themeColorDark" name="theme-color" content="#121212" media="(prefers-color-scheme: dark)">
|
||||
<link rel="canonical" id="canonical" href="/edit">
|
||||
|
|
@ -22,62 +22,70 @@
|
|||
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined">
|
||||
|
||||
<body>
|
||||
<iframe id="preview-frame"></iframe>
|
||||
<div class="editor-container">
|
||||
<div id="doc-file"></div>
|
||||
<input id="file-input" type="file" name="name" style="display: none;" />
|
||||
<div id="drop-zone">DROP HERE</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="drop-zone"></div>
|
||||
|
||||
<div id="copy-message">Link copied to clipboard.</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></div>
|
||||
<div id="doc-title" class="toolbarbutton" placeholder="untitled">
|
||||
<div class="title" id="doc-title-text">untitled</div>
|
||||
<form id="md-contents" class="menu">
|
||||
<div class="inputrow"><label for="md-title">title</label><input type="text" name="title" id="md-title" placeholder="untitled"></div>
|
||||
<div class="inputrow"><label for="md-include">metadata</label><input type="checkbox" name="includeMetadata" id="md-include" placeholder="untitled"><label for="md-include">include social metadata</label></div>
|
||||
<div class="inputrow"><label for="md-description">description</label><input type="text" name="description" id="md-description" placeholder="text"></div>
|
||||
<div class="inputrow"><label for="md-favicon">favicon</label><input type="text" name="favicon" id="md-favicon" placeholder="emoji or url"></div>
|
||||
<div class="inputrow"><label for="md-image">image</label><input type="text" name="image" id="md-image" placeholder="image url"></div>
|
||||
<div class="inputrow"><label for="md-password">password</label><input type="text" name="password" id="md-password" placeholder="encryption password"></div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="editor"></div>
|
||||
|
||||
<div class="toolbar" id="menubar">
|
||||
<!-- <div class="spacer"></div> -->
|
||||
|
||||
|
||||
<div class="toolbar hide-before-edit" id="formatbar">
|
||||
<span class="ql-formats">
|
||||
<button class="ql-bold"></button>
|
||||
<button class="ql-italic"></button>
|
||||
<button class="ql-underline"></button>
|
||||
<select class="ql-header" id="ql-header">HX</select>
|
||||
</span>
|
||||
<span class="ql-formats">
|
||||
<select class="ql-color"><option value="#F6D4D2"/><option value="#FAE4D3"/><option value="#FEF3D5"/><option value="#CFE8DC"/><option value="#CFE0E8"/><option value="#E1D7E8"/><option value="white"/><option value="#E99590"/><option value="#F3BB92"/><option value="#FDE095"/><option value="#86C6A8"/><option value="#86B1C6"/><option value="#B39BC6"/><option value="#A4A4A4"/><option value="#D42A20"/><option value="#E77625"/><option value="#FAC22B"/><option value="#0E8E51"/><option value="#0E638E"/><option value="#67378D"/><option value="#727272"/><option value="#BF0000"/><option value="#DB3F00"/><option value="#F8A600"/><option value="#005E12"/><option value="#00275E"/><option value="#2C005C"/><option value="#3D3D3D"/><option value="#860000"/><option value="#943E00"/><option value="#AE7400"/><option value="#00420D"/><option value="#001B42"/><option value="#1F0040"/><option value="black"/></select>
|
||||
<select class="ql-background"><option value="#F6D4D2"/><option value="#FAE4D3"/><option value="#FEF3D5"/><option value="#CFE8DC"/><option value="#CFE0E8"/><option value="#E1D7E8"/><option value="white"/><option value="#E99590"/><option value="#F3BB92"/><option value="#FDE095"/><option value="#86C6A8"/><option value="#86B1C6"/><option value="#B39BC6"/><option value="#A4A4A4"/><option value="#D42A20"/><option value="#E77625"/><option value="#FAC22B"/><option value="#0E8E51"/><option value="#0E638E"/><option value="#67378D"/><option value="#727272"/><option value="#BF0000"/><option value="#DB3F00"/><option value="#F8A600"/><option value="#005E12"/><option value="#00275E"/><option value="#2C005C"/><option value="#3D3D3D"/><option value="#860000"/><option value="#943E00"/><option value="#AE7400"/><option value="#00420D"/><option value="#001B42"/><option value="#1F0040"/><option value="black"/></select>
|
||||
<button class="ql-clean"></button>
|
||||
</span>
|
||||
<span class="ql-formats">
|
||||
<select class="ql-align"></select>
|
||||
<button class="ql-blockquote"></button>
|
||||
<button class="ql-code-block"></button>
|
||||
</span>
|
||||
<span class="ql-formats">
|
||||
<button class="ql-clean"></button>
|
||||
<button class="ql-link"></button>
|
||||
</span>
|
||||
<span class="ql-formats">
|
||||
<button type="button" class="ql-list" value="bullet"></button>
|
||||
<button type="button" class="ql-list" value="ordered"></button>
|
||||
</span>
|
||||
<span class="ql-formats">
|
||||
<button class="ql-indent" value="-1"></button>
|
||||
<button class="ql-indent" value="+1"></button>
|
||||
</span>
|
||||
</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></div>
|
||||
|
||||
<div id="doc-title" class="toolbarbutton hide-before-edit" placeholder="untitled">
|
||||
<div class="title" id="doc-title-text">untitled</div>
|
||||
<form id="md-contents" class="menu">
|
||||
<div class="inputrow"><label for="md-title">title</label><input type="text" name="title" id="md-title" placeholder="untitled"></div>
|
||||
<div class="inputrow"><label for="md-include">metadata</label><input type="checkbox" name="includeMetadata" id="md-include" placeholder="untitled"><label for="md-include">include social metadata</label></div>
|
||||
<div class="inputrow"><label for="md-description">description</label><input type="text" name="description" id="md-description" placeholder="text"></div>
|
||||
<div class="inputrow"><label for="md-favicon">favicon</label><input type="text" name="favicon" id="md-favicon" placeholder="emoji or url"></div>
|
||||
<div class="inputrow"><label for="md-image">image</label><input type="text" name="image" id="md-image" placeholder="image url"></div>
|
||||
<div class="inputrow"><label for="md-password">password</label><input type="text" name="password" id="md-password" placeholder="encryption password"></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="editor"></div>
|
||||
|
||||
<div class="toolbar" id="menubar">
|
||||
<!-- <div class="spacer"></div> -->
|
||||
<div class="toolbar-right">
|
||||
<div id="length" class="hide-before-edit"></div>
|
||||
<div id="share" class="hide-before-edit menu-item">share</div>
|
||||
<div id="mainmenu">
|
||||
<div class="menu-item">menu</div>
|
||||
<div id="menu-contents" class="menu">
|
||||
<a id="preview">show preview</a>
|
||||
<a id="copy">copy link</a>
|
||||
<hr>
|
||||
<span id="menus-share-hint" class="disabled">share via</span><br>
|
||||
|
|
@ -92,12 +100,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="toolbar" id="formatbar">
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
66
docs/edit.js
66
docs/edit.js
|
|
@ -22,7 +22,7 @@ var quill = new Quill('#editor', {
|
|||
modules: {
|
||||
syntax: true,
|
||||
keyboard: { bindings },
|
||||
toolbar: "#menubar"
|
||||
toolbar: "#formatbar"
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -69,14 +69,14 @@ window.onload = function() {
|
|||
}
|
||||
});
|
||||
|
||||
content.addEventListener("keydown", handleKey);
|
||||
content.addEventListener("keyup", handleInput);
|
||||
// content.addEventListener("keydown", handleKey);
|
||||
// content.addEventListener("keyup", handleInput);
|
||||
QS("#doc-title").addEventListener("keyup", handleInput);
|
||||
Array.from(document.getElementsByTagName("input")).forEach(i => i.addEventListener("keydown", handleInput))
|
||||
|
||||
document.getElementById("drop-zone").addEventListener("drop", handleDrop);
|
||||
document.getElementById("drop-zone").addEventListener("dragover", e => e.preventDefault());
|
||||
content.addEventListener("paste", handlePaste);
|
||||
editor.addEventListener("paste", handlePaste);
|
||||
// content.contentEditable = "true";
|
||||
editor.focus();
|
||||
// document.execCommand("selectAll", false, null);
|
||||
|
|
@ -86,9 +86,13 @@ window.onload = function() {
|
|||
if (!navigator.share) QS("#share").style.display = "none"
|
||||
QS("#twitter").onclick = tweetLink;
|
||||
QS("#copy").onclick = copyLink;
|
||||
QS("#preview").onclick = togglePreview;
|
||||
QS("#mainmenu").onclick = () => { toggleMenu(QS("#mainmenu"))};
|
||||
|
||||
QS("#doc-title").onclick = toggleMetadata;
|
||||
QS("#doc-title").onclick = toggleMetadata;
|
||||
|
||||
|
||||
var hash = window.location.hash.substring(1);
|
||||
|
||||
if (hash.length) {
|
||||
|
|
@ -110,7 +114,7 @@ window.onload = function() {
|
|||
};
|
||||
|
||||
function setContent(html) {
|
||||
content.innerHTML = html;
|
||||
editor.innerHTML = html;
|
||||
updateBodyClass();
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +132,10 @@ function updateBodyClass(hasContent) {
|
|||
} else {
|
||||
document.body.classList.remove("edited");
|
||||
}
|
||||
|
||||
console.log("importedFileData",importedFileData != undefined)
|
||||
document.body.classList.toggle("filecontent", importedFileData != undefined);
|
||||
|
||||
document.body.classList.add("loaded");
|
||||
}
|
||||
|
||||
|
|
@ -148,23 +156,9 @@ async function handleDrop(e) {
|
|||
|
||||
if (ratio <= 0.95) url = durl.href;
|
||||
importedFileData = url;
|
||||
updateLink(url, file.name, true);
|
||||
updateLink(url, {title:file.name}, true);
|
||||
setFileName(file.name);
|
||||
|
||||
// url = url.replace(DATA_PREFIX, DATA_PREFIX_8);
|
||||
// bitty.compressDataURL(url, function(url2) {
|
||||
// var ratio = url2.length / url.length;
|
||||
// console.log("Compressed to", Math.round(ratio * 100) + "%", url2, url);
|
||||
// if (e.ctrlKey)
|
||||
// bitty.decompressDataURL(url2, undefined, function(url3) {
|
||||
// console.log("Verified", url == url3);
|
||||
// });
|
||||
// if (e.altKey) url2 = url2.replace(DATA_PREFIX_BXZE, "!");
|
||||
|
||||
// importedFileData = durl.href;
|
||||
// updateLink(url2, file.name, true);
|
||||
// setFileName(file.name);
|
||||
// });
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
@ -264,42 +258,40 @@ function getMetadata() {
|
|||
return object;
|
||||
}
|
||||
|
||||
function handleContentChange() {
|
||||
async function handleContentChange() {
|
||||
|
||||
var text = editor.innerText;
|
||||
let hasContent = text.trim().length > 0;
|
||||
|
||||
updateBodyClass(hasContent);
|
||||
|
||||
if (!hasContent) return;
|
||||
|
||||
var metadata = getMetadata();
|
||||
|
||||
var rawHTML = text.indexOf("</") > 0;
|
||||
if (rawHTML) {
|
||||
text = text.replace(/[ |\t]+/g, " ").replace(/> +</g, "> <");
|
||||
} else {
|
||||
text = content.innerHTML;
|
||||
text = editor.innerHTML;
|
||||
}
|
||||
|
||||
|
||||
if (text.trim().length) {
|
||||
const t0 = performance.now();
|
||||
bitty.compressString(text, bitty.GZIP64_MARKER, function(zip) {
|
||||
const t1 = performance.now();
|
||||
let durl = new bitty.DataURL(`data:text/html;charset=utf-8,${text}`)
|
||||
durl = await durl.compress(bitty.GZIP_MARKER);
|
||||
console.log("data", durl)
|
||||
// bitty.compressString(text, bitty.GZIP64_MARKER, function(zip) {
|
||||
// bitty.compressString(text, bitty.LZMA64_MARKER, function(zip2) {
|
||||
// const t2 = performance.now();
|
||||
// console.debug("gz", Math.round(zip.length/text.length*100) + "%", Math.round((t1-t0)),"ms");
|
||||
// console.debug("lz", Math.round(zip2.length/text.length*100) + "%", Math.round((t2-t1)), "ms");
|
||||
// });
|
||||
zip.replace("=","")
|
||||
// zip.replace("=","")
|
||||
|
||||
if (rawHTML) {
|
||||
updateLink(DATA_PREFIX_GZIP + zip, metadata);
|
||||
updateLink(durl.href, metadata);
|
||||
} else {
|
||||
updateLink("?" + zip, metadata);
|
||||
updateLink("?" + durl.href, metadata);
|
||||
}
|
||||
});
|
||||
// });
|
||||
setFileName("");
|
||||
} else if (importedFileData) {
|
||||
updateLink(importedFileData, {title});
|
||||
|
|
@ -336,9 +328,9 @@ function updateLink(url, metadata, push) {
|
|||
bittyLink = new URL(url, document.location).href;
|
||||
|
||||
document.getElementById("canonical").href = bittyLink;
|
||||
|
||||
debugger
|
||||
console.log({bittyLink});
|
||||
|
||||
if(previewContent) QS("#preview-frame").src = bittyLink;
|
||||
|
||||
var hash = location.hash;
|
||||
// if (push || !hash || !hash.length) {
|
||||
|
|
@ -392,6 +384,12 @@ function toggleMetadata(e) {
|
|||
QS("#doc-title").classList.toggle("open");
|
||||
QS("#md-title").focus();
|
||||
}
|
||||
|
||||
let previewContent = false;
|
||||
function togglePreview() {
|
||||
previewContent = !previewContent;
|
||||
document.body.classList.toggle("preview", previewContent);
|
||||
}
|
||||
function copyThenLink() {
|
||||
copyLink();
|
||||
return confirm("Copied your link to the clipboard. Paste it to share.");
|
||||
|
|
|
|||
Loading…
Reference in a new issue