Add a HTML frontend

This commit is contained in:
Les De Ridder 2016-05-30 21:31:50 +02:00
parent 21aa7e2dcf
commit 15d293d9c0
6 changed files with 386 additions and 3 deletions

View File

@ -10,6 +10,7 @@ use App\Paste;
use Pygmentize\Pygmentize;
use Carbon\Carbon;
use Carbon\CarbonInterval;
class PasteController extends Controller
{
@ -20,7 +21,7 @@ class PasteController extends Controller
$paste = new Paste;
$paste->id = Paste::create_id();
$paste->created_at = $request->input('available_at', Carbon::now());
$paste->expires_at = $request->input('expires_at', null);
$paste->expires_at = $this->calculate_expiry($request->input('expire_after', null), $paste->created_at);
$paste->language = $request->input('language', 'text');
$paste->save();
$paste->content = $request->input('content');
@ -35,6 +36,18 @@ class PasteController extends Controller
}
}
private static function calculate_expiry($expire_after, $available_at)
{
if($expire_after === null || $expire_after === "never")
{
return null;
}
else
{
return Carbon::parse($available_at)->copy()->addSeconds((int)$expire_after);
}
}
public function view(Request $request, Paste $paste)
{
$format = $request->input('format', 'html'); //TODO: Use HTTP content negotiation for the default format
@ -53,6 +66,8 @@ class PasteController extends Controller
return $this->view_png($paste);
case 'terminal':
return $this->view_terminal($paste);
case 'irc':
return $this->view_irc($paste);
case 'terminal256':
return $this->view_terminal256($paste);
default:
@ -165,6 +180,29 @@ class PasteController extends Controller
}
}
private function view_irc(Paste $paste)
{
//TODO: More informative messages
if($paste->deleted)
{
response('This paste was deleted.')->header('Content-Type', 'text/plain');
}
else if($paste->is_future_paste)
{
response('This paste is not available yet.')->header('Content-Type', 'text/plain');
}
else if($paste->has_expired)
{
response('This paste has expired.')->header('Content-Type', 'text/plain');
}
else
{
$content = Pygmentize::highlight($paste->content, $paste->language, "utf-8", "irc");
return response($content)->header('Content-Type', 'text/plain');
}
}
private function view_json(Paste $paste)
{
if($paste->deleted)

View File

@ -1,5 +1,7 @@
<?php
use Illuminate\Http\Request;
/*
|--------------------------------------------------------------------------
| Application Routes
@ -11,8 +13,8 @@
|
*/
Route::get('/', function () {
return view('welcome');
Route::get('/', function (Request $request) {
return view('main', ['js' => $request->input('js', false)]);
});
Route::post('/paste', 'PasteController@create');

View File

@ -77,6 +77,11 @@ class Paste extends Model
return $this->created_at > Carbon::now();
}
public function getIdAttribute($value)
{
return trim($value);
}
public function getContentAttribute()
{
if($this->deleted)

128
public/pygments.css vendored Normal file
View File

@ -0,0 +1,128 @@
pre .hll { background-color: #ffffcc }
pre .c { color: #60a0b0; font-style: italic } /* Comment */
pre .err { border: 1px solid #FF0000 } /* Error */
pre .k { color: #007020; font-weight: bold } /* Keyword */
pre .o { color: #666666 } /* Operator */
pre .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */
pre .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
pre .cp { color: #007020 } /* Comment.Preproc */
pre .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */
pre .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
pre .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
pre .gd { color: #A00000 } /* Generic.Deleted */
pre .ge { font-style: italic } /* Generic.Emph */
pre .gr { color: #FF0000 } /* Generic.Error */
pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */
pre .gi { color: #00A000 } /* Generic.Inserted */
pre .go { color: #888888 } /* Generic.Output */
pre .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
pre .gs { font-weight: bold } /* Generic.Strong */
pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
pre .gt { color: #0044DD } /* Generic.Traceback */
pre .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
pre .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
pre .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
pre .kp { color: #007020 } /* Keyword.Pseudo */
pre .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
pre .kt { color: #902000 } /* Keyword.Type */
pre .m { color: #40a070 } /* Literal.Number */
pre .s { color: #4070a0 } /* Literal.String */
pre .na { color: #4070a0 } /* Name.Attribute */
pre .nb { color: #007020 } /* Name.Builtin */
pre .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
pre .no { color: #60add5 } /* Name.Constant */
pre .nd { color: #555555; font-weight: bold } /* Name.Decorator */
pre .ni { color: #d55537; font-weight: bold } /* Name.Entity */
pre .ne { color: #007020 } /* Name.Exception */
pre .nf { color: #06287e } /* Name.Function */
pre .nl { color: #002070; font-weight: bold } /* Name.Label */
pre .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
pre .nt { color: #062873; font-weight: bold } /* Name.Tag */
pre .nv { color: #bb60d5 } /* Name.Variable */
pre .ow { color: #007020; font-weight: bold } /* Operator.Word */
pre .w { color: #bbbbbb } /* Text.Whitespace */
pre .mb { color: #40a070 } /* Literal.Number.Bin */
pre .mf { color: #40a070 } /* Literal.Number.Float */
pre .mh { color: #40a070 } /* Literal.Number.Hex */
pre .mi { color: #40a070 } /* Literal.Number.Integer */
pre .mo { color: #40a070 } /* Literal.Number.Oct */
pre .sb { color: #4070a0 } /* Literal.String.Backtick */
pre .sc { color: #4070a0 } /* Literal.String.Char */
pre .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
pre .s2 { color: #4070a0 } /* Literal.String.Double */
pre .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
pre .sh { color: #4070a0 } /* Literal.String.Heredoc */
pre .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
pre .sx { color: #c65d09 } /* Literal.String.Other */
pre .sr { color: #235388 } /* Literal.String.Regex */
pre .s1 { color: #4070a0 } /* Literal.String.Single */
pre .ss { color: #517918 } /* Literal.String.Symbol */
pre .bp { color: #007020 } /* Name.Builtin.Pseudo */
pre .vc { color: #bb60d5 } /* Name.Variable.Class */
pre .vg { color: #bb60d5 } /* Name.Variable.Global */
pre .vi { color: #bb60d5 } /* Name.Variable.Instance */
pre .il { color: #40a070 } /* Literal.Number.Integer.Long */.syntax pre .hll { background-color: #ffffcc }
.syntax pre { background: #f0f0f0; }
.syntax pre .c { color: #60a0b0; font-style: italic } /* Comment */
.syntax pre .err { border: 1px solid #FF0000 } /* Error */
.syntax pre .k { color: #007020; font-weight: bold } /* Keyword */
.syntax pre .o { color: #666666 } /* Operator */
.syntax pre .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */
.syntax pre .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
.syntax pre .cp { color: #007020 } /* Comment.Preproc */
.syntax pre .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */
.syntax pre .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
.syntax pre .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
.syntax pre .gd { color: #A00000 } /* Generic.Deleted */
.syntax pre .ge { font-style: italic } /* Generic.Emph */
.syntax pre .gr { color: #FF0000 } /* Generic.Error */
.syntax pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.syntax pre .gi { color: #00A000 } /* Generic.Inserted */
.syntax pre .go { color: #888888 } /* Generic.Output */
.syntax pre .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.syntax pre .gs { font-weight: bold } /* Generic.Strong */
.syntax pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.syntax pre .gt { color: #0044DD } /* Generic.Traceback */
.syntax pre .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.syntax pre .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.syntax pre .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.syntax pre .kp { color: #007020 } /* Keyword.Pseudo */
.syntax pre .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.syntax pre .kt { color: #902000 } /* Keyword.Type */
.syntax pre .m { color: #40a070 } /* Literal.Number */
.syntax pre .s { color: #4070a0 } /* Literal.String */
.syntax pre .na { color: #4070a0 } /* Name.Attribute */
.syntax pre .nb { color: #007020 } /* Name.Builtin */
.syntax pre .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.syntax pre .no { color: #60add5 } /* Name.Constant */
.syntax pre .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.syntax pre .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.syntax pre .ne { color: #007020 } /* Name.Exception */
.syntax pre .nf { color: #06287e } /* Name.Function */
.syntax pre .nl { color: #002070; font-weight: bold } /* Name.Label */
.syntax pre .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.syntax pre .nt { color: #062873; font-weight: bold } /* Name.Tag */
.syntax pre .nv { color: #bb60d5 } /* Name.Variable */
.syntax pre .ow { color: #007020; font-weight: bold } /* Operator.Word */
.syntax pre .w { color: #bbbbbb } /* Text.Whitespace */
.syntax pre .mb { color: #40a070 } /* Literal.Number.Bin */
.syntax pre .mf { color: #40a070 } /* Literal.Number.Float */
.syntax pre .mh { color: #40a070 } /* Literal.Number.Hex */
.syntax pre .mi { color: #40a070 } /* Literal.Number.Integer */
.syntax pre .mo { color: #40a070 } /* Literal.Number.Oct */
.syntax pre .sb { color: #4070a0 } /* Literal.String.Backtick */
.syntax pre .sc { color: #4070a0 } /* Literal.String.Char */
.syntax pre .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.syntax pre .s2 { color: #4070a0 } /* Literal.String.Double */
.syntax pre .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.syntax pre .sh { color: #4070a0 } /* Literal.String.Heredoc */
.syntax pre .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.syntax pre .sx { color: #c65d09 } /* Literal.String.Other */
.syntax pre .sr { color: #235388 } /* Literal.String.Regex */
.syntax pre .s1 { color: #4070a0 } /* Literal.String.Single */
.syntax pre .ss { color: #517918 } /* Literal.String.Symbol */
.syntax pre .bp { color: #007020 } /* Name.Builtin.Pseudo */
.syntax pre .vc { color: #bb60d5 } /* Name.Variable.Class */
.syntax pre .vg { color: #bb60d5 } /* Name.Variable.Global */
.syntax pre .vi { color: #bb60d5 } /* Name.Variable.Instance */
.syntax pre .il { color: #40a070 } /* Literal.Number.Integer.Long */

View File

@ -0,0 +1,162 @@
<!DOCTYPE html>
<html>
<head>
<title>pastethingy</title>
<link href="https://fonts.googleapis.com/css?family=Lato:300" rel="stylesheet" type="text/css">
<link href='https://fonts.googleapis.com/css?family=Fira+Mono|Roboto+Mono:400,300' rel='stylesheet' type='text/css'>
<style>
/* how do I CSS */
html, body {
height: 100%;
margin: 0 auto;
font-family: 'Roboto Mono';
}
body {
width: 80%;
display: flex;
flex-flow: column;
}
header {
text-align: center;
font-family: 'Roboto Mono';
font-weight: 300;
font-size: 24px;
}
footer {
min-height: 35px;
display: flex;
justify-content: center;
}
.footer, a, p {
display: inline-block;
align-self: flex-end;
font-weight: 300;
color: #555;
margin-bottom: 0px;
}
section, form {
height: 100%;
display: flex;
flex-direction: column;
}
input, select, textarea, div, label {
margin: 5px 0px;
}
.input-box-container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
margin: 0 0;
}
label {
font-size: 12px;
font-weight: 400;
}
textarea {
height: 100%;
resize: none;
border: #ccc 1px solid;
outline: none;
padding: 5px 5px;
}
</style>
@if($js)
<script>
window.onload = function() {
document.querySelector("textarea").addEventListener('keydown',function(e) {
if(e.keyCode === 9) { //tab
var start = this.selectionStart;
var end = this.selectionEnd;
var target = e.target;
var value = target.value;
target.value = value.substring(0, start)
+ "\t"
+ value.substring(end);
this.selectionStart = this.selectionEnd = start + 1;
e.preventDefault();
}
},false);
};
</script>
@endif
</head>
<body>
<header>pastethingy</header>
<section>
<form action="/paste" method="post">
<div class="input-box-container">
<div>
<label for="language">Language:</label>
<select id="language" name="language">
<option value="text">Text</option>
<option value="c">C</option>
<option value="d">D</option>
<option value="fish">Fish</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="php">PHP</option>
<option value="irc">IRC logs</option>
<option value="perl">Perl</option>
<option value="python3">Python 3</option>
</select>
</div>
<div>
<label for="available_at">Available at:</label>
<input id="available_at" name="available_at" value="{{ Carbon\Carbon::now()->format('Y-m-d H:i') }}" type="text">
</div>
<div>
<label for="expire_after">Expire:</label>
<select id="expire_after" name="expire_after">
<option value="never">Never</option>
<option value="10">After 10 seconds</option>
<option value="60">After 1 minute</option>
<option value="180">After 3 minutes</option>
<option value="300">After 5 minutes</option>
<option value="600">After 10 minutes</option>
<option value="1800">After 30 minutes</option>
<option value="3600">After 1 hour</option>
<option value="43200">After 12 hours</option>
<option value="86400">After 1 day</option>
<option value="604800">After 1 week</option>
<option value="1209600">After 2 weeks</option>
<option value="2635200">After 1 month</option>
<option value="15811200">After 6 months</option>
<option value="31557600">After 1 year</option>
</select>
</div>
</div>
<textarea name="content"></textarea>
<input type="submit" value="Paste">
<input type="hidden" name="redirect" value="1">
</form>
</section>
<footer>
<div class="footer">
@if($js)
<a href="/">No JS version</a>
@else
<a href="/?js=1">Tab key support (requires JS)</a>
@endif
<p>&middot; Dates and times are UTC.</p>
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ $id }} &middot; pastethingy</title>
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">
<style>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
display: table;
font-weight: 100;
font-family: 'Lato';
}
.container {
display: table-cell;
}
.content {
display: inline-block;
}
.title {
text-align: center;
font-size: 96px;
}
</style>
<link href="/pygments.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="content">
<div class="title">pastethingy</div>
<div class="paste">
{!! $content !!}
</div>
</div>
</div>
</body>
</html>