
A JavaScript-only, client-side paste service to store and share plain text in a simple way.
It compresses plain text you typed using Lempel–Ziv–Markov chain algorithm and generates Base64-encoded URLs & markdown links without server-side handling.
How to use it:
1. Create a textarea element to store plain text.
<div id="plaintext-wrapper"> <textarea id="plaintext"></textarea> </div>
2. Create controls for the paste service.
<div id="nav">
<span class="nav-default">
<a class="nav-left" onclick="invert()">[invert colors]</a>
<a onclick="url_generate('raw')">[generate url]</a>
<a onclick="url_generate('markdown')">[generate markdown link]</a>
</span>
<span class="nav-text-offer">
<input id="text-offer-value"/>
<a onclick="text_offer_copy()">[copy]</a>
<a onclick="text_offer_cancel()">[cancel]</a>
</span>
</div>3. Load the required JavaScript file in the document.
<script src="lzma.js"></script>
4. The main JavaScript to enable the paste service.
var matches;
var lzma = new LZMA("lzma_worker.js");
document.addEventListener('DOMContentLoaded', function(){
document.getElementById("plaintext").focus();
if (matches = /(?:^|\;)invert\=([01])(?:\;|$)/.exec(document.cookie)) {
if (matches[1] === '1') {
document.body.classList.add("invert");
}
}
var base64 = location.hash.substr(1);
if (base64.length == 0) return;
if (!fetch) {
alert("Your browser does not support this page. Sorry! :(");
return;
}
fetch("data:application/octet-stream;base64,"+base64).then(r => r.blob()).then(function(blob){
var reader = new FileReader();
reader.onload = function(){
var compressed_data = Array.from(new Uint8Array(reader.result));
lzma.decompress(compressed_data, function(plaintext, error){
if (error) {
alert("Failed to decompress data: "+error);
return;
}
document.getElementById("plaintext").value = plaintext;
});
};
reader.readAsArrayBuffer(blob);
});
});
function url_generate(format) {
var plaintext = document.getElementById("plaintext").value;
lzma.compress(plaintext, 1, function(compressed, error){
if (error) {
alert("Failed to compress data: "+error);
return;
}
var reader = new FileReader();
reader.onload = function(){
var base64 = reader.result.substr(reader.result.indexOf(",")+1);
var url = "https://"+location.host+location.pathname+"#"+base64;
var result;
if (format === 'markdown') {
result = "[paste]("+url+")";
} else {
result = url;
}
text_offer(result);
};
reader.readAsDataURL(new Blob([new Uint8Array(compressed)]));
});
}
function text_offer(text) {
document.getElementById("text-offer-value").value = text;
document.getElementById("nav").classList.add("text-offer");
}
function text_offer_copy() {
var input = document.getElementById("text-offer-value");
input.select();
document.execCommand('copy');
text_offer_cancel();
}
function text_offer_cancel() {
document.getElementById("text-offer-value").value = "";
document.getElementById("nav").classList.remove("text-offer");
}
function invert() {
var pref = document.body.classList.contains("invert") ? 0 : 1;
document.cookie = "invert="+pref+";max-age=63072000";
document.body.classList[pref?"add":"remove"]("invert");
}5. The example CSS styles.
#plaintext {
width: 100%;
height: 100%;
padding: .5em;
border: 0;
margin: 0;
resize: none;
color: #eeeeee;
background: #000000;
}
body.invert #plaintext {
color: #000000;
background: #eeeeee;
}
#plaintext-wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 2em;
}
#nav {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 2em;
line-height: 2em;
text-align: right;
vertical-align: middle;
background: #333333;
color: #ffffff;
white-space: nowrap;
}
body.invert #nav {
background: #aaaaaa;
color: #000000;
}
#nav .nav-left {
float: left;
}
#nav a {
display: inline-block;
padding: 0 .5em;
text-decoration: none;
color: inherit;
cursor: pointer;
}
#nav a:hover {
background: #666666;
}
body.invert #nav a:hover {
background: #999999;
}
#nav #text-offer-value {
border: 1px solid #999999;
background: transparent;
width: calc(100vw - 11em);
text-overflow: ellipsis;
color: inherit;
margin-right: 5px;
}
#nav .nav-text-offer { display:none; }
#nav.text-offer .nav-default { display:none; }
#nav.text-offer .nav-text-offer { display:inline; }






