Add quill editor

This commit is contained in:
Nicholas Jitkoff 2022-06-28 09:04:53 -07:00
parent 676b2564e6
commit 418b1ea843
3 changed files with 626 additions and 138 deletions

View file

@ -2,32 +2,37 @@
html {
--text-color:rgba(0, 0, 0, 0.87);
--text-placeholder-color:rgba(0,0,0,0.54);
--selected-text-color:#D42A20;
--text-placeholder-color: rgba(0,0,0,0.54);
--text-link-color:#0070e0;
--background-color:white;
--shadow-color:black;
color: var(--text-color);
background-color: var(--background-color);
--divider-color: rgba(0,0,0,0.15);
}
@media (prefers-color-scheme: dark) {
html {
--text-color:white;
--text-placeholder-color:rgba(255,255,255,0.54);
--selected-text-color:#e45149;
--text-placeholder-color:rgba(255,255,255,0.33);
--text-link-color:#40a0ff;
--background-color:#111;
--shadow-color:black;
--divider-color: rgba(255,255,255,0.15);
}
}
body {
margin: 0 auto;
padding: 12vh 10vmin;
max-width: 35em;
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;
box-sizing:
border-box;
}
h1 {
@ -81,22 +86,54 @@ body.drag #content {
#doc-title {
outline: none;
min-width: 180px;
/* min-width: 180px; */
top: 0;
position: absolute;
padding: 0.5em 0;
font-weight: bold;
font-size:small;
padding: 0 1em;
font-weight: normal;
opacity:0.33;
user-select: none;
cursor:
default;
margin-left: -1em;
line-height: 2.5em;
display: inline-block;
/* margin-top: -31em; */
z-index: 100;
}
body.edited #doc-title:empty:before,
#doc-title:focus:empty:before {
#doc-title.open {
background-color:var(--text-color);
color:var(--background-color);
opacity:1.0;
font-weight:bold;
}
#doc-title:empty:after {
content:"untitled";
}
#doc-title.open #metadata-text {
display:none;
}
body:not(.edited) #doc-title {
display:none;
}
body.edited #doc-title:empty:after{
content: "untitled";
color: var(--text-placeholder-color);
}
body.edited #doc-title.open:after {
content:"metadata";
color: var(--background-color);
}
#doc-title:focus {
border-bottom: 1px solid #ccc;
border-bottom: 1px solid var(--divider-color);
}
#doc-title:empty:before {
@ -109,18 +146,57 @@ body.edited #doc-title:empty:before,
background: transparent;
}
#md-contents {
display: flex;
flex-direction: column;
position: absolute;
/* top: 2em; */
background-color: var(--background-color);
padding: 1em;
z-index: 100;
border: 2px solid var(--text-color);
box-shadow: 2px 1px var(--text-color);
gap: 2px;
font-weight: bold;
margin-left: -1em;
line-height:1.5em;
/* min-width: 320px; */
}
input {
border: none;
background-color: transparent;
border-left: -18px solid transparent;
margin:-1px -2px;
padding:1px 2px;
min-width: 18em;
color:var(--text-color);
}
input::placeholder {
color:var(--text-placeholder-color);
}
input:focus {
outline:none;
}
#doc-file {
border-radius: 1em;
background-color: #fafafa;
padding: 0.25em 1em;
/* font-size: smaller; */
margin-bottom: 2em;
background-position: top center;
background-repeat: no-repeat;
background-image: url("data:image/svg+xml,%0A%3Csvg width='128' height='128' viewBox='0 0 128 128' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cmask id='path-1-outside-1_116_2' maskUnits='userSpaceOnUse' x='27' y='15' width='74' height='98' fill='black'%3E%3Crect fill='white' x='27' y='15' width='74' height='98'/%3E%3Cpath d='M80 16H28V112H100V36L80 16Z'/%3E%3C/mask%3E%3Cpath d='M80 16H28V112H100V36L80 16Z' fill='white'/%3E%3Cpath d='M28 16V15H27V16H28ZM80 16L80.7071 15.2929L80.4142 15H80V16ZM28 112H27V113H28V112ZM100 112V113H101V112H100ZM100 36H101V35.5858L100.707 35.2929L100 36ZM28 17H80V15H28V17ZM29 112V16H27V112H29ZM100 111H28V113H100V111ZM99 36V112H101V36H99ZM100.707 35.2929L80.7071 15.2929L79.2929 16.7071L99.2929 36.7071L100.707 35.2929Z' fill='black' fill-opacity='0.15' mask='url(%23path-1-outside-1_116_2)'/%3E%3C/svg%3E%0A");
min-height: 160px;/* background-size: 128px; */text-align: center;padding-top: 128px;}
background-image: url("data:image/svg+xml,%3Csvg width='128' height='128' viewBox='0 0 128 128' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M112 126H20C18.8954 126 18 125.105 18 124V4C18 2.89543 18.8954 2 20 2H88.3431C88.8736 2 89.3823 2.21071 89.7574 2.58579L113.414 26.2426C113.789 26.6177 114 27.1264 114 27.6569V124C114 125.105 113.105 126 112 126Z' fill='white' stroke='black' stroke-width='4'/%3E%3Crect x='88' y='4' width='4' height='24' fill='black'/%3E%3Crect x='88' y='24' width='24' height='4' fill='black'/%3E%3C/svg%3E%0A");
min-height: 160px;
text-align: center;
padding-top: 200px;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-position: center 60px;
box-sizing: border-box;
}
#doc-file:empty {
display: none;
}
@ -154,18 +230,6 @@ min-height: 160px;/* background-size: 128px; */text-align: center;padding-top: 1
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;
@ -176,7 +240,8 @@ min-height: 160px;/* background-size: 128px; */text-align: center;padding-top: 1
}
#length {
opacity: 0.54;
color:var(--text-placeholder-color);
text-align: right;
}
/*body.edited #toolbar {
@ -184,21 +249,81 @@ min-height: 160px;/* background-size: 128px; */text-align: center;padding-top: 1
transform: translateY(0);
}
*/
#toolbar {
position: fixed;
top: 0;
right: 0;
padding: 0.5em 1em;
text-align: right;
font-size:small;
font-weight: bold;
/*transform: translateY(-2em);*/
.toolbar {
font-size: 0.25rem;
}
.toolbar .spacer {
width:auto;
flex-grow: 1;
}
#menubar {
font-size:1rem;
position: fixed;
/* top: 0; */
right: 0;
left: 0;
font-weight: 600;
transition: transform 100ms ease-out;
border-bottom-left-radius: 1em;
cursor: pointer;
/* height: 40px; */
/* height: 2.5rem; */
box-sizing: border-box;
padding:0;
user-select: none;
display: flex;
justify-content: space-between;
flex-direction: row;
flex-wrap: wrap;
border: none;
/* background: var(--divider-color); */
/* z-index: 100; */
}
#menubar {
position: fixed;
top: 0;
left:0;
right:0;
/* max-height: 5rem; */
padding:0;
border:
none;
background-color:var(--background-color);
display:
flex;
align-items: left;
flex-direction: row;
justify-content: flex-start;
flex-wrap: wrap-reverse;
/* height: 10rem; */
padding-left: 4vmin;
}
#menubar > span {
display: flex;
/* outline:1px solid red; */
width:
auto;
margin-right: 0;
}
.hide-before-edit,
.ql-formats {
opacity:1.0;
transition:opacity 1s, transform 1s;
}
body:not(.edited) .hide-before-edit {
opacity:0;
pointer-events: none;
}
/* body.loaded:not(.edited) #menubar .ql-formats{
opacity: 0;
pointer-events: none;
transform:translateX(-2px)
} */
#copy-message {
background: #2d2d2d;
color: white;
@ -216,43 +341,268 @@ body:not(.copied) #copy-message {
#menus-share-hint {
content: "hello";
padding-left: 1em;
}
#toolbar .disabled {
#menubar .disabled {
opacity: 0.333;
}
#toolbar a {
margin-left: 0.5em;
#menubar > div {
/* margin-left: 0.5em; */
cursor: pointer;
text-decoration: none;
color: var(--text-color);
vertical-align: middle;
padding: 0 0.75em;
line-height: 2.5em;
/* height: 2em; */
/* margin-top: 2px; */
/* box-sizing: border-box; */
/* display: inline-block; */
height: 2.5rem;
/* overflow: hidden; */
/* width: 3.7rem; */
z-index: 100;
white-space: nowrap;
position: relative;
}
#toolbar a:hover {
text-decoration: underline;
#menubar .menu a:hover {
/* text-decoration: underline; */
background-color: var(--text-color);
color: var(--background-color);
}
.menu {
width: auto;
display: none;
color:var(--text-color);
color: var(--text-color);
/* background-color: var(--background-color); */
border: 2px solid currentColor;
padding: 0.5em;
padding: 0.5em 0;
box-shadow: 2px 2px var(--shadow-color);
margin-right: -0.5em;border-radius: 2px;
margin-top: 0.7em;}
margin-right: 2px;
border-radius: 2px;
margin-top: -2px;
z-index: 300;
/* top: 100px; */
/* text-align: left; */
/* float: right; */
/* width: 10rem; */
position: absolute;
/* right: 1rem; */
}
div#menu-contents {}
#toolbar.menu-visible .menu {
display: block;
#ql-header .ql-picker-label:before {
/* min-width: 7.5rem !important; */
max-width:20px;
overflow:
hidden;
content:
"H";
font-size: 19px;
line-height: 17px;
}
div.menu-contents {
display:none;
}
#toolbar.menu-visible #menu {
opacity: 0.54;
.menu-visible .menu {
display: block;
background-color: var(--background-color);
}
#menubar > a:active,
#menubar.menu-visible .menu-item {
background-color: var(--text-color);
color: var(--background-color);
box-sizing: border-box;
}
#md-contents:not(.menu-visible) {
display:none;
}
.menu-visible > .menu-item {
background-color: var(--text-color);
color: var(--background-color);
}
.menu-item {
padding:0 0.5em;
cursor:default;
}
.menu hr {
border: none;
background-color: currentColor;
height: 2px;
background-color: transparent;
height: 0;
border-bottom: 1px dotted var(--text-color);
cursor:default;
}
.inputrow {
padding: 0.2em 0;
border-bottom: 1px solid var(--divider-color);
display: flex;
margin-bottom: 0.5em;
}
.inputrow:focus-within {
border-bottom:2px solid var(--text-color);
padding-bottom:calc(0.2em - 1px);
}
input {
font-size:16px;
}
label:first-child {
min-width: 6em;
display: block;
margin-right: 1em;
user-select:none;
}
#editor .ql-editor {
font-size: 16px;
padding:0;
}
@media only screen and (max-device-width: 480px) {
#twitter,
#copy {
display: none;
}
#sharehint {
display: block;
}
#menu-share-hint {
display: none;
}
.inputrow {
flex-direction: column;
}
label {
font-size:10px;
}
}
#editor .ql-toolbar {
/* background-color: red; */
}
#editor .ql-tooltip {
background-color: var(--background-color);
/* border: 2px solid var(--text-color); */
box-shadow: 1px 2px 0 2px var(--text-color), 0 0 0px 2px var(--text-color);
box-sizing: border-box;
}
#ql-editor .ql-bubble .ql-stroke {
stroke: red;
}
.ql-bubble .ql-stroke {
stroke: currentColor !important;
}
.ql-picker-item.ql-selected {
color: red !important;
}
.menu a {
color: var(--text-color);
text-decoration: none;
line-height: 2em;
text-align: left;
display: block;
padding: 0 1em;
cursor:default;
}
.menu {
cursor:default;
}
#menubar.ql-snow.ql-toolbar button,
#menubar.ql-snow.ql-toolbar .ql-picker {
height: 40px;
min-width: 40px;
float: none;
vertical-align: middle;
text-align: revert;
width: 40px;
}
#menubar.ql-snow.ql-toolbar button,
#menubar.ql-snow.ql-toolbar .ql-picker .ql-picker-label {
/* background-size: 24px; */
padding: 10px;
}
div#editor.ql-container.ql-snow {
border: none;
}
#menubar.ql-snow .ql-color-picker .ql-picker-item {
margin: 0;
width: 1.5rem;
height: 1.5rem;
}
#menubar.ql-snow .ql-color-picker .ql-picker-options {
width: 11.2rem;
padding: 0;
}
.toolbar-right {
display: flex;
width: auto;
flex-wrap: nowrap;
gap: 1em;
justify-self: flex-end;
margin-left: auto;
}
#menubar .ql-toolbar,
#menubar .ql-stroke,
#menubar .ql-picker,
#menubar.ql-snow a {
color: var(--text-color) ;
stroke: var(--text-color) ;
}
.ql-picker-label:hover,
.ql-active {
color: var(--text-color) !important;
}
.ql-picker-options {
background-color: var(--background-color) !important;
}
.ql-picker-item.ql-selected {
color: #e45149 !important;
}
#mainmenu .menu {
right: 0;
/* top: 1px; */
}
div#mainmenu {
position: relative;
}
input#md-include {min-width: unset;height: 2em; width: 1em;margin-right: 1em;}
label:not(:first-child) {
font-weight: normal;
font-size: 16px;
}
.ql-formats {
opacity:0.0;
}

View file

@ -2,42 +2,96 @@
<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; 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'; script-src 'self' https://cdn.quilljs.com/ https://cdnjs.cloudflare.com/; connect-src https://codepen.io; font-src https://fonts.gstatic.com; style-src https://fonts.googleapis.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">
<title>itty.bitty</title>
<link rel="stylesheet" type="text/css" href="edit.css">
<link id="favicon" rel="icon" href='/favicon.svg'>
<link rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<script src="//cdn.quilljs.com/1.3.6/quill.min.js"></script>
<script src="/js/lzma/lzma_worker-min.js"></script>
<script src="/js/jquery-3.3.1.min.js"></script>
<script src="/edit.js" type="module"></script>
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined">
<body>
<div id="doc-title" contenteditable="true" placeholder="itty.bitty"></div>
<div id="doc-file"></div>
<div id="placeholder">
&nbsp;itty bitty things<br>
&nbsp;can be conveyed in a link.<br>
&nbsp;type here &ndash; and then share!<p>&nbsp;<a id="ib-info" href="http://about.bitty.site" target="_blank">about itty bitty</a><br>
</div>
<input id="file-input" type="file" name="name" style="display: none;" />
<div id="copy-message">Link copied to clipboard.</div>
<div id="content"></div>
<span id="toolbar">
<a target="_blank" id="length"></a>&nbsp;<a id="share" class="">share</a></div>&nbsp;<a target="_blank" class="" id="menu">menu</a>
<div id="menu-contents" class="menu">
<a id="copy">copy link</a>
<hr>
<span id="menus-share-hint" class="disabled">share via</span><br>
<a target="_blank" id="qrcode" href="https://zxing.appspot.com/generator/">qr code</a><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> -->
<hr>
<!-- <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 id="placeholder">&nbsp;itty bitty things<br>&nbsp;can be conveyed in a link.<br>&nbsp;type here &ndash; and then share!<p>&nbsp;<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>
</span>
<div id="editor"></div>
<div class="toolbar" id="menubar">
<!-- <div class="spacer"></div> -->
<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>
<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>
<button class="ql-indent" value="-1"></button>
<button class="ql-indent" value="+1"></button>
</span>
<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="copy">copy link</a>
<hr>
<span id="menus-share-hint" class="disabled">share via</span><br>
<a target="_blank" id="qrcode" href="https://zxing.appspot.com/generator/">make qr code</a>
<a target="_blank" id="twitter" href="https://twitter.com/">twitter</a>
<!-- <a target="_blank" id="bitly" href="https://bitly.com/">Bitly</a><br> -->
<a id="upload">upload file…</a>
<hr>
<!-- <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>
</div>
</div>
</div>
<div class="toolbar" id="formatbar">
</div>
</body>
</html>

View file

@ -1,5 +1,7 @@
import * as bitty from './bitty.js';
window.bitty = bitty;
var QS = document.querySelector.bind(document);
var QSS = document.querySelectorAll.bind(document);
@ -14,9 +16,32 @@ var b = document.documentElement.setAttribute(
navigator.userAgent
);
var bindings = {}
var quill = new Quill('#editor', {
theme: 'snow',
modules: {
syntax: true,
keyboard: { bindings },
toolbar: "#menubar"
}
});
quill.on('text-change', function(delta, oldDelta, source) {
if (source == 'api') {
console.debug("An API call triggered this change.");
} else if (source == 'user') {
console.debug("A user action triggered this change.", source);
}
handleContentChange();
});
quill.setSelection(0, Infinity);
var editor = quill.root;
console.log("editor", editor);
editor.autocomplete="off";
var importedFileData = undefined;
var content = undefined;
var content = editor;
window.onload = function() {
window.onpopstate = function(e) {
setContent(e.state);
@ -26,9 +51,9 @@ window.onload = function() {
location.reload();
};
document.body.onclick = function(e) {
if (e.target == document.body) content.focus();
if (e.target == document.body) editor.focus();
};
content = document.getElementById("content");
content.ondragenter = function(e) {
document.body.classList.add("drag");
};
@ -38,18 +63,21 @@ window.onload = function() {
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))
content.addEventListener("drop", handleDrop);
content.addEventListener("paste", handlePaste);
content.contentEditable = "true";
content.focus();
document.execCommand("selectAll", false, null);
// content.contentEditable = "true";
editor.focus();
// document.execCommand("selectAll", false, null);
QS("#qrcode").onclick = makeQRCode;
QS("#upload").onclick = upload;
QS("#share").onclick = share;
if (!navigator.share) QS("#share").style.display = "none"
QS("#twitter").onclick = tweetLink;
QS("#copy").onclick = copyLink;
QS("#menu").onclick = toggleMenu;
QS("#mainmenu").onclick = () => { toggleMenu(QS("#mainmenu"))};
QS("#doc-title").onclick = toggleMetadata;
var hash = window.location.hash.substring(1);
if (hash.length) {
@ -60,7 +88,7 @@ window.onload = function() {
title.replace(/_/g, " ")
);
hash = hash.substring(slashIndex + 1);
updateLink(hash, title);
updateLink(hash, {title});
if (hash.startsWith("?")) {
hash = hash.substring(1);
zipToString(hash, setContent);
@ -83,9 +111,8 @@ function setFileName(name) {
}
}
function updateBodyClass() {
var length = content.innerText.length;
if (length || importedFileData) {
function updateBodyClass(hasContent) {
if (hasContent || importedFileData) {
document.body.classList.add("edited");
} else {
document.body.classList.remove("edited");
@ -114,7 +141,7 @@ function handleDrop(e) {
if (e.altKey) url2 = url2.replace(DATA_PREFIX_BXZE, "!");
importedFileData = url2;
updateLink(url2, file.name, true);
updateLink(url2, {title:file.name}, true);
setFileName(file.name);
});
},
@ -151,6 +178,9 @@ function handleKey(e) {
document.execCommand("createLink", true, url);
}
}
} else if (code == 9 ) {
console.log("tab");
e.preventDefault();
}
if (handled) e.preventDefault();
}
@ -195,44 +225,67 @@ function fetchCodepen(url) {
setTimeout(function() {
var data = (useTemplate ? "" : DATA_PREFIX_BXZE) + zip;
importedFileData = data;
updateLink(data, title);
updateLink(data, {title});
}, 300);
});
});
}
function handleInput(e) {
updateBodyClass();
var text = content.innerText;
var title = QS("#doc-title").innerText;
handleContentChange(e);
}
function getMetadata() {
let formData = new FormData(document.forms[0]);
var object = {};
formData.forEach((value, key) => object[key] = value);
return object;
}
var rawHTML = text.indexOf("</") > 0;
if (rawHTML) {
text = text.replace(/[ |\t]+/g, " ").replace(/> +</g, "> <");
} else {
text = content.innerHTML;
}
function handleContentChange() {
if (text.trim().length) {
const t0 = performance.now();
bitty.compressString(text, bitty.GZIP64_MARKER, function(zip) {
const t1 = performance.now();
bitty.compressString(text, bitty.LZMA64_MARKER, function(zip2) {
const t2 = performance.now();
console.debug("\ngz", Math.round(zip.length/text.length*100), Math.round((t1-t0)),"ms", "\nlz", Math.round(zip2.length/text.length*100), Math.round((t2-t1)), "ms");
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;
}
if (text.trim().length) {
const t0 = performance.now();
bitty.compressString(text, bitty.GZIP64_MARKER, function(zip) {
const t1 = performance.now();
// 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("=","")
if (rawHTML) {
updateLink(DATA_PREFIX_GZIP + zip, metadata);
} else {
updateLink("?" + zip, metadata);
}
});
if (rawHTML) {
updateLink(DATA_PREFIX_GZIP + zip, title);
} else {
updateLink("?" + zip, title);
}
});
setFileName("");
} else if (importedFileData) {
updateLink(importedFileData, title);
} else {
updateLink("");
}
setFileName("");
} else if (importedFileData) {
updateLink(importedFileData, {title});
} else {
updateLink("");
}
}
var maxLengths = {
@ -241,23 +294,43 @@ var maxLengths = {
"#qrcode": 2953
};
function updateLink(url, title, push) {
if (title) title = encodeURIComponent(title.trim().replace(/\s/g, "_"));
let bittyLink = undefined;
function updateLink(url, metadata, push) {
let title = metadata.title;
// if (title) title = encodeURIComponent(title.trim().replace(/\s/g, "_"));
let includeMetadata = !metadata.includeMetadata;
let path = includeMetadata ? "/" : bitty.metadataToPath(metadata) ?? "/";
let prefix = includeMetadata ? bitty.encodePrettyComponent(title) : "";
if (url.length) {
url = "/#" + (title || "") + "/" + url;
url = path + "#" + prefix + "/" + url;
} else {
url = "/edit";
}
document.getElementById("doc-title-text").innerText = title.length ? title : "untitled";
bittyLink = new URL(url, document.location).href;
document.getElementById("canonical").href = bittyLink;
console.log({bittyLink});
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;
// if (push || !hash || !hash.length) {
// window.history.pushState(content.innerHTML, null, url);
// } else {
// window.history.replaceState(content.innerHTML, null, url);
// }
var length = bittyLink.length;
QS("#length").innerText = length + " bytes";
QS("#length").href = url;
QS("#length").onclick = () => {
window.open(bittyLink, "_blank");
}
for (var key in maxLengths) {
var maxLength = maxLengths[key];
if (length > maxLength) {
@ -271,7 +344,7 @@ function updateLink(url, title, push) {
function share() {
navigator.share({
title: 'itty.bitty',
url: location.href
url: bittyLink
}).then(() => {
console.log('Thanks for sharing!');
})
@ -283,9 +356,20 @@ function makeQRCode() {
encodeURIComponent(location.href);
this.href = url;
}
function upload() {
document.getElementById('file-input').click();
}
function toggleMenu() {
QS("#toolbar").classList.toggle("menu-visible");
function toggleMenu(el) {
el.classList.toggle("menu-visible");
}
function toggleMetadata(e) {
if (e.target.closest(".menu")) return;
console.log(e)
QS("#md-contents").classList.toggle("menu-visible");
QS("#doc-title").classList.toggle("open");
QS("#md-title").focus();
}
function copyThenLink() {
copyLink();