Browse Source

Integrated main templates and started designing new view mode switch, noted TODOs

main
Diane 1 year ago
parent
commit
125ade91b4
No known key found for this signature in database GPG Key ID: B13153D92467FCC1
  1. 4
      .gitignore
  2. 17
      css/style.css
  3. 10
      handlers.go
  4. 1
      static/.gitignore
  5. 1
      static/highlight.css
  6. 3
      static/highlight.min.js
  7. 42
      static/markdown.css
  8. 349
      static/normalize.css
  9. BIN
      static/paste.kra
  10. BIN
      static/paste.png
  11. 174
      static/style.css
  12. 188
      templates/about.html
  13. 69
      templates/homepage.html
  14. 24
      templates/markdown.html
  15. 37
      templates/partials.html
  16. 32
      templates/show.html
  17. 5
      todo.txt

4
.gitignore

@ -4,5 +4,7 @@ build/
*.min.css
node_modules/
# Configuration files, binaries etc.
paste*
paste
paste.exe
build.css
*.toml

17
css/style.css

@ -1,17 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
select.h-full {
height: 40px;
}
h1:before {
content: '# ';
}
h2:before {
content: '## ';
}
.bg-theme {
background-color: #23241f;
}

10
handlers.go

@ -28,9 +28,7 @@ type Content struct {
// Those following string fields are the paste in its different view modes (raw, view, markdown, etc.)
// on a URL-prefix-basis, e.g. View may contain `/s/<code>`, raw would contain `/r/<code>`,
// and md would contain `/md/<code>`
View string
Raw string
Md string
Code string
OriginalCommand PasteSubmitCommand
}
@ -214,8 +212,7 @@ func (h Handlers) handleShowPaste(w http.ResponseWriter, req *http.Request) {
if ok, res := h.handlePasteRetrieval(w, req, key); ok {
ErrIf(h.Templates.ExecuteTemplate(w, "show", &Content{
Value: res,
Raw: "/r/" + key,
Md: "/md/" + key,
Code: key,
}))
}
}
@ -237,8 +234,7 @@ func (h Handlers) HandleShowMarkdown(w http.ResponseWriter, req *http.Request) {
if ok, res := h.handlePasteRetrieval(w, req, key); ok {
ErrIf(h.Templates.ExecuteTemplate(w, "markdown", &Content{
Value: res,
Raw: "/r/" + key,
View: "/s/" + key,
Code: key,
}))
}
}

1
static/.gitignore

@ -1 +0,0 @@
style.css

1
static/highlight.css

@ -0,0 +1 @@
.hljs{display:block;overflow-x:auto;padding:.5em;color:#383a42;background:#fafafa}.hljs-comment,.hljs-quote{color:#a0a1a7;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e45649}.hljs-literal{color:#0184bb}.hljs-addition,.hljs-attribute,.hljs-meta-string,.hljs-regexp,.hljs-string{color:#50a14f}.hljs-built_in,.hljs-class .hljs-title{color:#c18401}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#4078f2}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}

3
static/highlight.min.js
File diff suppressed because it is too large
View File

42
static/markdown.css

@ -1,14 +1,4 @@
/* markdown-renderer-specific style rules */
main {
margin: 2em;
}
@media screen and (min-width: 720px) {
main {
margin: 2em auto;
width: 700px;
}
}
pre > code {
display: block;
}
@ -19,38 +9,6 @@ pre {
overflow: auto;
}
h1:before,
h2:before,
h3:before,
h4:before,
h5:before,
h6:before {
content: '';
}
main a {
color: #4299e1;
}
h1 {
font-size: 3rem;
}
h2 {
font-size: 2.25rem;
}
h3 {
font-size: 1.875rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1.125rem;
}

349
static/normalize.css

@ -0,0 +1,349 @@
/*! normalize.assets v8.0.1 | MIT License | github.com/necolas/normalize.assets */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

BIN
static/paste.kra

BIN
static/paste.png

After

Width: 1000  |  Height: 1000  |  Size: 9.7 KiB

174
static/style.css

@ -0,0 +1,174 @@
:root {
--foreground: black;
--primary: #55CDFC;
--primary-darker: #00ADF0;
--secondary: #F7A8B8;
--shadow: #ddd;
--margin: .125rem;
--padding: .5rem;
--font: 1.2rem;
}
* {
box-sizing: border-box;
}
header * {
margin: 0;
list-style-type: none;
padding: 0;
}
header > nav > ul > li {
padding: 0.2em 0;
}
body {
border-top: 6px solid var(--secondary);
padding: 2em;
font-family: sans-serif, sans-serif;
}
blockquote {
margin: 0;
padding: 1em 2em;
border-left: 6px solid var(--secondary);
}
hr {
border: 1px solid var(--primary);
}
p, li {
font-size: 1.2rem;
}
a {
color: var(--primary);
font-weight: bold;
text-decoration: underline var(--primary);
}
a:hover, a:focus {
#border: var(--margin) solid var(--shadow);
text-decoration: underline var(--secondary) var(--margin);
}
nav a {
text-decoration: none;
}
.brand {
color: var(--foreground);
}
.spaced {
display: flex;
justify-content: space-between;
}
.bot-aligned {
align-items: flex-end;
}
.mid-aligned {
align-items: center;
}
@media screen and (min-width: 400px) {
body {
padding-left: 4em;
padding-right: 4em;
}
header {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
header > h1 {
margin: 0;
}
header > nav > ul {
list-style-type: none;
}
header > nav > ul > li {
display: inline-block;
}
header > nav > ul > li:not(:last-of-type):after {
content: ' | ';
}
}
.fullsize {
display: block;
width: 100%;
}
.center {
text-align: center;
}
input, textarea, button, select {
border: var(--margin) solid var(--shadow);
margin: var(--margin);
padding: var(--padding);
border-radius: 0;
}
input:focus, textarea:focus, button:focus, select:focus {
border-color: var(--primary);
}
input:invalid, textarea:invalid, button:invalid, select:invalid {
border-color: var(--secondary);
}
fieldset {
padding: 0;
margin: 0;
border: 0;
}
label {
font-weight: bold;
}
.primary {
border-color: var(--primary-darker);
background-color: var(--primary);
}
.primary:hover, .primary:focus {
border-color: var(--primary);
background-color: var(--primary-darker);
}
.code {
display: flex;
font-family: monospace, monospace;
}
.code > .lineno {
padding-right: var(--padding);
margin-right: var(--margin);
border-right: 2px solid var(--primary);
}
.code > .content {
overflow-x: auto;
flex: 1;
}
.code > code {
background-color: unset;
font-size: var(--font);
}
.bold {
font-weight: bold;
}

188
templates/about.html

@ -2,98 +2,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{template "header"}}
{{template "head"}}
<title>About Paste</title>
</head>
<body class="bg-gray-900 text-white">
<header class="8 bg-gray-200 flex flex-wrap justify-between items-center p-2">
{{template "nav"}}
</header>
<main class="container mx-auto px-8 pb-8">
<h1 class="text-xl py-8">About paste</h1>
<p>
Paste is a FOSS ephemeral pastebin tool, made to be simple,
lightweight, and without any tracker or javascript.
</p>
<p>
Ephemeral means it does not store <i>anything</i> on a form of
persistent storage (like a HDD or a SSD), but instead only keeps
it in RAM for the selected duration (between 1 and 24 hours as of now).
</p>
<p>
FOSS means that the source-code is available for free for anyone
who might want to self-host it, or extend it
(<a href="https://gitlab.com/Artemix/paste" class="underline text-blue-500 font-medium">Source-code</a>).
</p>
<h1 class="text-xl py-8">Privacy Policy</h1>
<p>
As general logging, we only collect your IP.
This is solely for cases where someone tries to abuse our services,
to be able to block them out.
</p>
<h2 class="text-lg py-6">Paste storing</h2>
<p>
Every paste is stored in ephemeral memory (RAM, through Redis configured
to not persist anything), with an auto-expiry set to, at maximum, 24 hours.
</p>
<p>
Following that, we don't persist anything, and once the expiry time
is passed, or the server (/ redis instance) rebooted, everything is
forgotten.
</p>
<h2 class="text-lg py-6">Analytics</h2>
<p>
Except for the possible exception above, we don't collect anything.
No, really. The person behind this is very privacy-conscious, so
they'll always try to only keep the necessary data, and <i>nothing more</i>.
No ad, no tracker in any form, period.
</p>
<h2 class="text-lg py-6">Security</h2>
<p>
We employ good methods to keep data secure. Not digging into details,
but the usual stuff, like a good firewall, monitoring system, and no
apparent openflow.
</p>
<p>
There's only one person who's technically authorized to be on the
hosting servers, so only one person should be able to have access.
</p>
<p>
Note that we're not saying that our servers and services are unbreakable
and perfect, but that we try to do our very best to prevent any
possibility for such incidents to occur.
</p>
<h2 class="text-lg py-6">Incident or vulnerability disclosure</h2>
<body>
{{template "header"}}
<hr>
<main>
<section>
<h1>About Paste</h1>
<p>Paste is a FOSS ephemeral pastebin tool, made to be simple, lightweight, and without any tracker or
javascript.<br/>
Ephemeral means it doesn't store anything in long-term storage mechanisms such as a storage database or
the file system, but instead keeps everything in volatile and expirable storage (for the selected
duration, technically for a maximum of 24 hours).</p>
<article>
<h2>Financial contributions</h2>
<p>Paste is a completely free and open service, with intent to keep it as so, but operating it still
costs.</p>
<p>If you are tech-savvy, your contributions for improvements, bug-fixes, new feature proposals, etc.,
are most welcome, but if you do not want to directly contribute to the software, <em>financial
contributions</em> are gladly received on <a href="https://www.buymeacoffee.com/Artemis">the
donation page</a>!</p>
</section>
<hr/>
<section>
<h1>Privacy policy</h1>
<p>As general logging, we only collect your IP. This is solely for cases where someone tries to abuse our
services, to be able to block them out.</p>
<article>
<h2>Paste storing</h2>
<p>Every paste is stored in volatile memory (through Redis) with an auto-expiry set to, <em>at
maximum</em>, 24 hours after insertion.<br/>
Redis is configured to keep regular memory snapshots so, if the server crashes or needs an urgent
restart, you will not lose your pastes.<br/>
The snapshots are not persisted, or backuped, so once a paste expires, it will disappear from the
snapshots.</p>
</article>
<article>
<h2>Analytics</h2>
<p>Except for the possible exception above, we don't collect anything.
No, really.
The person behind this is very privacy-conscious, so they'll always try to only keep the necessary
data, and nothing more.
No ad, no tracker in any form, period.</p>
</article>
<article>
<h2>Security</h2>
<p>
We employ good methods to keep data secure. Not digging into details,
but the usual stuff, like a good firewall, monitoring system, and no
apparent openflow.
</p>
<p>
There's only one person who's technically authorized to be on the
hosting servers, so only one person should be able to have access.
</p>
<p>
Note that we're not saying that our servers and services are unbreakable
and perfect, but that we try to do our very best to prevent any
possibility for such incidents to occur.
</p>
</article>
<article>
<h2>Incident or vulnerability disclosure</h2>
<p>
If you managed to encounter an incident or a vulnerability in our
infrastructure, we'd gladly receive your feedback and alerts by
e-mail at <a href="mailto:alert+paste@artemix.org">alert+paste@artemix.org</a>.
</p>
<p>
Responsible disclosure will allow us to recover and fix those
incidents without much risk, allowing us to provide you our services
with as much quality as we can manage to.
</p>
</article>
</section>
</main>
<p>
If you managed to encounter an incident or a vulnerability in our
infrastructure, we'd gladly receive your feedback and alerts by
e-mail at <code>alert[at]artemix[dot]org</code>.
</p>
<hr>
<footer class="center">
<p>
Responsible disclosure will allow us to recover and fix those
incidents without much risk, allowing us to provide you our services
with as much quality as we can manage to.
Made by <a href="#">Artemis</a>
- <a href="#">Source-code</a>
- <a href="#">Donate</a>
</p>
<p><i>Plus, you may receive a special mention or some small token of appreciation!</i></p>
</main>
</footer>
</body>
</html>
{{end}}

69
templates/homepage.html

@ -2,38 +2,51 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{template "header"}}
{{template "head"}}
<title>Paste</title>
</head>
<body class="bg-gray-900 text-white h-screen">
<main class="flex flex-col h-screen">
<header class="8 bg-gray-200 flex flex-wrap justify-between items-center p-2">
{{template "nav"}}
{{if .Error}}<p class="text-red-400 font-bold">{{.Error}}</p>{{end}}
<fieldset class="shadow-xl rounded bg-white text-black">
{{/* How to properly select the expected value here, in case of submit error */}}
<select name="time" id="time" class="h-full p-2 rounded-l" form="paster">
<option value="1h">1 hour</option>
<option value="6h">6 hours</option>
<option value="12h">12 hours</option>
<option value="24h" selected>1 day (24 hours)</option>
</select><button
type="submit"
form="paster"
class="p-2 bg-blue-400 text-white rounded-r">Store
</button>
<body>
{{template "header"}}
<hr>
<main>
<form method="post">
<fieldset>
<label for="paste">Your document</label>
<textarea required autofocus
id="paste"
name="paste"
class="fullsize"
rows="20"
placeholder="Paste your document here"></textarea>
</fieldset>
</header>
<form method="POST" id="paster" class="w-full flex-1">
<textarea
class="bg-gray-900 resize-none font-mono p-2 w-full h-full block"
name="paste"
id="paste"
rows="15"
required autofocus
placeholder="Enter your paste here"
spellcheck="false">{{if .OriginalCommand }}{{.OriginalCommand.Paste}}{{end}}</textarea>
<footer class="spaced">
<fieldset>
<label for="time">It will be stored for</label>
<select id="time" name="time">
<option value="1h">1 hour</option>
<option value="6h">6 hours</option>
<option value="12h">12 hours</option>
<option value="24h" selected>1 day (24 hours)</option>
</select>
</fieldset>
<button type="submit" class="primary">Store</button>
</footer>
</form>
</main>
<hr>
<footer class="center">
<p>
Made by <a href="https://www.artemix.org/">Artemis</a>
- <a href="https://git.sr.ht/~artemis/paste">Source-code</a>
- <a href="https://www.buymeacoffee.com/Artemis">Donate</a>
</p>
</footer>
</body>
</html>
{{end}}

24
templates/markdown.html

@ -2,25 +2,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{template "header"}}
<link rel="stylesheet" href="/static/markdown.css"/>
{{template "head"}}
<title>{{.Code}} - Paste</title>
<link rel="stylesheet" href="/static/markdown.css"/>
<link rel="stylesheet" href="/static/highlight.css"/>
<script src="/static/highlight.min.js" defer></script>
</head>
<body>
<header class="bg-gray-200 flex flex-wrap justify-between items-center p-2">
{{template "nav"}}
<fieldset class="shadow-xl bg-white text-black">
<a
href="{{.View}}"
class="p-2 bg-blue-400 hover:bg-blue-800 text-white rounded-l"
>Source view</a><a
href="{{.Raw}}"
class="p-2 bg-blue-400 hover:bg-blue-800 text-white rounded-r">Raw view</a>
</fieldset>
</header>
{{template "header"}}
{{template "view-mode"}}
<main>
{{.Value|markdown}}
{{.Value|markdown}}
</main>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlightingOnLoad());</script>
</body>
</html>
{{end}}

37
templates/partials.html

@ -1,13 +1,36 @@
{{define "header"}}
{{define "head"}}
<meta charset="UTF-8">
<title>Paste</title>
<link rel="stylesheet" href="/static/normalize.css"/>
<link rel="stylesheet" href="/static/style.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{{end}}
{{define "nav"}}
<nav class="text-black">
<a class="inline-block font-bold text-3xl pr-2" href="/">Paste</a>
<a href="/about" class="underline text-blue-500 font-medium">About</a>
</nav>
{{define "header"}}
<header>
<h1><a class=brand href="/">Paste</a></h1>
<nav>
<ul>
<li><a href="/">New paste</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
{{end}}
{{define "view-mode"}}
<hr>
<header class="spaced mid-aligned">
<div></div>
<form action="/change-mode">
<label for="">View mode: </label>
<select name="" id="">
<option value="">Source-code</option>
<option value="">Markdown</option>
<option value="">Raw</option>
</select>
<button type="submit">Change view</button>
</form>
</header>
{{end}}

32
templates/show.html

@ -2,32 +2,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{template "header"}}
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/monokai-sublime.min.css">
{{template "head"}}
<title>{{.Code}} - Paste</title>
<link rel="stylesheet" href="/static/highlight.css">
<script src="/static/highlight.min.js" defer></script>
</head>
<body class="bg-theme">
<header class="bg-gray-200 flex flex-wrap justify-between items-center p-2">
{{template "nav"}}
<fieldset class="shadow-xl bg-white text-black">
<a
href="{{.Md}}"
class="p-2 bg-blue-400 hover:bg-blue-800 text-white rounded-l"
>Markdown view</a><a
href="{{.Raw}}"
class="p-2 bg-blue-400 hover:bg-blue-800 text-white rounded-r">Raw view</a>
</fieldset>
</header>
<body>
{{template "header"}}
{{template "view-mode"}}
<main>
<pre class="flex">
<code class="text-right border-r-2 border-gray-800">{{.Value|lineno}}</code>
<code class="flex-1">{{.Value}}</code>
<pre class="code">
<code class="lineno">{{.Value|lineno}}</code>
<code class="content">{{.Value}}</code>
</pre>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlightingOnLoad());</script>
</body>
</html>
{{end}}

5
todo.txt

@ -0,0 +1,5 @@
text trimming on paste
uniformized 404 error page
server-side syntaxic coloration
mode changer
change routing system to use GET parameters and - as prefix
Loading…
Cancel
Save