add some fancy magic :kekw:

This commit is contained in:
2025-10-13 18:21:23 +02:00
parent 2e59c1f5e7
commit 22badaf535
15 changed files with 1328 additions and 786 deletions

View File

@@ -4,20 +4,51 @@ html {
body {
background: #002B36;
height: 90%;
color: #839496;
font-family: sans-serif;
margin: 0;
padding: 1em;
padding: 0;
display: flex;
flex-direction: column;
height: 100%;
}
#tools {
background: #00212b;
padding: 8px;
font-size: 14px;
flex-shrink: 0;
}
#tools .function {
display: inline-block;
padding: 4px 8px;
margin: 0 4px;
color: #839496;
border-radius: 3px;
text-decoration: none;
}
#tools .function.enabled {
cursor: pointer;
color: #93a1a1;
}
#tools .function.enabled:hover {
background: #073642;
color: #eee8d5;
}
#content {
height: 100%;
padding: 0;
flex-grow: 1;
padding: 1em;
overflow-y: auto;
}
textarea {
background: transparent;
border: 0;
color: #fff;
color: #eee8d5;
font-family: monospace;
font-size: 1em;
height: 100%;
@@ -34,6 +65,7 @@ textarea {
outline: none;
padding: 0 0 4em 0;
white-space: pre-wrap;
word-wrap: break-word;
}
#code code {
@@ -60,77 +92,4 @@ pre .line::before {
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#tools {
background: #08323c;
bottom: 0;
font-size: 0;
left: 0;
position: fixed;
width: 100%;
}
#tools .function {
background: url(function-icons.png);
display: inline-block;
height: 37px;
position: relative;
width: 32px;
}
#tools .link embed {
vertical-align: bottom;
}
#tools .function.enabled:hover {
cursor: pointer;
}
#tools .function.save {
background-position: -5px top;
}
#tools .function.enabled.save {
background-position: -5px center;
}
#tools .function.enabled.save:hover {
background-position: -5px bottom;
}
#tools .function.new {
background-position: -42px top;
}
#tools .function.enabled.new {
background-position: -42px center;
}
#tools .function.enabled.new:hover {
background-position: -42px bottom;
}
#tools .function.duplicate {
background-position: -79px top;
}
#tools .function.enabled.duplicate {
background-position: -79px center;
}
#tools .function.enabled.duplicate:hover {
background-position: -79px bottom;
}
#tools .function.raw {
background-position: -116px top;
}
#tools .function.enabled.raw {
background-position: -116px center;
}
#tools .function.enabled.raw:hover {
background-position: -116px bottom;
}
}

View File

@@ -1,6 +1,5 @@
// represents the haste-application
var haste = function() {
this.appName = "Hastebin Plus";
const Haste = function() {
this.appName = "unknownBIN";
this.$textarea = $('textarea');
this.$box = $('#code');
this.$code = $('#code code');
@@ -9,26 +8,26 @@ var haste = function() {
};
// set title (browser window)
haste.prototype.setTitle = function(ext) {
var title = ext ? this.appName + ' - ' + ext : this.appName;
Haste.prototype.setTitle = function(ext) {
const title = ext ? `${this.appName} - ${ext}` : this.appName;
document.title = title;
};
// show the light key
haste.prototype.lightKey = function() {
Haste.prototype.lightKey = function() {
this.configureKey(['new', 'save']);
};
// show the full key
haste.prototype.fullKey = function() {
Haste.prototype.fullKey = function() {
this.configureKey(['new', 'duplicate', 'raw']);
};
// enable certain keys
haste.prototype.configureKey = function(enable) {
Haste.prototype.configureKey = function(enable) {
$('#tools .function').each(function() {
var $this = $(this);
for (var i = 0; i < enable.length; i++) {
const $this = $(this);
for (let i = 0; i < enable.length; i++) {
if ($this.hasClass(enable[i])) {
$this.addClass('enabled');
return true;
@@ -39,9 +38,9 @@ haste.prototype.configureKey = function(enable) {
};
// setup a new, blank document
haste.prototype.newDocument = function(hideHistory) {
Haste.prototype.newDocument = function(hideHistory) {
this.$box.hide();
this.doc = new haste_document();
this.doc = new HasteDocument();
if (!hideHistory) {
window.history.pushState(null, this.appName, '/');
}
@@ -53,14 +52,14 @@ haste.prototype.newDocument = function(hideHistory) {
};
// load an existing document
haste.prototype.loadDocument = function(key) {
var _this = this;
_this.doc = new haste_document();
Haste.prototype.loadDocument = function(key) {
const _this = this;
_this.doc = new HasteDocument();
_this.doc.load(key, function(ret) {
if (ret) {
_this.$code.html(ret.value);
_this.setTitle(ret.key);
window.history.pushState(null, _this.appName + '-' + ret.key, '/' + ret.key);
window.history.pushState(null, `${_this.appName}-${ret.key}`, `/${ret.key}`);
_this.fullKey();
_this.$textarea.val('').hide();
_this.$box.show();
@@ -71,22 +70,22 @@ haste.prototype.loadDocument = function(key) {
};
// duplicate the current document
haste.prototype.duplicateDocument = function() {
Haste.prototype.duplicateDocument = function() {
if (this.doc.locked) {
var currentData = this.doc.data;
const currentData = this.doc.data;
this.newDocument();
this.$textarea.val(currentData);
}
};
// lock the current document
haste.prototype.lockDocument = function() {
var _this = this;
Haste.prototype.lockDocument = function() {
const _this = this;
this.doc.save(this.$textarea.val(), function(err, ret) {
if (!err && ret) {
_this.$code.html(ret.value.trim().replace(/.+/g, "<span class=\"line\">$&</span>").replace(/^\s*[\r\n]/gm, "<span class=\"line\"></span>\n"));
_this.setTitle(ret.key);
window.history.pushState(null, _this.appName + '-' + ret.key, '/' + ret.key);
window.history.pushState(null, `${_this.appName}-${ret.key}`, `/${ret.key}`);
_this.fullKey();
_this.$textarea.val('').hide();
_this.$box.show();
@@ -95,8 +94,8 @@ haste.prototype.lockDocument = function() {
};
// configure buttons and their shortcuts
haste.prototype.configureButtons = function() {
var _this = this;
Haste.prototype.configureButtons = function() {
const _this = this;
this.buttons = [
{
$where: $('#tools .save'),
@@ -133,17 +132,17 @@ haste.prototype.configureButtons = function() {
return evt.ctrlKey && evt.shiftKey && evt.keyCode === 82;
},
action: function() {
window.location.href = '/raw/' + _this.doc.key;
window.location.href = `/raw/${_this.doc.key}`;
}
}
];
for (var i = 0; i < this.buttons.length; i++) {
for (let i = 0; i < this.buttons.length; i++) {
this.configureButton(this.buttons[i]);
}
};
// handles the button-click
haste.prototype.configureButton = function(options) {
Haste.prototype.configureButton = function(options) {
options.$where.click(function(evt) {
evt.preventDefault();
if (!options.clickDisabled && $(this).hasClass('enabled')) {
@@ -153,11 +152,11 @@ haste.prototype.configureButton = function(options) {
};
// enables the configured shortcuts
haste.prototype.configureShortcuts = function() {
var _this = this;
Haste.prototype.configureShortcuts = function() {
const _this = this;
$(document.body).keydown(function(evt) {
var button;
for (var i = 0; i < _this.buttons.length; i++) {
let button;
for (let i = 0; i < _this.buttons.length; i++) {
button = _this.buttons[i];
if (button.shortcut && button.shortcut(evt)) {
evt.preventDefault();
@@ -169,12 +168,12 @@ haste.prototype.configureShortcuts = function() {
};
// represents a single document
var haste_document = function() {
const HasteDocument = function() {
this.locked = false;
};
// escape HTML-characters
haste_document.prototype.htmlEscape = function(s) {
HasteDocument.prototype.htmlEscape = function(s) {
return s
.replace(/&/g, '&amp;')
.replace(/>/g, '&gt;')
@@ -183,40 +182,39 @@ haste_document.prototype.htmlEscape = function(s) {
};
// load a document from the server
haste_document.prototype.load = function(key, callback) {
var _this = this;
$.ajax('/documents/' + key, {
HasteDocument.prototype.load = function(key, callback) {
const _this = this;
$.ajax(`/documents/${key}`, {
type: 'get',
dataType: 'json',
success: function(res) {
_this.locked = true;
_this.key = key;
_this.data = res.data;
high = hljs.highlightAuto(res.data).value;
const high = hljs.highlightAuto(res.data).value;
callback({
value: high.replace(/.+/g, "<span class=\"line\">$&</span>").replace(/^\s*[\r\n]/gm, "<span class=\"line\"></span>\n"),
key: key,
});
},
error: function(err) {
error: function() {
callback(false);
}
});
};
// sends the document to the server
haste_document.prototype.save = function(data, callback) {
HasteDocument.prototype.save = function(data, callback) {
if (this.locked) return false;
this.data = data;
var _this = this;
$.ajax('/documents', {
type: 'post',
data: data.trim(),
data: data,
dataType: 'json',
contentType: 'application/json; charset=utf-8',
contentType: 'text/plain; charset=utf-8',
success: function(res) {
new haste().loadDocument(res.key);
new Haste().loadDocument(res.key);
},
error: function(res) {
try {
@@ -234,16 +232,16 @@ $(function() {
// allow usage of tabs
if (evt.keyCode === 9) {
evt.preventDefault();
var myValue = ' ';
const myValue = ' ';
if (document.selection) {
this.focus();
sel = document.selection.createRange();
let sel = document.selection.createRange();
sel.text = myValue;
this.focus();
} else if (this.selectionStart || this.selectionStart == '0') {
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var scrollTop = this.scrollTop;
const startPos = this.selectionStart;
const endPos = this.selectionEnd;
const scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
this.focus();
this.selectionStart = startPos + myValue.length;
@@ -256,8 +254,8 @@ $(function() {
}
});
var app = new haste();
var path = window.location.pathname;
const app = new Haste();
const path = window.location.pathname;
if (path === '/') {
app.newDocument(true);
} else {
@@ -265,4 +263,4 @@ $(function() {
}
});
hljs.initHighlightingOnLoad();
hljs.initHighlightingOnLoad();

1
static/application.min.css vendored Normal file
View File

@@ -0,0 +1 @@
html{height:100%}body{background:#002b36;color:#839496;font-family:sans-serif;margin:0;padding:0;display:flex;flex-direction:column;height:100%}#tools{background:#00212b;padding:8px;font-size:14px;flex-shrink:0}#tools .function{display:inline-block;padding:4px 8px;margin:0 4px;color:#839496;border-radius:3px;text-decoration:none}#tools .function.enabled{cursor:pointer;color:#93a1a1}#tools .function.enabled:hover{background:#073642;color:#eee8d5}#content{flex-grow:1;padding:1em;overflow-y:auto}textarea{background:0 0;border:0;color:#eee8d5;font-family:monospace;font-size:1em;height:100%;outline:0;padding:0;resize:none;width:100%}#code{border:0;font-size:1em;margin:0;outline:0;padding:0 0 4em 0;white-space:pre-wrap;word-wrap:break-word}#code code{background:0 0!important;padding:0}pre{counter-reset:line-numbering}pre .line::before{color:#4c6a71;content:counter(line-numbering);counter-increment:line-numbering;display:inline-block;margin-right:1em;text-align:right;width:1.5em!important;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}

1
static/application.min.js vendored Normal file
View File

@@ -0,0 +1 @@
let Haste=function(){this.appName="unknownBIN",this.$textarea=$("textarea"),this.$box=$("#code"),this.$code=$("#code code"),this.configureShortcuts(),this.configureButtons()},HasteDocument=(Haste.prototype.setTitle=function(t){t=t?this.appName+" - "+t:this.appName;document.title=t},Haste.prototype.lightKey=function(){this.configureKey(["new","save"])},Haste.prototype.fullKey=function(){this.configureKey(["new","duplicate","raw"])},Haste.prototype.configureKey=function(o){$("#tools .function").each(function(){var e=$(this);for(let t=0;t<o.length;t++)if(e.hasClass(o[t]))return e.addClass("enabled"),!0;e.removeClass("enabled")})},Haste.prototype.newDocument=function(t){this.$box.hide(),this.doc=new HasteDocument,t||window.history.pushState(null,this.appName,"/"),this.setTitle(),this.lightKey(),this.$textarea.val("").show("fast",function(){this.focus()})},Haste.prototype.loadDocument=function(t){let e=this;e.doc=new HasteDocument,e.doc.load(t,function(t){t?(e.$code.html(t.value),e.setTitle(t.key),window.history.pushState(null,e.appName+"-"+t.key,"/"+t.key),e.fullKey(),e.$textarea.val("").hide(),e.$box.show()):e.newDocument()})},Haste.prototype.duplicateDocument=function(){var t;this.doc.locked&&(t=this.doc.data,this.newDocument(),this.$textarea.val(t))},Haste.prototype.lockDocument=function(){let o=this;this.doc.save(this.$textarea.val(),function(t,e){!t&&e&&(o.$code.html(e.value.trim().replace(/.+/g,'<span class="line">$&</span>').replace(/^\s*[\r\n]/gm,'<span class="line"></span>\n')),o.setTitle(e.key),window.history.pushState(null,o.appName+"-"+e.key,"/"+e.key),o.fullKey(),o.$textarea.val("").hide(),o.$box.show())})},Haste.prototype.configureButtons=function(){let e=this;this.buttons=[{$where:$("#tools .save"),shortcut:function(t){return t.ctrlKey&&83===t.keyCode},action:function(){""!==e.$textarea.val().replace(/^\s+|\s+$/g,"")&&e.lockDocument()}},{$where:$("#tools .new"),shortcut:function(t){return t.ctrlKey&&32===t.keyCode},action:function(){e.newDocument(!e.doc.key)}},{$where:$("#tools .duplicate"),shortcut:function(t){return e.doc.locked&&t.ctrlKey&&68===t.keyCode},action:function(){e.duplicateDocument()}},{$where:$("#tools .raw"),shortcut:function(t){return t.ctrlKey&&t.shiftKey&&82===t.keyCode},action:function(){window.location.href="/raw/"+e.doc.key}}];for(let t=0;t<this.buttons.length;t++)this.configureButton(this.buttons[t])},Haste.prototype.configureButton=function(e){e.$where.click(function(t){t.preventDefault(),!e.clickDisabled&&$(this).hasClass("enabled")&&e.action()})},Haste.prototype.configureShortcuts=function(){let n=this;$(document.body).keydown(function(e){var o;for(let t=0;t<n.buttons.length;t++)if((o=n.buttons[t]).shortcut&&o.shortcut(e))return e.preventDefault(),void o.action()})},function(){this.locked=!1});HasteDocument.prototype.htmlEscape=function(t){return t.replace(/&/g,"&amp;").replace(/>/g,"&gt;").replace(/</g,"&lt;").replace(/"/g,"&quot;")},HasteDocument.prototype.load=function(e,o){let n=this;$.ajax("/documents/"+e,{type:"get",dataType:"json",success:function(t){n.locked=!0,n.key=e,n.data=t.data;t=hljs.highlightAuto(t.data).value;o({value:t.replace(/.+/g,'<span class="line">$&</span>').replace(/^\s*[\r\n]/gm,'<span class="line"></span>\n'),key:e})},error:function(){o(!1)}})},HasteDocument.prototype.save=function(t,e){if(this.locked)return!1;this.data=t,$.ajax("/documents",{type:"post",data:t,dataType:"json",contentType:"text/plain; charset=utf-8",success:function(t){(new Haste).loadDocument(t.key)},error:function(t){try{e($.parseJSON(t.responseText))}catch(t){e({message:"Something went wrong!"})}}})},$(function(){$("textarea").keydown(function(t){var e,o,n;9===t.keyCode&&(t.preventDefault(),t=" ",document.selection?(this.focus(),document.selection.createRange().text=t,this.focus()):this.selectionStart||"0"==this.selectionStart?(e=this.selectionStart,o=this.selectionEnd,n=this.scrollTop,this.value=this.value.substring(0,e)+t+this.value.substring(o,this.value.length),this.focus(),this.selectionStart=e+t.length,this.selectionEnd=e+t.length,this.scrollTop=n):(this.value+=t,this.focus()))});var t=new Haste,e=window.location.pathname;"/"===e?t.newDocument(!0):t.loadDocument(e.substring(1,e.length))}),hljs.initHighlightingOnLoad();

1
static/highlight.min.css vendored Normal file
View File

@@ -0,0 +1 @@
.hljs{display:block;overflow-x:auto;padding:.5em;background:#002b36;color:#839496}.hljs-comment,.hljs-quote{color:#586e75}.hljs-addition,.hljs-keyword,.hljs-selector-tag{color:#859900}.hljs-doctag,.hljs-literal,.hljs-meta .hljs-meta-string,.hljs-number,.hljs-regexp,.hljs-string{color:#2aa198}.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-title{color:#268bd2}.hljs-attr,.hljs-attribute,.hljs-class .hljs-title,.hljs-template-variable,.hljs-type,.hljs-variable{color:#b58900}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-subst,.hljs-symbol{color:#cb4b16}.hljs-built_in,.hljs-deletion{color:#dc322f}.hljs-formula{background:#073642}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Hastebin Plus</title>
<title>unknownBIN</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" type="text/css" href="application.min.css"/>
<link rel="stylesheet" type="text/css" href="highlight.min.css"/>
@@ -11,15 +11,15 @@
<script src="application.min.js"></script>
</head>
<body>
<div id="tools">
<div class="save function" title="Save [Ctrl + S]">Save</div>
<div class="new function" title="New [Ctrl + Space]">New</div>
<div class="duplicate function" title="Duplicate [Ctrl + D]">Duplicate</div>
<div class="raw function" title="Raw [Ctrl + Shift + R]">Raw</div>
</div>
<div id="content">
<pre id="code" style="display:none;" tabindex="0"><code></code></pre>
<textarea spellcheck="false" style="display:none;"></textarea>
</div>
<div id="tools">
<div class="save function" title="Save [Ctrl + S]"></div>
<div class="new function" title="New [Ctrl + Space]"></div>
<div class="duplicate function" title="Duplicate [Ctrl + D]"></div>
<div class="raw function" title="Raw [Ctrl + Shift + R]"></div>
</div>
</body>
</html>
</html>