Client-side Paste Service In Pure JavaScript – Paste

Category: Javascript , Text | November 8, 2019
Author: topaz
Views Total: 17
Official Page: Go to website
Last Update: November 8, 2019
License: MIT

Preview:

Client-side Paste Service In Pure JavaScript – Paste

Description:

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; }

You Might Be Interested In:


Leave a Reply