initial commit

This commit is contained in:
Niklas 2021-02-05 02:09:44 +01:00
commit d2db386693
18 changed files with 12340 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}

27
Dockerfile Normal file
View File

@ -0,0 +1,27 @@
FROM node:15 as build
WORKDIR /build
COPY public ./public
COPY src ./src
COPY package.json .
COPY yarn.lock .
COPY tsconfig.json .
RUN yarn install
RUN yarn build
FROM nginx
WORKDIR /app
COPY --from=build /build/build ./
COPY nginx.conf /etc/nginx/nginx.conf.template
COPY docker-entrypoint.sh /
EXPOSE 80
ENTRYPOINT /docker-entrypoint.sh

0
README.md Normal file
View File

3
build-docker.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
sudo docker build -t docker.kapelle.org/ncpb .

8
docker-compose.yml Normal file
View File

@ -0,0 +1,8 @@
version: "3"
services:
pb:
build: .
ports:
- "8080:80"
environment:
- ENDPOINT=https://your.nextcloud.org/

5
docker-entrypoint.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env sh
set -e
export DOLLAR='$'
envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
nginx -g 'daemon off;'

20
nginx.conf Normal file
View File

@ -0,0 +1,20 @@
events {}
http {
include mime.types;
server {
root /app;
listen 80;
index index.html;
location / {
try_files ${DOLLAR}uri /index.html;
}
location = /api/endpoint {
return 200 '${ENDPOINT}';
}
}
}

42
package.json Normal file
View File

@ -0,0 +1,42 @@
{
"name": "ncpb",
"version": "0.1.0",
"private": true,
"dependencies": {
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-copy-to-clipboard": "^5.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-syntax-highlighter": "^13.5.0",
"react": "^17.0.1",
"react-copy-to-clipboard": "^5.0.3",
"react-dom": "^17.0.1",
"react-scripts": "4.0.2",
"react-syntax-highlighter": "^15.4.3",
"typescript": "^4.1.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

12
public/index.html Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pastebin</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

101
src/App.tsx Normal file
View File

@ -0,0 +1,101 @@
import React, { useEffect, useState } from "react";
import CopyToClipboard from "react-copy-to-clipboard";
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import style from "react-syntax-highlighter/dist/cjs/styles/prism/vsc-dark-plus"
import cutomStyle from "./customStyle";
import getLangFromFilename from "./getLangFromFilename";
interface Props {
shareID: string;
}
const filenameRegex = /filename\*?=['"]?(?:UTF-\d['"]*)?([^;\r\n"']*)['"]?;?/gi;
function parseFilename(headers: Headers): string{
const raw = headers.get("content-disposition");
if (raw == null) {
return ""
}
let m;
while ((m = filenameRegex.exec(raw)) !== null) {
// Return the first match that we got
return m[1];
}
return "";
}
function App(props: Props) {
const [content,setContent] = useState<string>("");
const [title,setTitle] = useState<string>("");
const [lang,setLang] = useState<string>("text");
const [endpoint,setEndpoint] = useState<string>("");
useEffect(()=>{
(async () =>{
setEndpoint(await (await fetch("/api/endpoint")).text());
})()
},[])
useEffect(()=>{
(async ()=>{
if (!endpoint){
// Still loading endpoint
return
}
const response = await fetch(`${endpoint}/index.php/s/${props.shareID}/download`);
if (response.status === 404){
// File not found
// TODO display error
return;
}
const contentLength = parseInt(response.headers.get("content-length")!,10);
const filename = parseFilename(response.headers);
setTitle(filename);
document.title = filename;
setLang(getLangFromFilename(filename) || "text")
if (contentLength <= 20000) {
const text = await response.text()
setContent(text);
}else{
// TODO display error
}
})()
},[props.shareID,endpoint])
function downloadClick() {
window.open(`${endpoint}/index.php/s/${props.shareID}/download`, "_self");
}
return (
<div className="fileContainer">
<div className="headerContainer">
<span className="fileTitle">{title}</span>
<div className="buttonContainer">
<CopyToClipboard text={content}>
<button className="titleButton">Copy</button>
</CopyToClipboard>
<button className="titleButton" onClick={downloadClick}>Download</button>
</div>
</div>
<SyntaxHighlighter
customStyle={cutomStyle}
showLineNumbers={true}
style={style}
wrapLongLines={true}
language={lang}
>
{content}
</SyntaxHighlighter>
</div>
);
}
export default App;

5
src/customStyle.ts Normal file
View File

@ -0,0 +1,5 @@
const cutomStyle = {
"backgroundColor": "#0d1117"
}
export default cutomStyle;

486
src/getLangFromFilename.ts Normal file
View File

@ -0,0 +1,486 @@
export default function getLangFromFilename(filename: string): string {
let extension: string;
try {
const filenameParts = filename.split(".");
extension = filenameParts[filenameParts.length - 1].toLocaleLowerCase();
} catch (err) {
return "text";
}
// bases on https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_PRISM.MD
switch (extension) {
case "abap":
return "abap";
// case "":
// return "abnf";
// case "":
// return "actionscript";
// case "":
// return "ada";
// case "":
// return "agda";
// case "":
// return "al";
// case "":
// return "antlr4";
// case "":
// return "apacheconf";
// case "":
// return "apl";
// case "":
// return "applescript";
// case "":
// return "aql";
// case "":
// return "arduino";
// case "":
// return "arff";
// case "":
// return "asciidoc";
// case "":
// return "asm6502";
// case "":
// return "aspnet";
// case "":
// return "autohotkey";
// case "":
// return "autoit";
case "sh":
return "bash";
// case "":
// return "basic";
case "bat":
return "batch";
case "":
return "bbcode";
// case "":
// return "birb";
// case "":
// return "bison";
// case "":
// return "bnf";
case "bf":
return "brainfuck";
// case "":
// return "brightscript";
// case "":
// return "bro";
// case "":
// return "bsl";
case "c":
return "c";
// case "":
// return "cil";
// case "":
// return "clike";
// case "":
// return "clojure";
// case "":
// return "cmake";
// case "":
// return "coffeescript";
// case "":
// return "concurnas";
case "cpp":
return "cpp";
// case "":
// return "crystal";
case "cs":
return "csharp";
// case "":
// return "csp";
// case "":
// return "cssExtras (css-extras)";
case "css":
return "css";
// case "":
// return "cypher";
// case "":
// return "d";
// case "":
// return "dart";
// case "":
// return "dax";
// case "":
// return "dhall";
// case "":
// return "diff";
// case "":
// return "django";
// case "":
// return "dnsZoneFile (dns-zone-file)";
// case "":
// return "docker";
// case "":
// return "ebnf";
// case "":
// return "editorconfig";
// case "":
// return "eiffel";
// case "":
// return "ejs";
// case "":
// return "elixir";
// case "":
// return "elm";
// case "":
// return "erb";
// case "":
// return "erlang";
// case "":
// return "etlua";
// case "":
// return "excelFormula (excel-formula)";
// case "":
// return "factor";
// case "":
// return "firestoreSecurityRules (firestore-security-rules)";
// case "":
// return "flow";
// case "":
// return "fortran";
// case "":
// return "fsharp";
// case "":
// return "ftl";
// case "":
// return "gcode";
// case "":
// return "gdscript";
// case "":
// return "gedcom";
// case "":
// return "gherkin";
// case "":
// return "git";
// case "":
// return "glsl";
// case "":
// return "gml";
case "go":
return "go";
// case "":
// return "graphql";
// case "":
// return "groovy";
// case "":
// return "haml";
// case "":
// return "handlebars";
case "hs":
return "haskell";
// case "":
// return "haxe";
// case "":
// return "hcl";
// case "":
// return "hlsl";
// case "":
// return "hpkp";
// case "":
// return "hsts";
// case "":
// return "http";
// case "":
// return "ichigojam";
// case "":
// return "icon";
// case "":
// return "iecst";
// case "":
// return "ignore";
// case "":
// return "inform7";
case "ini":
return "ini";
// case "":
// return "io";
// case "":
// return "j";
case "java":
return "java";
// case "":
// return "javadoc";
// case "":
// return "javadoclike";
case "js":
return "javascript";
// case "":
// return "javastacktrace";
// case "":
// return "jolie";
// case "":
// return "jq";
// case "":
// return "jsExtras (js-extras)";
// case "":
// return "jsTemplates (js-templates)";
// case "":
// return "jsdoc";
case "json":
return "json";
// case "":
// return "json5";
// case "":
// return "jsonp";
// case "":
// return "jsstacktrace";
case "jsx":
return "jsx";
// case "":
// return "julia";
// case "":
// return "keyman";
// case "":
// return "kotlin";
case "tex":
return "latex";
// case "":
// return "latte";
// case "":
// return "less";
// case "":
// return "lilypond";
// case "":
// return "liquid";
// case "":
// return "lisp";
// case "":
// return "livescript";
// case "":
// return "llvm";
// case "":
// return "lolcode";
case "lua":
return "lua";
// case "":
// return "makefile";
case "md":
return "markdown";
// case "":
// return "markupTemplating (markup-templating)";
// case "":
// return "markup";
// case "":
// return "matlab";
// case "":
// return "mel";
// case "":
// return "mizar";
// case "":
// return "mongodb";
// case "":
// return "monkey";
// case "":
// return "moonscript";
// case "":
// return "n1ql";
// case "":
// return "n4js";
// case "":
// return "nand2tetrisHdl (nand2tetris-hdl)";
// case "":
// return "naniscript";
// case "":
// return "nasm";
// case "":
// return "neon";
// case "":
// return "nginx";
// case "":
// return "nim";
// case "":
// return "nix";
// case "":
// return "nsis";
// case "":
// return "objectivec";
// case "":
// return "ocaml";
// case "":
// return "opencl";
// case "":
// return "oz";
// case "":
// return "parigp";
// case "":
// return "parser";
// case "":
// return "pascal";
// case "":
// return "pascaligo";
// case "":
// return "pcaxis";
// case "":
// return "peoplecode";
// case "":
// return "perl";
// case "":
// return "phpExtras (php-extras)";
case "php":
return "php";
// case "":
// return "phpdoc";
// case "":
// return "plsql";
// case "":
// return "powerquery";
// case "":
// return "powershell";
// case "":
// return "processing";
// case "":
// return "prolog";
// case "":
// return "properties";
// case "":
// return "protobuf";
case "pug":
return "pug";
// case "":
// return "puppet";
// case "":
// return "pure";
// case "":
// return "purebasic";
// case "":
// return "purescript";
case "py":
return "python";
// case "":
// return "q";
// case "":
// return "qml";
// case "":
// return "qore";
// case "":
// return "r";
// case "":
// return "racket";
// case "":
// return "reason";
// case "":
// return "regex";
// case "":
// return "renpy";
// case "":
// return "rest";
// case "":
// return "rip";
// case "":
// return "roboconf";
// case "":
// return "robotframework";
// case "":
// return "ruby";
case "rs":
return "rust";
// case "":
// return "sas";
// case "":
// return "sass";
// case "":
// return "scala";
// case "":
// return "scheme";
case "scss":
return "scss";
// case "":
// return "shellSession (shell-session)";
// case "":
// return "smali";
// case "":
// return "smalltalk";
// case "":
// return "smarty";
// case "":
// return "sml";
// case "":
// return "solidity";
// case "":
// return "solutionFile (solution-file)";
// case "":
// return "soy";
// case "":
// return "sparql";
// case "":
// return "splunkSpl (splunk-spl)";
case "sqf":
return "sqf";
case "sql":
return "sql";
// case "":
// return "stan";
// case "":
// return "stylus";
// case "":
// return "swift";
// case "":
// return "t4Cs (t4-cs)";
// case "":
// return "t4Templating (t4-templating)";
// case "":
// return "t4Vb (t4-vb)";
// case "":
// return "tap";
// case "":
// return "tcl";
// case "":
// return "textile";
case "toml":
return "toml";
case "tsx":
return "tsx";
// case "":
// return "tt2";
// case "":
// return "turtle";
// case "":
// return "twig";
case "ts":
return "typescript";
// case "":
// return "typoscript";
// case "":
// return "unrealscript";
// case "":
// return "vala";
// case "":
// return "vbnet";
// case "":
// return "velocity";
// case "":
// return "verilog";
// case "":
// return "vhdl";
// case "":
// return "vim";
// case "":
// return "visualBasic (visual-basic)";
// case "":
// return "warpscript";
// case "":
// return "wasm";
// case "":
// return "wiki";
// case "":
// return "xeora";
// case "":
// return "xmlDoc (xml-doc)";
// case "":
// return "xojo";
// case "":
// return "xquery";
case "yaml":
case "yml":
return "yaml";
// case "":
// return "yang";
// case "":
// return "zig";
default:
return "text"
}
}

15
src/index.tsx Normal file
View File

@ -0,0 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import "./style.css"
const shareID = new URL(window.location.href).pathname.substr(1);
ReactDOM.render(
<React.StrictMode>
<App
shareID={shareID}
/>
</React.StrictMode>,
document.getElementById('root')
);

1
src/react-app-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="react-scripts" />

57
src/style.css Normal file
View File

@ -0,0 +1,57 @@
.fileContainer{
margin-top: 4rem;
margin-right: auto;
margin-left: auto;
border-width: 2px;
border-color: #1f6feb;
border-style: solid;
border-radius: 5px;
max-width: 60rem;
}
.headerContainer{
font-size: larger;
font-family: sans-serif;
color: #58a6ff;
padding-left: 2rem;
padding-right: 2rem;
padding-bottom: 2rem;
padding-top: 1rem;
border-bottom: solid 1px #1f6feb;
}
.fileTitle{
float: left;
}
.buttonContainer{
float: right;
}
.titleButton{
border: none;
border-radius: 2px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: small;
margin-left: 1em;
background-color: #1f6feb;
color: white;
}
/* Not the best soution but it works */
/* https://github.com/react-syntax-highlighter/react-syntax-highlighter/issues/347 */
.linenumber {
color: #50545b !important;
}
body {
background-color: #0d1117;
}

26
tsconfig.json Normal file
View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}

11506
yarn.lock Normal file

File diff suppressed because it is too large Load Diff