Updates (very important to read)

Client-side CSS & JS files will now be processed with Gulp.
Gulp tasks are configured in gulpfile.js file.

CSS files will be optimized with postcss-preset-env, which will
auto-add vendor prefixes and convert any parts necessary for browsers
compatibility.
Afterwards they will be minified with cssnano.

JS files will be optimized with bublé,
likewise for browsers compatibility.
Afterwards they will be minified with terser.

Unprocessed CSS & JS files will now be located at src directory, while
the processed results will be located at dist directory.

Due to bublé, the JS files should now be compatible up to IE 11
at the minimum.
Previously the safe would not work in IE 11 due to extensive usage of
template literals.
Due to that as well, JS files in src directory will now extensively use
arrow functions for my personal comfort (as they will be converted too).

The server will use the processed files at dist directory by default.
If you want to rebuild the files by your own, you can run "yarn build".
Gulp is a development dependency, so make sure you have installed all
development dependencies (e.i. NOT using "yarn install --production").

---

yarn lint -> gulp lint

yarn build -> gulp default

yarn watch -> gulp watch

yarn develop -> env NODE_ENV=development yarn watch

---

Fixed not being able to demote staff into normal users.

/api/token/verify will no longer respond with 401 HTTP error code,
unless an error occurred (which will be 500 HTTP error code).

Fixed /nojs route not displaying file's original name when a duplicate
is found on the server.

Removed is-breeze CSS class name, in favor of Bulma's is-info.

Removed custom styling from auth page, in favor of global styling.

Removed all usage of style HTML attribute in favor of CSS classes.

Renamed js/s/ to js/misc/.

Use loading spinners on dashboard's sidebar menus.

Disable all other sidebar menus when something is loading.

Changed title HTML attribute of disabled control buttons in
uploads & users list.

Hid checkboxes and WIP controls from users list.

Better error messages handling.
Especially homepage will now support CF's HTTP error codes.

Updated various icons.
Also, added fontello config file at public/libs/fontello/config.json.
This should let you edit them more easily with fontello.

Use Gatsby icon for my blog's link in homepage's footer.

A bunch of other improvements here & there.
This commit is contained in:
Bobby Wibowo 2019-09-15 13:20:11 +07:00
parent f5445a639c
commit c9ba16e1d6
No known key found for this signature in database
GPG Key ID: 51C3A1E1E22D26CF
78 changed files with 4112 additions and 975 deletions

7
.browserslistrc Normal file
View File

@ -0,0 +1,7 @@
# Browserslist's defaults (supports IE 11 at the minimum)
# https://github.com/browserslist/browserslist#queries
> 0.5%
last 2 versions
Firefox ESR
not dead

View File

@ -1 +1,3 @@
**/*.min.js
dist/js/*
public/libs/*

74
.gitignore vendored
View File

@ -1,17 +1,63 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Dependency directories
node_modules/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# npm's package-lock (if npm is accidentally used)
package-lock.json
# vscode's workspace settings
/.vscode
# Configuration file
/config.js
# Database
/database/db
# Uploads directory
/uploads
# Custom pages directory
/pages/custom
# User files
.DS_Store
.nvmrc
.vscode
!.gitkeep
node_modules
uploads
logs
database/db
config.js
start.json
npm-debug.log
pages/custom/**
migrate.js
yarn-error.log
package-lock.json
public/render/**/original
public/render/**/wip
/start.json
/migrate.js
# User directories (renders)
/public/render/**/original
/public/render/**/wip

2
.stylelintignore Normal file
View File

@ -0,0 +1,2 @@
dist/css/*
public/libs/*

View File

@ -1,13 +1,13 @@
const config = require('./../config')
const db = require('knex')(config.database)
const EventEmitter = require('events')
const fs = require('fs')
const logger = require('./../logger')
const path = require('path')
const paths = require('./pathsController')
const randomstring = require('randomstring')
const utils = require('./utilsController')
const Zip = require('jszip')
const paths = require('./pathsController')
const utils = require('./utilsController')
const config = require('./../config')
const logger = require('./../logger')
const db = require('knex')(config.database)
const self = {
onHold: new Set()

View File

@ -1,12 +1,12 @@
const { promisify } = require('util')
const bcrypt = require('bcrypt')
const config = require('./../config')
const db = require('knex')(config.database)
const logger = require('./../logger')
const perms = require('./permissionController')
const randomstring = require('randomstring')
const perms = require('./permissionController')
const tokens = require('./tokenController')
const utils = require('./utilsController')
const config = require('./../config')
const logger = require('./../logger')
const db = require('knex')(config.database)
const self = {
compare: promisify(bcrypt.compare),
@ -152,7 +152,7 @@ self.editUser = async (req, res, next) => {
update.enabled = Boolean(req.body.enabled)
if (req.body.group !== undefined) {
update.permission = perms.permissions[req.body.group] || target.permission
update.permission = perms.permissions[req.body.group]
if (typeof update.permission !== 'number' || update.permission < 0)
update.permission = target.permission
}

View File

@ -1,8 +1,8 @@
const { promisify } = require('util')
const config = require('./../config')
const fs = require('fs')
const logger = require('./../logger')
const path = require('path')
const config = require('./../config')
const logger = require('./../logger')
const self = {}
@ -33,6 +33,7 @@ self.thumbPlaceholder = path.resolve(config.uploads.generateThumbs.placeholder |
self.logs = path.resolve(config.logsFolder)
self.customPages = path.resolve('pages/custom')
self.dist = path.resolve('dist')
self.public = path.resolve('public')
self.errorRoot = path.resolve(config.errorPages.rootDir)
@ -47,33 +48,28 @@ const verify = [
]
self.init = async () => {
try {
for (const p of verify)
try {
await self.access(p)
} catch (err) {
if (err.code !== 'ENOENT') {
logger.error(err)
} else {
const mkdir = await self.mkdir(p)
if (mkdir)
logger.log(`Created directory: ${p}`)
}
// Check & create directories
for (const p of verify)
try {
await self.access(p)
} catch (err) {
if (err.code !== 'ENOENT') {
throw err
} else {
const mkdir = await self.mkdir(p)
if (mkdir)
logger.log(`Created directory: ${p}`)
}
// Purge chunks directory
const uuidDirs = await self.readdir(self.chunks)
for (const uuid of uuidDirs) {
const root = path.join(self.chunks, uuid)
const chunks = await self.readdir(root)
for (const chunk of chunks)
await self.unlink(path.join(root, chunk))
await self.rmdir(root)
}
self.verified = true
} catch (error) {
logger.error(error)
// Purge any leftover in chunks directory
const uuidDirs = await self.readdir(self.chunks)
for (const uuid of uuidDirs) {
const root = path.join(self.chunks, uuid)
const chunks = await self.readdir(root)
for (const chunk of chunks)
await self.unlink(path.join(root, chunk))
await self.rmdir(root)
}
}

View File

@ -1,9 +1,9 @@
const config = require('./../config')
const db = require('knex')(config.database)
const logger = require('./../logger')
const perms = require('./permissionController')
const randomstring = require('randomstring')
const perms = require('./permissionController')
const utils = require('./utilsController')
const config = require('./../config')
const logger = require('./../logger')
const db = require('knex')(config.database)
const self = {
tokenLength: 64,
@ -41,7 +41,7 @@ self.verify = async (req, res, next) => {
: ''
if (!token)
return res.status(401).json({ success: false, description: 'No token provided.' })
return res.json({ success: false, description: 'No token provided.' })
try {
const user = await db.table('users')
@ -50,7 +50,7 @@ self.verify = async (req, res, next) => {
.first()
if (!user)
return res.status(401).json({ success: false, description: 'Invalid token.' })
return res.json({ success: false, description: 'Invalid token.' })
return res.json({
success: true,

View File

@ -1,15 +1,15 @@
const config = require('./../config')
const crypto = require('crypto')
const db = require('knex')(config.database)
const fetch = require('node-fetch')
const fs = require('fs')
const logger = require('./../logger')
const multer = require('multer')
const path = require('path')
const randomstring = require('randomstring')
const paths = require('./pathsController')
const perms = require('./permissionController')
const randomstring = require('randomstring')
const utils = require('./utilsController')
const config = require('./../config')
const logger = require('./../logger')
const db = require('knex')(config.database)
const self = {}
@ -563,6 +563,11 @@ self.storeFilesToDb = async (req, res, user, infoMap) => {
// Continue even when encountering errors
await utils.unlinkFile(info.data.filename).catch(logger.error)
// logger.log(`Unlinked ${info.data.filename} since a duplicate named ${dbFile.name} exists`)
// If on /nojs route, append original file name reported by client
if (req.path === '/nojs')
dbFile.original = info.data.originalname
exists.push(dbFile)
continue
}
@ -635,11 +640,11 @@ self.sendUploadResponse = async (req, res, result) => {
url: `${config.domain}/${file.name}`
}
// Add expiry date if a temporary upload
// If a temporary upload, add expiry date
if (file.expirydate)
map.expirydate = file.expirydate
// Add original name if on /nojs route
// If on /nojs route, add original name
if (req.path === '/nojs')
map.original = file.original

View File

@ -1,15 +1,15 @@
const { promisify } = require('util')
const { spawn } = require('child_process')
const config = require('./../config')
const db = require('knex')(config.database)
const fetch = require('node-fetch')
const ffmpeg = require('fluent-ffmpeg')
const logger = require('./../logger')
const path = require('path')
const paths = require('./pathsController')
const perms = require('./permissionController')
const sharp = require('sharp')
const si = require('systeminformation')
const paths = require('./pathsController')
const perms = require('./permissionController')
const config = require('./../config')
const logger = require('./../logger')
const db = require('knex')(config.database)
const self = {
clamd: {
@ -148,6 +148,18 @@ self.escape = (string) => {
: html
}
self.stripIndents = string => {
if (!string) return
const result = string.replace(/^[^\S\n]+/gm, '')
const match = result.match(/^[^\S\n]*(?=\S)/gm)
const indent = match && Math.min(...match.map(el => el.length))
if (indent) {
const regexp = new RegExp(`^.{${indent}}`, 'gm')
return result.replace(regexp, '')
}
return result
}
self.authorize = async (req, res) => {
// TODO: Improve usage of this function by the other APIs
const token = req.headers.token

View File

@ -1,6 +1,6 @@
const logger = require('./../logger')
const perms = require('./../controllers/permissionController')
const randomstring = require('randomstring')
const perms = require('./../controllers/permissionController')
const logger = require('./../logger')
// TODO: Auto-detect missing columns here
// That way we will no longer need the migration script

View File

@ -1,6 +1,6 @@
const perms = require('./../controllers/permissionController')
const config = require('./../config')
const db = require('knex')(config.database)
const perms = require('./../controllers/permissionController')
const map = {
files: {

2
dist/css/album.css vendored Normal file
View File

@ -0,0 +1,2 @@
.section{background:none}@media screen and (max-width:768px){.description{text-align:center}}
/*# sourceMappingURL=album.css.map */

1
dist/css/album.css.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["album.css"],"names":[],"mappings":"AAAA,SACE,eACF,CAEA,oCACE,aACE,iBACF,CACF","file":"album.css","sourcesContent":[".section {\n background: none\n}\n\n@media screen and (max-width: 768px) {\n .description {\n text-align: center\n }\n}\n"]}

2
dist/css/dashboard.css vendored Normal file
View File

@ -0,0 +1,2 @@
body{-webkit-animation:none;animation:none}#dashboard{-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}.section{background:none}.menu-list a{color:#3794d2}.menu-list a:hover{color:#60a8dc;background-color:#4d4d4d}.menu-list a.is-active{color:#eff0f1;background-color:#3794d2}.menu-list a[disabled]{color:#7a7a7a;cursor:not-allowed}.menu-list a[disabled]:hover{background:none}ul#albumsContainer{border-left:0;padding-left:0}ul#albumsContainer li{border-left:1px solid #898b8d;padding-left:.75em}#page.fade-in,ul#albumsContainer li{-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}.pagination{margin-bottom:1.25rem}.pagination a:not([disabled]){color:#eff0f1;border-color:#4d4d4d;background-color:#31363b}a.pagination-link:not(.is-current):hover,a.pagination-next:not([disabled]):hover,a.pagination-previous:not([disabled]):hover{color:#eff0f1;border-color:#60a8dc;background-color:#31363b}a.pagination-link.is-current{background-color:#3794d2;border-color:#3794d2}a.pagination-link.is-current:hover{border-color:#60a8dc}li[data-action=page-ellipsis]{cursor:pointer}.label{color:#bdc3c7}.menu-list li ul{border-left-color:#898b8d}.image-container .checkbox{position:absolute;top:.75rem;left:.75rem}.no-touch .image-container .checkbox{opacity:.5}.no-touch .image-container .controls,.no-touch .image-container .details{opacity:0}.no-touch .image-container:hover .checkbox,.no-touch .image-container:hover .controls,.no-touch .image-container:hover .details{opacity:1}#page{min-width:0}.table{color:#bdc3c7;background-color:#31363b;font-size:.75rem}.table.is-striped tbody tr:nth-child(2n),.table tr:hover{background:none}.table.is-striped tbody tr:hover,.table.is-striped tbody tr:nth-child(2n):hover,.tag{background-color:#4d4d4d}.table td,.table th{border:0;white-space:nowrap}.table th{color:#eff0f1;height:2.25em}.table thead td,.table thead th{color:#eff0f1;background-color:#ff3860}.table .cell-indent{padding-left:2.25em}.is-linethrough{text-decoration:line-through}#menu.is-loading li a{cursor:progress}#statistics tr :nth-child(2){min-width:50%}
/*# sourceMappingURL=dashboard.css.map */

1
dist/css/dashboard.css.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["dashboard.css"],"names":[],"mappings":"AAAA,KACE,sBAAc,CAAd,cACF,CAEA,WACE,mCAA4B,CAA5B,2BACF,CAEA,SACE,eACF,CAEA,aACE,aACF,CAEA,mBACE,aAAc,CACd,wBACF,CAEA,uBACE,aAAc,CACd,wBACF,CAEA,uBACE,aAAc,CACd,kBACF,CAEA,6BACE,eACF,CAEA,mBACE,aAAc,CACd,cACF,CAEA,sBACE,6BAA8B,CAC9B,kBAEF,CAEA,oCAHE,mCAA4B,CAA5B,2BAKF,CAEA,YACE,qBACF,CAEA,8BACE,aAAc,CACd,oBAAqB,CACrB,wBACF,CAEA,6HAGE,aAAc,CACd,oBAAqB,CACrB,wBACF,CAEA,6BACE,wBAAyB,CACzB,oBACF,CAEA,mCACE,oBACF,CAEA,8BACE,cACF,CAEA,OACE,aACF,CAEA,iBACE,yBACF,CAEA,2BACE,iBAAkB,CAClB,UAAY,CACZ,WACF,CAEA,qCACE,UACF,CAEA,yEAEE,SACF,CAEA,gIAGE,SACF,CAEA,MAEE,WACF,CAEA,OACE,aAAc,CACd,wBAAyB,CACzB,gBACF,CAEA,yDAEE,eACF,CAEA,qFAGE,wBACF,CAEA,oBAEE,QAAS,CACT,kBACF,CAEA,UACE,aAAc,CACd,aACF,CAEA,gCAEE,aAAc,CACd,wBACF,CAEA,oBACE,mBACF,CAEA,gBACE,4BACF,CAEA,sBACE,eACF,CAEA,6BACE,aACF","file":"dashboard.css","sourcesContent":["body {\n animation: none\n}\n\n#dashboard {\n animation: fadeInOpacity 0.5s\n}\n\n.section {\n background: none\n}\n\n.menu-list a {\n color: #3794d2\n}\n\n.menu-list a:hover {\n color: #60a8dc;\n background-color: #4d4d4d\n}\n\n.menu-list a.is-active {\n color: #eff0f1;\n background-color: #3794d2\n}\n\n.menu-list a[disabled] {\n color: #7a7a7a;\n cursor: not-allowed\n}\n\n.menu-list a[disabled]:hover {\n background: none\n}\n\nul#albumsContainer {\n border-left: 0;\n padding-left: 0\n}\n\nul#albumsContainer li {\n border-left: 1px solid #898b8d;\n padding-left: 0.75em;\n animation: fadeInOpacity 0.5s\n}\n\n#page.fade-in {\n animation: fadeInOpacity 0.5s\n}\n\n.pagination {\n margin-bottom: 1.25rem\n}\n\n.pagination a:not([disabled]) {\n color: #eff0f1;\n border-color: #4d4d4d;\n background-color: #31363b\n}\n\na.pagination-link:not(.is-current):hover,\na.pagination-next:not([disabled]):hover,\na.pagination-previous:not([disabled]):hover {\n color: #eff0f1;\n border-color: #60a8dc;\n background-color: #31363b\n}\n\na.pagination-link.is-current {\n background-color: #3794d2;\n border-color: #3794d2\n}\n\na.pagination-link.is-current:hover {\n border-color: #60a8dc\n}\n\nli[data-action=\"page-ellipsis\"] {\n cursor: pointer\n}\n\n.label {\n color: #bdc3c7\n}\n\n.menu-list li ul {\n border-left-color: #898b8d\n}\n\n.image-container .checkbox {\n position: absolute;\n top: 0.75rem;\n left: 0.75rem\n}\n\n.no-touch .image-container .checkbox {\n opacity: 0.5\n}\n\n.no-touch .image-container .controls,\n.no-touch .image-container .details {\n opacity: 0\n}\n\n.no-touch .image-container:hover .checkbox,\n.no-touch .image-container:hover .controls,\n.no-touch .image-container:hover .details {\n opacity: 1\n}\n\n#page {\n /* fix overflow issue with flex */\n min-width: 0\n}\n\n.table {\n color: #bdc3c7;\n background-color: #31363b;\n font-size: 0.75rem\n}\n\n.table tr:hover,\n.table.is-striped tbody tr:nth-child(2n) {\n background: none\n}\n\n.table.is-striped tbody tr:hover,\n.table.is-striped tbody tr:nth-child(2n):hover,\n.tag {\n background-color: #4d4d4d\n}\n\n.table td,\n.table th {\n border: 0;\n white-space: nowrap\n}\n\n.table th {\n color: #eff0f1;\n height: 2.25em\n}\n\n.table thead td,\n.table thead th {\n color: #eff0f1;\n background-color: #ff3860\n}\n\n.table .cell-indent {\n padding-left: 2.25em\n}\n\n.is-linethrough {\n text-decoration: line-through\n}\n\n#menu.is-loading li a {\n cursor: progress\n}\n\n#statistics tr *:nth-child(2) {\n min-width: 50%\n}\n"]}

2
dist/css/home.css vendored Normal file
View File

@ -0,0 +1,2 @@
#b{width:200px;height:200px;border-radius:100%;display:inline-block;margin-bottom:40px;vertical-align:top;-webkit-animation-delay:.5s;animation-delay:.5s;-webkit-animation-duration:1.5s;animation-duration:1.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:floatUp;animation-name:floatUp;-webkit-animation-timing-function:cubic-bezier(0,.71,.29,1);animation-timing-function:cubic-bezier(0,.71,.29,1);box-shadow:0 20px 60px rgba(10,10,10,.05),0 5px 10px rgba(10,10,10,.1),0 1px 1px rgba(10,10,10,.2)}#b img.logo{max-height:200px}#dropzone *{pointer-events:none}#panel,#tokenContainer{display:none}#maxSize{font-size:1rem}.dz-preview .dz-details{display:flex}.dz-preview .dz-details .dz-filename,.dz-preview .dz-details .dz-size{flex:1}.dz-preview .dz-error-mark,.dz-preview .dz-success-mark,.dz-preview img{display:none}@-webkit-keyframes floatUp{0%{opacity:0;box-shadow:0 0 0 rgba(10,10,10,0),0 0 0 rgba(10,10,10,0),0 0 0 rgba(10,10,10,0);transform:scale(.86)}25%{opacity:1}67%{box-shadow:0 0 0 rgba(10,10,10,0),0 5px 10px rgba(10,10,10,.1),0 1px 1px rgba(10,10,10,.2);transform:scale(1)}to{box-shadow:0 20px 60px rgba(10,10,10,.05),0 5px 10px rgba(10,10,10,.1),0 1px 1px rgba(10,10,10,.2);transform:scale(1)}}@keyframes floatUp{0%{opacity:0;box-shadow:0 0 0 rgba(10,10,10,0),0 0 0 rgba(10,10,10,0),0 0 0 rgba(10,10,10,0);transform:scale(.86)}25%{opacity:1}67%{box-shadow:0 0 0 rgba(10,10,10,0),0 5px 10px rgba(10,10,10,.1),0 1px 1px rgba(10,10,10,.2);transform:scale(1)}to{box-shadow:0 20px 60px rgba(10,10,10,.05),0 5px 10px rgba(10,10,10,.1),0 1px 1px rgba(10,10,10,.2);transform:scale(1)}}.uploads>div{-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s;margin:1rem}.uploads>div:first-child{margin-top:1.5rem}.uploads.nojs{margin-bottom:0}.uploads .field>.icon:not(.icon-block){color:#3794d2}.uploads .field>.icon.icon-block{color:#da4453}.uploads progress{margin-top:.5rem;margin-bottom:1rem}.uploads img{max-width:200px}.name{font-size:1rem;color:#bdc3c7}.link>a,.name{word-break:break-all}.clipboard-mobile{margin-top:5px}#albumDiv{-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}#albumDiv .control{text-align:inherit}#linksColumn{margin-top:-.25rem;margin-left:-.25rem;margin-right:-.25rem;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}#linksColumn .column{padding:.25rem}#linksColumn>span{padding:0 .3rem;color:#7f8c8d}.git-commit a{display:inline-block;word-break:break-all}#tabs{margin-bottom:1rem;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}#tabs ul{border-bottom:1px solid #898b8d}#tabs li a{color:#bdc3c7;border-bottom-color:#898b8d}#tabs.is-boxed li.is-active a{color:#3794d2;background:#232629;border-color:#898b8d #898b8d #232629}#tabs.is-boxed li:not(.is-active) a:hover{background:#4d4d4d}.tab-content{margin-bottom:-.75rem;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}.tab-content .label{color:#bdc3c7;font-weight:400}#tab-config.tab-content form{margin-bottom:.75rem}#urlMaxSize{font-weight:700}.render{position:fixed;right:0;bottom:0;font-size:1rem;color:#bdc3c7;cursor:pointer}.render.button{border-bottom-left-radius:0;border-bottom-right-radius:0;right:1%;opacity:.25;transition:opacity .25s}.render.button:hover{opacity:1}
/*# sourceMappingURL=home.css.map */

1
dist/css/home.css.map vendored Normal file

File diff suppressed because one or more lines are too long

2
dist/css/style.css vendored Normal file
View File

@ -0,0 +1,2 @@
html{background-color:#232629;overflow-y:auto}body{color:#eff0f1;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}@-webkit-keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}@keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}a{color:#3794d2}a:hover{color:#60a8dc}hr{background-color:#898b8d}.message-body code,code{background-color:#222528;border-radius:5px}.title{color:#eff0f1}.subtitle,.subtitle strong{color:#bdc3c7}.input::-moz-placeholder,.textarea::-moz-placeholder{color:#7f8c8d}.input::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:#7f8c8d}.input:-moz-placeholder,.textarea:-moz-placeholder{color:#7f8c8d}.input:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:#7f8c8d}.input.is-active,.input.is-focused,.input:active,.input:focus,.textarea.is-active,.textarea.is-focused,.textarea:active,.textarea:focus{border-color:#3794d2}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#4d4d4d}.table td,.table th{vertical-align:middle}.help{color:#7f8c8d}.button.is-info.is-hovered [class*=" icon-"]:before,.button.is-info.is-hovered [class^=icon-]:before,.button.is-info:hover [class*=" icon-"]:before,.button.is-info:hover [class^=icon-]:before{fill:#fff}.checkbox:hover,.radio:hover{color:#7f8c8d}.message{background-color:#31363b}.message-body{color:#eff0f1;border:0;box-shadow:0 20px 60px rgba(10,10,10,.05),0 5px 10px rgba(10,10,10,.1),0 1px 1px rgba(10,10,10,.2)}.menu-list a.is-loading:after{-webkit-animation:spinAround .5s linear infinite;animation:spinAround .5s linear infinite;border-radius:290486px;border-color:transparent transparent #dbdbdb #dbdbdb;border-style:solid;border-width:2px;content:"";display:block;height:1em;width:1em;right:.5em;top:calc(50% - .5em);position:absolute!important}
/*# sourceMappingURL=style.css.map */

1
dist/css/style.css.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["style.css"],"names":[],"mappings":"AAAA,KACE,wBAAyB,CACzB,eACF,CAEA,KACE,aAAc,CACd,mCAA4B,CAA5B,2BACF,CAEA,iCACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,yBACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,EACE,aACF,CAEA,QACE,aACF,CAEA,GACE,wBACF,CAEA,wBAEE,wBAAyB,CACzB,iBACF,CAEA,OACE,aACF,CAMA,2BACE,aACF,CAEA,qDAEE,aACF,CAEA,uEAEE,aACF,CAEA,mDAEE,aACF,CAEA,6DAEE,aACF,CAEA,wIAQE,oBACF,CAEA,qDACE,wBACF,CAEA,oBAEE,qBACF,CAEA,MACE,aACF,CAEA,gMAIE,SACF,CAEA,6BAEE,aACF,CAEA,SACE,wBACF,CAEA,cACE,aAAc,CACd,QAAS,CACT,kGACF,CAEA,8BACE,gDAA0C,CAA1C,wCAA0C,CAE1C,sBAAuB,CAEvB,oDAA6B,CAA7B,kBAA6B,CAA7B,gBAA6B,CAC7B,UAAW,CACX,aAAc,CACd,UAAW,CACX,SAAU,CACV,UAA2B,CAC3B,oBAA0B,CAC1B,2BACF","file":"style.css","sourcesContent":["html {\n background-color: #232629;\n overflow-y: auto\n}\n\nbody {\n color: #eff0f1;\n animation: fadeInOpacity 0.5s\n}\n\n@-webkit-keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\n@keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\na {\n color: #3794d2\n}\n\na:hover {\n color: #60a8dc\n}\n\nhr {\n background-color: #898b8d\n}\n\ncode,\n.message-body code {\n background-color: #222528;\n border-radius: 5px\n}\n\n.title {\n color: #eff0f1\n}\n\n.subtitle {\n color: #bdc3c7\n}\n\n.subtitle strong {\n color: #bdc3c7\n}\n\n.input::-moz-placeholder,\n.textarea::-moz-placeholder {\n color: #7f8c8d\n}\n\n.input::-webkit-input-placeholder,\n.textarea::-webkit-input-placeholder {\n color: #7f8c8d\n}\n\n.input:-moz-placeholder,\n.textarea:-moz-placeholder {\n color: #7f8c8d\n}\n\n.input:-ms-input-placeholder,\n.textarea:-ms-input-placeholder {\n color: #7f8c8d\n}\n\n.input.is-active,\n.input.is-focused,\n.input:active,\n.input:focus,\n.textarea.is-active,\n.textarea.is-focused,\n.textarea:active,\n.textarea:focus {\n border-color: #3794d2\n}\n\n.table.is-hoverable tbody tr:not(.is-selected):hover {\n background-color: #4d4d4d\n}\n\n.table td,\n.table th {\n vertical-align: middle\n}\n\n.help {\n color: #7f8c8d\n}\n\n.button.is-info.is-hovered [class^=\"icon-\"]::before,\n.button.is-info.is-hovered [class*=\" icon-\"]::before,\n.button.is-info:hover [class^=\"icon-\"]::before,\n.button.is-info:hover [class*=\" icon-\"]::before {\n fill: #fff\n}\n\n.checkbox:hover,\n.radio:hover {\n color: #7f8c8d\n}\n\n.message {\n background-color: #31363b\n}\n\n.message-body {\n color: #eff0f1;\n border: 0;\n box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2)\n}\n\n.menu-list a.is-loading::after {\n animation: spinAround 0.5s infinite linear;\n border: 2px solid #dbdbdb;\n border-radius: 290486px;\n border-right-color: transparent;\n border-top-color: transparent;\n content: \"\";\n display: block;\n height: 1em;\n width: 1em;\n right: calc(0% + (1em / 2));\n top: calc(50% - (1em / 2));\n position: absolute !important\n}\n"]}

2
dist/css/sweetalert.css vendored Normal file
View File

@ -0,0 +1,2 @@
.swal-modal{background-color:#31363b}.swal-modal .field{text-align:left;text-align:initial}.swal-modal.is-expanded{width:auto;max-width:90%}.swal-text,.swal-title{color:#eff0f1}.swal-text{text-align:center}.swal-content .checkbox,.swal-content .label,.swal-content .radio{color:#eff0f1}.swal-content .checkbox:hover,.swal-content .radio:hover{color:#bdc3c7}.swal-button{background-color:#3794d2;color:#eff0f1}.swal-button:hover{background-color:#60a8dc}.swal-button:focus{box-shadow:0 0 0 1px #31363b,0 0 0 3px rgba(55,148,210,.29)}.swal-button--loading{color:transparent}.swal-button--danger{background-color:#da4453}.swal-icon--info{border-color:#3794d2}.swal-icon--info:after,.swal-icon--info:before{background-color:#3794d2}.swal-icon--error{border-color:#da4453}.swal-icon--error__line{background-color:#da4453}.swal-icon--warning{border-color:#f67400;-webkit-animation:pulseWarning .5s infinite alternate;animation:pulseWarning .5s infinite alternate}.swal-icon--warning__body,.swal-icon--warning__dot{background-color:#f67400;-webkit-animation:pulseWarningBody .5s infinite alternate;animation:pulseWarningBody .5s infinite alternate}@-webkit-keyframes pulseWarning{0%{border-color:#ffaa60}to{border-color:#f67400}}@keyframes pulseWarning{0%{border-color:#ffaa60}to{border-color:#f67400}}@-webkit-keyframes pulseWarningBody{0%{background-color:#ffaa60}to{background-color:#f67400}}@keyframes pulseWarningBody{0%{background-color:#ffaa60}to{background-color:#f67400}}.swal-icon--success{border-color:#27ae60}.swal-icon--success__line{background-color:#27ae60}.swal-icon--success__hide-corners{background-color:#31363b}.swal-icon--success:after,.swal-icon--success:before{background:#31363b}.swal-display-thumb-container{min-width:200px;min-height:200px;display:flex;align-items:center;justify-content:center}
/*# sourceMappingURL=sweetalert.css.map */

1
dist/css/sweetalert.css.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["sweetalert.css"],"names":[],"mappings":"AAAA,YACE,wBACF,CAEA,mBACE,eAAkB,CAAlB,kBACF,CAEA,wBACE,UAAW,CACX,aACF,CAEA,uBAEE,aACF,CAEA,WACE,iBACF,CAEA,kEAGE,aACF,CAEA,yDAEE,aACF,CAEA,aACE,wBAAyB,CACzB,aACF,CAEA,mBACE,wBACF,CAEA,mBACE,2DACF,CAEA,sBACE,iBACF,CAEA,qBACE,wBACF,CAEA,iBACE,oBACF,CAEA,+CAEE,wBACF,CAEA,kBACE,oBACF,CAEA,wBACE,wBACF,CAEA,oBACE,oBAAqB,CACrB,qDAA8C,CAA9C,6CACF,CAEA,mDAEE,wBAAyB,CACzB,yDAAkD,CAAlD,iDACF,CAEA,gCACE,GACE,oBACF,CAEA,GACE,oBACF,CACF,CAEA,wBACE,GACE,oBACF,CAEA,GACE,oBACF,CACF,CAEA,oCACE,GACE,wBACF,CAEA,GACE,wBACF,CACF,CAEA,4BACE,GACE,wBACF,CAEA,GACE,wBACF,CACF,CAEA,oBACE,oBACF,CAEA,0BACE,wBACF,CAEA,kCACE,wBACF,CAEA,qDAEE,kBACF,CAEA,8BACE,eAAgB,CAChB,gBAAiB,CACjB,YAAa,CACb,kBAAmB,CACnB,sBACF","file":"sweetalert.css","sourcesContent":[".swal-modal {\n background-color: #31363b\n}\n\n.swal-modal .field {\n text-align: initial\n}\n\n.swal-modal.is-expanded {\n width: auto;\n max-width: 90%\n}\n\n.swal-title,\n.swal-text {\n color: #eff0f1\n}\n\n.swal-text {\n text-align: center\n}\n\n.swal-content .label,\n.swal-content .checkbox,\n.swal-content .radio {\n color: #eff0f1\n}\n\n.swal-content .checkbox:hover,\n.swal-content .radio:hover {\n color: #bdc3c7\n}\n\n.swal-button {\n background-color: #3794d2;\n color: #eff0f1\n}\n\n.swal-button:hover {\n background-color: #60a8dc\n}\n\n.swal-button:focus {\n box-shadow: 0 0 0 1px #31363b, 0 0 0 3px rgba(55, 148, 210, 0.29)\n}\n\n.swal-button--loading {\n color: transparent\n}\n\n.swal-button--danger {\n background-color: #da4453\n}\n\n.swal-icon--info {\n border-color: #3794d2\n}\n\n.swal-icon--info::after,\n.swal-icon--info::before {\n background-color: #3794d2\n}\n\n.swal-icon--error {\n border-color: #da4453\n}\n\n.swal-icon--error__line {\n background-color: #da4453\n}\n\n.swal-icon--warning {\n border-color: #f67400;\n animation: pulseWarning 0.5s infinite alternate\n}\n\n.swal-icon--warning__body,\n.swal-icon--warning__dot {\n background-color: #f67400;\n animation: pulseWarningBody 0.5s infinite alternate\n}\n\n@-webkit-keyframes pulseWarning {\n 0% {\n border-color: #ffaa60\n }\n\n to {\n border-color: #f67400\n }\n}\n\n@keyframes pulseWarning {\n 0% {\n border-color: #ffaa60\n }\n\n to {\n border-color: #f67400\n }\n}\n\n@-webkit-keyframes pulseWarningBody {\n 0% {\n background-color: #ffaa60\n }\n\n to {\n background-color: #f67400\n }\n}\n\n@keyframes pulseWarningBody {\n 0% {\n background-color: #ffaa60\n }\n\n to {\n background-color: #f67400\n }\n}\n\n.swal-icon--success {\n border-color: #27ae60\n}\n\n.swal-icon--success__line {\n background-color: #27ae60\n}\n\n.swal-icon--success__hide-corners {\n background-color: #31363b\n}\n\n.swal-icon--success::after,\n.swal-icon--success::before {\n background: #31363b\n}\n\n.swal-display-thumb-container {\n min-width: 200px;\n min-height: 200px;\n display: flex;\n align-items: center;\n justify-content: center\n}\n"]}

2
dist/css/thumbs.css vendored Normal file
View File

@ -0,0 +1,2 @@
.image-container{display:flex;width:200px;height:200px;margin:9px;background-color:#31363b;overflow:hidden;align-items:center;box-shadow:0 20px 60px rgba(10,10,10,.05),0 5px 10px rgba(10,10,10,.1),0 1px 1px rgba(10,10,10,.2)}.image-container .title{font-weight:400;word-break:break-all}.image-container .image{display:flex;height:100%;width:100%;align-items:center;justify-content:center}.image-container .image img{max-height:100%;max-width:100%;height:auto;width:auto}.image-container .controls{display:flex;position:absolute;top:.75rem;right:.75rem}.image-container .controls .button{border-radius:0}.image-container .controls .button:not(:active):not(:hover){color:#fff;background-color:rgba(49,54,59,.75)}.image-container .details{position:absolute;left:.75rem;bottom:.75rem;right:.75rem;background-color:rgba(49,54,59,.75);color:#eff0f1;padding:.25rem;font-size:.75rem}.image-container .details p{display:block;text-overflow:ellipsis;overflow:hidden}.image-container .details p span{font-weight:700}
/*# sourceMappingURL=thumbs.css.map */

1
dist/css/thumbs.css.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["thumbs.css"],"names":[],"mappings":"AAAA,iBACE,YAAa,CACb,WAAY,CACZ,YAAa,CACb,UAAW,CACX,wBAAyB,CACzB,eAAgB,CAChB,kBAAmB,CACnB,kGACF,CAEA,wBACE,eAAmB,CACnB,oBACF,CAEA,wBACE,YAAa,CACb,WAAY,CACZ,UAAW,CACX,kBAAmB,CACnB,sBACF,CAEA,4BACE,eAAgB,CAChB,cAAe,CACf,WAAY,CACZ,UACF,CAEA,2BACE,YAAa,CACb,iBAAkB,CAClB,UAAY,CACZ,YACF,CAEA,mCACE,eACF,CAEA,4DACE,UAAW,CACX,mCACF,CAEA,0BACE,iBAAkB,CAClB,WAAa,CACb,aAAe,CACf,YAAc,CACd,mCAAwC,CACxC,aAAc,CACd,cAAgB,CAChB,gBACF,CAEA,4BACE,aAAc,CACd,sBAAuB,CACvB,eACF,CAEA,iCACE,eACF","file":"thumbs.css","sourcesContent":[".image-container {\n display: flex;\n width: 200px;\n height: 200px;\n margin: 9px;\n background-color: #31363b;\n overflow: hidden;\n align-items: center;\n box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2)\n}\n\n.image-container .title {\n font-weight: normal;\n word-break: break-all\n}\n\n.image-container .image {\n display: flex;\n height: 100%;\n width: 100%;\n align-items: center;\n justify-content: center\n}\n\n.image-container .image img {\n max-height: 100%;\n max-width: 100%;\n height: auto;\n width: auto\n}\n\n.image-container .controls {\n display: flex;\n position: absolute;\n top: 0.75rem;\n right: 0.75rem\n}\n\n.image-container .controls .button {\n border-radius: 0\n}\n\n.image-container .controls .button:not(:active):not(:hover) {\n color: #fff;\n background-color: rgba(49, 54, 59, 0.75)\n}\n\n.image-container .details {\n position: absolute;\n left: 0.75rem;\n bottom: 0.75rem;\n right: 0.75rem;\n background-color: rgba(49, 54, 59, 0.75);\n color: #eff0f1;\n padding: 0.25rem;\n font-size: 0.75rem\n}\n\n.image-container .details p {\n display: block;\n text-overflow: ellipsis;\n overflow: hidden\n}\n\n.image-container .details p span {\n font-weight: bold\n}\n"]}

2
dist/js/album.js vendored Normal file
View File

@ -0,0 +1,2 @@
var lsKeys={},page={lazyLoad:null};window.onload=function(){for(var e=document.querySelectorAll(".file-size"),a=0;a<e.length;a++)e[a].innerHTML=page.getPrettyBytes(parseInt(e[a].innerHTML.replace(/\s*B$/i,"")));page.lazyLoad=new LazyLoad};
//# sourceMappingURL=album.js.map

1
dist/js/album.js.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["album.js"],"names":["const","lsKeys","page","lazyLoad","window","onload","elements","document","querySelectorAll","i","length","innerHTML","getPrettyBytes","parseInt","replace","LazyLoad"],"mappings":"AAGAA,IAAMC,OAAS,GAETC,KAAO,CACXC,SAAU,MAGZC,OAAOC,OAAM,WAEX,IADAL,IAAMM,EAAWC,SAASC,iBAAiB,cAClCC,EAAI,EAAGA,EAAIH,EAASI,OAAQD,IACnCH,EAASG,GAAGE,UAAYT,KAAKU,eAAeC,SAASP,EAASG,GAAGE,UAAUG,QAAQ,SAAU,MAE/FZ,KAAKC,SAAW,IAAIY","file":"album.js","sourcesContent":["/* global LazyLoad */\n\n// eslint-disable-next-line no-unused-vars\nconst lsKeys = {}\n\nconst page = {\n lazyLoad: null\n}\n\nwindow.onload = () => {\n const elements = document.querySelectorAll('.file-size')\n for (let i = 0; i < elements.length; i++)\n elements[i].innerHTML = page.getPrettyBytes(parseInt(elements[i].innerHTML.replace(/\\s*B$/i, '')))\n\n page.lazyLoad = new LazyLoad()\n}\n"]}

2
dist/js/auth.js vendored Normal file
View File

@ -0,0 +1,2 @@
var lsKeys={token:"token"},page={token:localStorage[lsKeys.token],user:null,pass:null,do:function(e,r){var o=page.user.value.trim();if(!o)return swal("An error occurred!","You need to specify a username.","error");var t=page.pass.value.trim();if(!t)return swal("An error occurred!","You need to specify a password.","error");r.classList.add("is-loading"),axios.post("api/"+e,{username:o,password:t}).then((function(o){if(!1===o.data.success)return r.classList.remove("is-loading"),swal("Unable to "+e+"!",o.data.description,"error");localStorage.token=o.data.token,window.location="dashboard"})).catch((function(e){return console.error(e),r.classList.remove("is-loading"),swal("An error occurred!","There was an error with the request, please check the console for more information.","error")}))},verify:function(){page.token&&axios.post("api/tokens/verify",{token:page.token}).then((function(e){if(!1===e.data.success)return swal("An error occurred!",e.data.description,"error");window.location="dashboard"})).catch((function(e){console.error(e);var r=e.response.data&&e.response.data.description?e.response.data.description:"There was an error with the request, please check the console for more information.";return swal(e.response.status+" "+e.response.statusText,r,"error")}))}};window.onload=function(){page.verify(),page.user=document.querySelector("#user"),page.pass=document.querySelector("#pass"),document.querySelector("#authForm").addEventListener("submit",(function(e){e.preventDefault()})),document.querySelector("#loginBtn").addEventListener("click",(function(e){page.do("login",e.currentTarget)})),document.querySelector("#registerBtn").addEventListener("click",(function(e){page.do("register",e.currentTarget)}))};
//# sourceMappingURL=auth.js.map

1
dist/js/auth.js.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["auth.js"],"names":["const","lsKeys","token","page","localStorage","user","pass","do","dest","trigger","value","trim","swal","classList","add","axios","post","username","password","then","response","data","success","remove","description","window","location","catch","error","console","verify","onload","document","querySelector","addEventListener","event","preventDefault","currentTarget"],"mappings":"AAEAA,IAAMC,OAAS,CACbC,MAAO,SAGHC,KAAO,CAEXD,MAAOE,aAAaH,OAAOC,OAG3BG,KAAM,KACNC,KAAM,KAGRC,GAAO,SAAIC,EAAMC,GACfT,IAAMK,EAAOF,KAAKE,KAAKK,MAAMC,OAC7B,IAAKN,EACH,OAAOO,KAAK,qBAAsB,kCAAmC,SAEvEZ,IAAMM,EAAOH,KAAKG,KAAKI,MAAMC,OAC7B,IAAKL,EACH,OAAOM,KAAK,qBAAsB,kCAAmC,SAEvEH,EAAQI,UAAUC,IAAI,cACtBC,MAAMC,KAAK,OAAOR,EAAQ,CACxBS,SAAUZ,EACVa,SAAUZ,IACTa,MAAI,SAACC,GACN,IAA8B,IAA1BA,EAASC,KAAKC,QAEhB,OADAb,EAAQI,UAAUU,OAAO,cAClBX,KAAK,aAAaJ,EAAI,IAAKY,EAASC,KAAKG,YAAa,SAG/DpB,aAAaF,MAAQkB,EAASC,KAAKnB,MACnCuB,OAAOC,SAAW,eACjBC,OAAK,SAACC,GAGP,OAFAC,QAAQD,MAAMA,GACdnB,EAAQI,UAAUU,OAAO,cAClBX,KAAK,qBAAsB,sFAAuF,aAI7HkB,OAAW,WACJ3B,KAAKD,OAEVa,MAAMC,KAAK,oBAAqB,CAC9Bd,MAAOC,KAAKD,QACXiB,MAAI,SAACC,GACN,IAA8B,IAA1BA,EAASC,KAAKC,QAChB,OAAOV,KAAK,qBAAsBQ,EAASC,KAAKG,YAAa,SAE/DC,OAAOC,SAAW,eACjBC,OAAK,SAACC,GACPC,QAAQD,MAAMA,GACd5B,IAAMwB,EAAcI,EAAMR,SAASC,MAAQO,EAAMR,SAASC,KAAKG,YAC3DI,EAAMR,SAASC,KAAKG,YACpB,sFACJ,OAAOZ,KAAQgB,EAAMR,SAAS,OAAM,IAAIQ,EAAMR,SAAmB,WAAII,EAAa,cAItFC,OAAOM,OAAM,WACX5B,KAAK2B,SAEL3B,KAAKE,KAAO2B,SAASC,cAAc,SACnC9B,KAAKG,KAAO0B,SAASC,cAAc,SAGnCD,SAASC,cAAc,aAAaC,iBAAiB,UAAQ,SAAEC,GAC7DA,EAAMC,oBAGRJ,SAASC,cAAc,aAAaC,iBAAiB,SAAO,SAAEC,GAC5DhC,KAAKI,GAAG,QAAS4B,EAAME,kBAGzBL,SAASC,cAAc,gBAAgBC,iBAAiB,SAAO,SAAEC,GAC/DhC,KAAKI,GAAG,WAAY4B,EAAME","file":"auth.js","sourcesContent":["/* global swal, axios */\n\nconst lsKeys = {\n token: 'token'\n}\n\nconst page = {\n // user token\n token: localStorage[lsKeys.token],\n\n // HTML elements\n user: null,\n pass: null\n}\n\npage.do = (dest, trigger) => {\n const user = page.user.value.trim()\n if (!user)\n return swal('An error occurred!', 'You need to specify a username.', 'error')\n\n const pass = page.pass.value.trim()\n if (!pass)\n return swal('An error occurred!', 'You need to specify a password.', 'error')\n\n trigger.classList.add('is-loading')\n axios.post(`api/${dest}`, {\n username: user,\n password: pass\n }).then(response => {\n if (response.data.success === false) {\n trigger.classList.remove('is-loading')\n return swal(`Unable to ${dest}!`, response.data.description, 'error')\n }\n\n localStorage.token = response.data.token\n window.location = 'dashboard'\n }).catch(error => {\n console.error(error)\n trigger.classList.remove('is-loading')\n return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')\n })\n}\n\npage.verify = () => {\n if (!page.token) return\n\n axios.post('api/tokens/verify', {\n token: page.token\n }).then(response => {\n if (response.data.success === false)\n return swal('An error occurred!', response.data.description, 'error')\n\n window.location = 'dashboard'\n }).catch(error => {\n console.error(error)\n const description = error.response.data && error.response.data.description\n ? error.response.data.description\n : 'There was an error with the request, please check the console for more information.'\n return swal(`${error.response.status} ${error.response.statusText}`, description, 'error')\n })\n}\n\nwindow.onload = () => {\n page.verify()\n\n page.user = document.querySelector('#user')\n page.pass = document.querySelector('#pass')\n\n // Prevent default form's submit action\n document.querySelector('#authForm').addEventListener('submit', event => {\n event.preventDefault()\n })\n\n document.querySelector('#loginBtn').addEventListener('click', event => {\n page.do('login', event.currentTarget)\n })\n\n document.querySelector('#registerBtn').addEventListener('click', event => {\n page.do('register', event.currentTarget)\n })\n}\n"]}

2
dist/js/dashboard.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/dashboard.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
dist/js/home.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/home.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
dist/js/misc/render.js vendored Normal file
View File

@ -0,0 +1,2 @@
lsKeys.render="render",page.renderType="miku",page.renderConfig={al:{name:"ship waifu~",root:"render/al/",array:["admiral_graf_spee_1.png","admiral_hipper_1.png","akagi_1.png","akashi_1.png","akashi_2.png","atago_1.png","atago_3.png","atago_4.png","atago_5.png","belfast_2.png","choukai_1.png","deutschland_1.png","enterprise_1.png","glorious_1.png","hammann_1.png","hammann_2.png","hammann_3.png","hatsuharu_1.png","kaga_1.png","kaga_2.png","kaga_3.png","laffey_1.png","laffey_2.png","laffey_3.png","prinz_eugen_3.png","san_diego_1.png","takao_3.png","unicorn_1.png","unicorn_2.png","unicorn_3.png","unicorn_4.png","unicorn_6.png","unicorn_7.png","unicorn_8.png","yamashiro_1.png","yamashiro_2.png","yamashiro_3.png","yukikaze_1.png"]},miku:{name:"miku ❤️~",root:"render/miku/",array:[]}};for(var i=1;i<=50;i++)page.renderConfig.miku.array.push(("00"+i).slice(-3)+".png");page.config=null,page.render=null,page.doRenderSwal=function(){var e=document.createElement("div");e.innerHTML='\n <div class="field">\n <div class="control">\n <label class="checkbox">\n <input id="swalRender" type="checkbox" '+("0"===localStorage[lsKeys.render]?"":"checked")+">\n Enable random render of "+page.config.name+'\n </label>\n </div>\n <p class="help">If disabled, you will still be able to see a small button on the bottom right corner of the screen to re-enable it.</p>\n </div>\n ',swal({content:e,buttons:{confirm:!0}}).then((function(n){if(n){var a=e.querySelector("#swalRender").checked?void 0:"0";if(a!==localStorage[lsKeys.render])a?localStorage[lsKeys.render]=a:localStorage.removeItem(lsKeys.render),swal("Success!","Random render is now "+(a?"disabled":"enabled")+".","success"),document.querySelector("body > .render").remove(),page.doRender()}}))},page.getRenderVersion=function(){var e=document.querySelector("#renderScript");return e&&e.dataset.version?"?v="+e.dataset.version:""},page.doRender=function(){var e;(page.config=page.renderConfig[page.renderType],page.config&&page.config.array.length)&&("0"===localStorage[lsKeys.render]?((e=document.createElement("a")).className="button is-info is-hidden-mobile",e.title=page.config.name,e.innerHTML='<i class="icon-picture"></i>'):(page.render=page.config.array[Math.floor(Math.random()*page.config.array.length)],(e=document.createElement("img")).alt=e.title=page.config.name,e.className="is-hidden-mobile",e.src=""+page.config.root+page.render+page.getRenderVersion()),e.classList.add("render"),e.addEventListener("click",page.doRenderSwal),document.body.appendChild(e))},page.doRender();
//# sourceMappingURL=render.js.map

1
dist/js/misc/render.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
dist/js/misc/utils.js vendored Normal file
View File

@ -0,0 +1,2 @@
lsKeys.siBytes="siBytes",page.prepareShareX=function(){var e=page.token?{token:page.token||"",albumid:page.album||""}:{};e.filelength=page.fileLength||"",e.age=page.uploadAge||"";for(var t=[],a=Object.keys(e),n=0;n<a.length;n++)t.push(' "'+a[n]+'": "'+e[a[n]]+'"');var o=(location.hostname+location.pathname).replace(/\/(dashboard)?$/,""),r=o.replace(/\//g,"_"),i=document.querySelector("#ShareX"),l='{\n "Name": "'+r+'",\n "DestinationType": "ImageUploader, FileUploader",\n "RequestMethod": "POST",\n "RequestURL": "'+location.protocol+"//"+o+'/api/upload",\n "Headers": {\n'+t.join(",\n")+'\n },\n "Body": "MultipartFormData",\n "FileFormName": "files[]",\n "URL": "$json:files[0].url$",\n "ThumbnailURL": "$json:files[0].url$"\n}',s=new Blob([l],{type:"application/octet-binary"});i.setAttribute("href",URL.createObjectURL(s)),i.setAttribute("download",r+".sxcu")},page.getPrettyDate=function(e){return e.getFullYear()+"-"+(e.getMonth()<9?"0":"")+(e.getMonth()+1)+"-"+(e.getDate()<10?"0":"")+e.getDate()+" "+(e.getHours()<10?"0":"")+e.getHours()+":"+(e.getMinutes()<10?"0":"")+e.getMinutes()+":"+(e.getSeconds()<10?"0":"")+e.getSeconds()},page.getPrettyBytes=function(e){if("number"!=typeof e&&!isFinite(e))return e;var t="0"!==localStorage[lsKeys.siBytes],a=e<0?"-":"",n=t?1e3:1024;if(a&&(e=-e),e<n)return""+a+e+" B";var o=Math.min(Math.floor(Math.log(e)*Math.LOG10E/3),8);return""+a+Number((e/Math.pow(n,o)).toPrecision(3))+" "+((t?"kMGTPEZY":"KMGTPEZY").charAt(o-1)+(t?"":"i"))+"B"};
//# sourceMappingURL=utils.js.map

1
dist/js/misc/utils.js.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["utils.js"],"names":["lsKeys","siBytes","page","prepareShareX","const","values","token","albumid","album","filelength","fileLength","age","uploadAge","headers","keys","Object","i","length","push","origin","location","hostname","pathname","replace","originClean","sharexElement","document","querySelector","sharexFile","join","sharexBlob","Blob","type","setAttribute","URL","createObjectURL","getPrettyDate","date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getPrettyBytes","num","isFinite","si","localStorage","neg","scale","exponent","Math","min","floor","log","LOG10E","Number","pow","toPrecision","charAt"],"mappings":"AAGAA,OAAOC,QAAU,UAEjBC,KAAKC,cAAa,WAChBC,IAAMC,EAASH,KAAKI,MAAQ,CAC1BA,MAAOJ,KAAKI,OAAS,GACrBC,QAASL,KAAKM,OAAS,IACrB,GACJH,EAAOI,WAAaP,KAAKQ,YAAc,GACvCL,EAAOM,IAAMT,KAAKU,WAAa,GAI/B,IAFAR,IAAMS,EAAU,GACVC,EAAOC,OAAOD,KAAKT,GAChBW,EAAI,EAAGA,EAAIF,EAAKG,OAAQD,IAE/BH,EAAQK,KAAK,QAAQJ,EAAKE,GAAE,OAAOX,EAAOS,EAAKE,IAAG,KAEpDZ,IAAMe,GAAUC,SAASC,SAAWD,SAASE,UAAUC,QAAQ,kBAAmB,IAC5EC,EAAcL,EAAOI,QAAQ,MAAO,KAEpCE,EAAgBC,SAASC,cAAc,WACvCC,EAAa,iBACRJ,EAAW,yGAGLJ,SAAS,SAAQ,KAAKD,EAAM,kCAE7CN,EAAQgB,KAAK,OAAM,oJAQbC,EAAa,IAAIC,KAAK,CAACH,GAAa,CAAEI,KAAM,6BAClDP,EAAcQ,aAAa,OAAQC,IAAIC,gBAAgBL,IACvDL,EAAcQ,aAAa,WAAeT,EAAW,UAGvDtB,KAAKkC,cAAa,SAAGC,GACnB,OAAOA,EAAKC,cAAgB,KACzBD,EAAKE,WAAa,EAAI,IAAM,KAC5BF,EAAKE,WAAa,GAAK,KACvBF,EAAKG,UAAY,GAAK,IAAM,IAC7BH,EAAKG,UAAY,KAChBH,EAAKI,WAAa,GAAK,IAAM,IAC9BJ,EAAKI,WAAa,KACjBJ,EAAKK,aAAe,GAAK,IAAM,IAChCL,EAAKK,aAAe,KACnBL,EAAKM,aAAe,GAAK,IAAM,IAChCN,EAAKM,cAGTzC,KAAK0C,eAAc,SAAGC,GAGpB,GAAmB,iBAARA,IAAqBC,SAASD,GAAM,OAAOA,EAEtDzC,IAAM2C,EAAsC,MAAjCC,aAAahD,OAAOC,SACzBgD,EAAMJ,EAAM,EAAI,IAAM,GACtBK,EAAQH,EAAK,IAAO,KAE1B,GADIE,IAAKJ,GAAOA,GACZA,EAAMK,EAAO,MAAO,GAAGD,EAAMJ,EAAG,KAEpCzC,IAAM+C,EAAWC,KAAKC,IAAID,KAAKE,MAAOF,KAAKG,IAAIV,GAAOO,KAAKI,OAAU,GAAI,GAGzE,MAAO,GAAGP,EAFKQ,QAAQZ,EAAMO,KAAKM,IAAIR,EAAOC,IAAWQ,YAAY,IAE9C,MADTZ,EAAK,WAAa,YAAYa,OAAOT,EAAW,IAAMJ,EAAK,GAAK,MAChD","file":"utils.js","sourcesContent":["/* global lsKeys, page */\n\n// keys for localStorage\nlsKeys.siBytes = 'siBytes'\n\npage.prepareShareX = () => {\n const values = page.token ? {\n token: page.token || '',\n albumid: page.album || ''\n } : {}\n values.filelength = page.fileLength || ''\n values.age = page.uploadAge || ''\n\n const headers = []\n const keys = Object.keys(values)\n for (let i = 0; i < keys.length; i++)\n // Pad by 4 space\n headers.push(` \"${keys[i]}\": \"${values[keys[i]]}\"`)\n\n const origin = (location.hostname + location.pathname).replace(/\\/(dashboard)?$/, '')\n const originClean = origin.replace(/\\//g, '_')\n\n const sharexElement = document.querySelector('#ShareX')\n const sharexFile = `{\n \"Name\": \"${originClean}\",\n \"DestinationType\": \"ImageUploader, FileUploader\",\n \"RequestMethod\": \"POST\",\n \"RequestURL\": \"${location.protocol}//${origin}/api/upload\",\n \"Headers\": {\n${headers.join(',\\n')}\n },\n \"Body\": \"MultipartFormData\",\n \"FileFormName\": \"files[]\",\n \"URL\": \"$json:files[0].url$\",\n \"ThumbnailURL\": \"$json:files[0].url$\"\n}`\n\n const sharexBlob = new Blob([sharexFile], { type: 'application/octet-binary' })\n sharexElement.setAttribute('href', URL.createObjectURL(sharexBlob))\n sharexElement.setAttribute('download', `${originClean}.sxcu`)\n}\n\npage.getPrettyDate = date => {\n return date.getFullYear() + '-' +\n (date.getMonth() < 9 ? '0' : '') + // month's index starts from zero\n (date.getMonth() + 1) + '-' +\n (date.getDate() < 10 ? '0' : '') +\n date.getDate() + ' ' +\n (date.getHours() < 10 ? '0' : '') +\n date.getHours() + ':' +\n (date.getMinutes() < 10 ? '0' : '') +\n date.getMinutes() + ':' +\n (date.getSeconds() < 10 ? '0' : '') +\n date.getSeconds()\n}\n\npage.getPrettyBytes = num => {\n // MIT License\n // Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n if (typeof num !== 'number' && !isFinite(num)) return num\n\n const si = localStorage[lsKeys.siBytes] !== '0'\n const neg = num < 0 ? '-' : ''\n const scale = si ? 1000 : 1024\n if (neg) num = -num\n if (num < scale) return `${neg}${num} B`\n\n const exponent = Math.min(Math.floor((Math.log(num) * Math.LOG10E) / 3), 8) // 8 is count of KMGTPEZY\n const numStr = Number((num / Math.pow(scale, exponent)).toPrecision(3))\n const pre = (si ? 'kMGTPEZY' : 'KMGTPEZY').charAt(exponent - 1) + (si ? '' : 'i')\n return `${neg}${numStr} ${pre}B`\n}\n"]}

106
gulpfile.js Normal file
View File

@ -0,0 +1,106 @@
const gulp = require('gulp')
const cssnano = require('cssnano')
const del = require('del')
const buble = require('gulp-buble')
const eslint = require('gulp-eslint')
const gulpif = require('gulp-if')
const nodemon = require('gulp-nodemon')
const postcss = require('gulp-postcss')
const postcssPresetEnv = require('postcss-preset-env')
const sourcemaps = require('gulp-sourcemaps')
const stylelint = require('gulp-stylelint')
const terser = require('gulp-terser')
/** TASKS: LINT */
gulp.task('lint:js', () => {
return gulp.src('./src/js/**/*.js')
.pipe(eslint())
.pipe(eslint.failAfterError())
})
gulp.task('lint:css', () => {
return gulp.src('./src/css/**/*.css')
.pipe(stylelint())
})
gulp.task('lint', gulp.parallel('lint:js', 'lint:css'))
/** TASKS: CLEAN */
gulp.task('clean:css', () => {
return del(['dist/css'])
})
gulp.task('clean:js', () => {
return del(['dist/js'])
})
gulp.task('clean', gulp.parallel('clean:css', 'clean:js'))
/** TASKS: BUILD */
gulp.task('build:css', () => {
const plugins = [
postcssPresetEnv()
]
// Minify on production
if (process.env.NODE_ENV !== 'development')
plugins.push(cssnano())
return gulp.src('./src/css/**/*.css')
.pipe(sourcemaps.init())
.pipe(postcss(plugins))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./dist/css'))
})
gulp.task('build:js', () => {
return gulp.src('./src/js/**/*.js')
.pipe(sourcemaps.init())
.pipe(buble())
// Minify on production
.pipe(gulpif(process.env.NODE_ENV !== 'development', terser()))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./dist/js'))
})
gulp.task('build', gulp.parallel('build:css', 'build:js'))
gulp.task('default', gulp.series('lint', 'clean', 'build'))
/** TASKS: WATCH (SKIP LINTER) */
gulp.task('watch:css', () => {
return gulp.watch([
'src/**/*.css'
], gulp.series('clean:css', 'build:css'))
})
gulp.task('watch:js', () => {
return gulp.watch([
'src/**/*.js'
], gulp.series('clean:js', 'build:js'))
})
gulp.task('watch:src', gulp.parallel('watch:css', 'watch:js'))
gulp.task('nodemon', done => {
return nodemon({
script: './lolisafe.js',
env: process.env,
watch: [
'lolisafe.js',
'logger.js',
'config.js',
'controllers/',
'database/',
'routes/'
],
ext: 'js',
done
})
})
gulp.task('watch', gulp.series('clean', 'build', gulp.parallel('watch:src', 'nodemon')))

View File

@ -1,13 +1,13 @@
const bodyParser = require('body-parser')
const clamd = require('clamdjs')
const config = require('./config')
const express = require('express')
const helmet = require('helmet')
const logger = require('./logger')
const nunjucks = require('nunjucks')
const path = require('path')
const RateLimit = require('express-rate-limit')
const readline = require('readline')
const config = require('./config')
const logger = require('./logger')
const safe = express()
process.on('uncaughtException', error => {
@ -50,6 +50,8 @@ if (Array.isArray(config.rateLimits) && config.rateLimits.length)
safe.use(bodyParser.urlencoded({ extended: true }))
safe.use(bodyParser.json())
let setHeaders
// Cache control (safe.fiery.me)
if (config.cacheControl) {
const cacheControls = {
@ -66,16 +68,6 @@ if (config.cacheControl) {
next()
})
const setHeaders = res => {
res.set('Access-Control-Allow-Origin', '*')
res.set('Cache-Control', cacheControls.default)
}
if (config.serveFilesWithNode)
safe.use('/', express.static(paths.uploads, { setHeaders }))
safe.use('/', express.static(paths.public, { setHeaders }))
// Do NOT cache these dynamic routes
safe.use(['/a', '/api', '/nojs'], (req, res, next) => {
res.set('Cache-Control', cacheControls.disable)
@ -93,13 +85,19 @@ if (config.cacheControl) {
setHeaders(res)
next()
})
} else {
if (config.serveFilesWithNode)
safe.use('/', express.static(paths.uploads))
safe.use('/', express.static(paths.public))
setHeaders = res => {
res.set('Access-Control-Allow-Origin', '*')
res.set('Cache-Control', cacheControls.default)
}
}
if (config.serveFilesWithNode)
safe.use('/', express.static(paths.uploads, { setHeaders }))
safe.use('/', express.static(paths.public, { setHeaders }))
safe.use('/', express.static(paths.dist, { setHeaders }))
safe.use('/', album)
safe.use('/', nojs)
safe.use('/api', api)
@ -247,7 +245,10 @@ safe.use('/api', api)
prompt: ''
}).on('line', line => {
try {
if (line === '.exit') process.exit(0)
if (line === 'rs')
return
if (line === '.exit')
return process.exit(0)
// eslint-disable-next-line no-eval
logger.log(eval(line))
} catch (error) {

View File

@ -15,8 +15,11 @@
"license": "MIT",
"scripts": {
"start": "node ./lolisafe.js",
"startdev": "env NODE_ENV=development node ./lolisafe.js",
"pm2": "pm2 start --name safe ./lolisafe.js",
"pm2": "pm2 start ./lolisafe.js",
"lint": "gulp lint",
"build": "gulp default",
"watch": "gulp watch",
"develop": "env NODE_ENV=development yarn watch",
"cf-purge": "node ./scripts/cf-purge.js",
"clean-up": "node ./scripts/clean-up.js",
"delete-expired": "node ./scripts/delete-expired.js",
@ -43,12 +46,27 @@
"systeminformation": "^4.14.8"
},
"devDependencies": {
"eslint": "^6.3.0",
"browserslist": "^4.7.0",
"cssnano": "^4.1.10",
"del": "^5.1.0",
"eslint": "^6.4.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-compat": "^3.3.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-node": "^10.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"gulp": "^4.0.2",
"gulp-buble": "^0.9.0",
"gulp-cli": "^2.2.0",
"gulp-eslint": "^6.0.0",
"gulp-if": "^3.0.0",
"gulp-nodemon": "^2.4.2",
"gulp-postcss": "^8.0.0",
"gulp-sourcemaps": "^2.6.5",
"gulp-stylelint": "^9.0.0",
"gulp-terser": "^1.2.0",
"postcss-preset-env": "^6.7.0",
"stylelint": "^10.1.0",
"stylelint-config-standard": "^18.3.0"
}

View File

@ -1,31 +0,0 @@
input {
background: rgba(0, 0, 0, 0)
}
input,
a {
border-left: 0;
border-top: 0;
border-right: 0;
border-radius: 0;
-webkit-box-shadow: 0 0 0;
box-shadow: 0 0 0
}
.select-wrapper {
text-align: center;
margin-bottom: 10px
}
#login .input {
border-top: 0;
border-right: 0;
border-left: 0;
border-radius: 0;
padding-right: calc(0.75em + 1px);
padding-left: calc(0.75em + 1px)
}
#login .control .button {
border-radius: 0
}

View File

@ -1,15 +1,6 @@
Font license info
## Typicons
(c) Stephen Hutchings 2012
Author: Stephen Hutchings
License: SIL (http://scripts.sil.org/OFL)
Homepage: http://typicons.com/
## Elusive
Copyright (C) 2013 by Aristeides Stathopoulos

View File

@ -0,0 +1,240 @@
{
"name": "",
"css_prefix_text": "icon-",
"css_use_suffix": false,
"hinting": true,
"units_per_em": 1000,
"ascent": 850,
"glyphs": [
{
"uid": "01b8329f17c7058552798e482d41b794",
"css": "sharex",
"code": 59393,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M328 923C230 913 145 849 99 752 47 642 56 506 123 406 167 340 230 296 304 280 325 276 374 276 395 280 440 290 481 310 515 339 522 344 527 349 527 349 526 349 517 351 507 353 385 370 284 451 250 558 240 587 238 603 238 637 238 671 240 687 250 717 264 758 285 792 320 826 352 859 384 881 427 898L443 905 436 908C424 913 391 921 371 923 351 925 346 925 328 923ZM576 934C512 929 455 910 406 878 340 834 296 770 280 696 276 675 276 626 281 605 290 560 310 519 339 485 344 478 349 473 349 473 350 474 351 483 353 493 370 615 451 716 558 750 587 760 603 762 637 762 683 762 711 755 754 734 816 703 869 644 898 573L905 557 908 564C918 587 926 638 924 663 916 766 852 853 752 901 699 926 632 939 576 934ZM618 722C573 715 528 695 491 667 471 651 471 650 482 649 611 633 715 552 750 442 760 413 762 397 762 363 762 317 755 289 734 246 704 185 646 132 577 104 564 98 558 95 560 94 564 91 595 82 610 80 634 75 652 75 672 77 737 84 794 112 842 162 866 187 881 209 897 240 919 283 930 324 934 374 940 451 919 531 878 594 834 659 771 703 698 719 683 723 634 724 618 722ZM649 518C633 389 552 285 442 250 413 240 397 238 363 238 319 238 291 245 251 263 221 278 200 293 174 319 141 352 119 384 102 427L95 443 92 436C82 413 74 362 76 337 85 234 148 147 248 99 329 60 426 55 512 83 550 95 579 110 610 133 665 175 705 236 719 302 723 320 725 359 722 378 716 425 697 470 667 509 651 529 651 529 649 518Z",
"width": 1000
},
"search": [
"sharex"
]
},
{
"uid": "7961745a0533e615b5e9f5cf39b902dc",
"css": "terminal",
"code": 59408,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M929 71H71C32 71 0 103 0 143V857C0 897 32 929 71 929H929C968 929 1000 897 1000 857V143C1000 103 968 71 929 71ZM143 571L286 429 143 286 214 214 429 429 214 643 143 571ZM714 643H429V571H714V643Z",
"width": 1000
},
"search": [
"terminal"
]
},
{
"uid": "dec0ce0476433f7e49e096526cf89465",
"css": "hammer",
"code": 59409,
"src": "fontawesome"
},
{
"uid": "4bcff864c368690c11e641fcf71d229b",
"css": "privatebin",
"code": 59415,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M484.4 980.9C477 977.1 377.4 922.9 263 860.4 112.4 778.1 54.3 745.5 52.4 741.9 50.2 737.9 50 694.3 51 497 52.2 275.7 52.5 256.7 55.6 253.6 57.5 251.7 157.1 196.9 277 131.9 427.9 50.1 496.8 13.7 501 13.7 504.6 13.7 515.5 18.5 528 25.4 539.5 31.8 638 85.6 746.9 145.1 890.4 223.4 945.7 254.5 947.6 258.1 949.8 262.1 950 305.7 949 503 947.8 724 947.5 743.3 944.4 746.4 940.6 750.3 508.4 984.9 502 986.6 499.5 987.2 492.5 985 484.4 980.9ZM622 768C622 767 614.3 736.8 605 701 573.8 581.9 558.6 513.8 556.6 484.8L555.4 466.5 576 444.8C612.6 405.9 631.9 371 633.6 340.5 634.3 327 633.7 322 630.2 312.5 620.7 287.2 593 259.3 563.2 245.1 512.7 221 460.5 226.7 420.5 260.6 387.4 288.8 370.2 323.3 372.5 356.7 374.5 384.8 389.9 412 422.4 444.5 433.2 455.2 442.5 466.4 443.2 469.3 445.4 477.8 442.6 507 437 536 430.3 570.4 408.2 659.3 391.2 720.3 383.9 746.3 378 768.1 378 768.8 378 769.5 432.9 770 500 770 577.9 770 622 769.3 622 768Z",
"width": 1000
},
"search": [
"privatebin"
]
},
{
"uid": "4109c474ff99cad28fd5a2c38af2ec6f",
"css": "filter",
"code": 61616,
"src": "fontawesome"
},
{
"uid": "c8585e1e5b0467f28b70bce765d5840c",
"css": "docs",
"code": 61637,
"src": "fontawesome"
},
{
"uid": "178053298e3e5b03551d754d4b9acd8b",
"css": "doc-inv",
"code": 61787,
"src": "fontawesome"
},
{
"uid": "98d9c83c1ee7c2c25af784b518c522c5",
"css": "block",
"code": 59410,
"src": "fontawesome"
},
{
"uid": "0ddd3e8201ccc7d41f7b7c9d27eca6c1",
"css": "link",
"code": 59411,
"src": "fontawesome"
},
{
"uid": "98687378abd1faf8f6af97c254eb6cd6",
"css": "cog-alt",
"code": 59412,
"src": "fontawesome"
},
{
"uid": "f4445feb55521283572ee88bc304f928",
"css": "floppy",
"code": 59413,
"src": "fontawesome"
},
{
"uid": "bd7fd67bed189448225cad0fe4ef3d7c",
"css": "chrome",
"code": 62056,
"src": "fontawesome"
},
{
"uid": "c97bfbcfb31e74be0653d8551c89a40f",
"css": "firefox",
"code": 62057,
"src": "fontawesome"
},
{
"uid": "1bafeeb1808a5fe24484c7890096901a",
"css": "user-plus",
"code": 59414,
"src": "fontawesome"
},
{
"uid": "5d595124cecf472869d1cdc020da0ccc",
"css": "upload-cloud",
"code": 59417,
"src": "entypo"
},
{
"uid": "a1be363d4de9be39857893d4134f6215",
"css": "picture",
"code": 59394,
"src": "elusive"
},
{
"uid": "50e664a6f12199784c02600b2ccfd60a",
"css": "th-list",
"code": 59395,
"src": "elusive"
},
{
"uid": "76f961b11f65300838a5a78856aca30f",
"css": "th-large",
"code": 59418,
"src": "elusive"
},
{
"uid": "3ab2abf6f936d3e53ee8c184cedaed82",
"css": "trash",
"code": 59396,
"src": "elusive"
},
{
"uid": "a73c5deb486c8d66249811642e5d719a",
"css": "arrows-cw",
"code": 59398,
"src": "fontawesome"
},
{
"uid": "55e2ff85b1c459c383f46da6e96014b0",
"css": "plus",
"code": 59399,
"src": "elusive"
},
{
"uid": "499b745a2e2485bdd059c3a53d048e5f",
"css": "cancel",
"code": 59397,
"src": "elusive"
},
{
"uid": "3a00327e61b997b58518bd43ed83c3df",
"css": "login",
"code": 59401,
"src": "fontawesome"
},
{
"uid": "d7271d490b71df4311e32cdacae8b331",
"css": "home",
"code": 59402,
"src": "fontawesome"
},
{
"uid": "0bda4bc779d4c32623dec2e43bd67ee8",
"css": "gauge",
"code": 59403,
"src": "fontawesome"
},
{
"uid": "17ebadd1e3f274ff0205601eef7b9cc4",
"css": "help-circled",
"code": 59405,
"src": "fontawesome"
},
{
"uid": "0f6a2573a7b6df911ed199bb63717e27",
"css": "github-circled",
"code": 59406,
"src": "fontawesome"
},
{
"uid": "38575a803c4da31ce20d77e1e1236bcb",
"css": "paper-plane",
"code": 61912,
"src": "fontawesome"
},
{
"uid": "62b0580ee8edc3a3edfbf68a47c852d5",
"css": "pencil",
"code": 59407,
"src": "elusive"
},
{
"uid": "96ea1be71f597a5bdfc8f791ada4f651",
"css": "archive",
"code": 59392,
"src": "entypo"
},
{
"uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
"css": "download",
"code": 59419,
"src": "fontawesome"
},
{
"uid": "1a27e6346cdf0480c9c22351378bebbb",
"css": "clipboard",
"code": 59400,
"src": "typicons"
},
{
"uid": "92cf34c9a8e5d2486d75fcd393dffb07",
"css": "gatsby",
"code": 59420,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M500 33.3C243.3 33.3 33.3 243.3 33.3 500S243.3 966.7 500 966.7 966.7 756.7 966.7 500 756.7 33.3 500 33.3ZM240 760C170 690 133.3 596.7 133.3 506.7L496.7 866.7C403.3 863.3 310 830 240 760ZM580 856.7L143.3 420C180 256.7 326.7 133.3 500 133.3 623.3 133.3 730 193.3 796.7 283.3L746.7 326.7C690 250 600 200 500 200 370 200 260 283.3 216.7 400L600 783.3C696.7 750 770 666.7 793.3 566.7H633.3V500H866.7C866.7 673.3 743.3 820 580 856.7Z",
"width": 1000
},
"search": [
"gatsby"
]
}
]
}

View File

@ -1,11 +1,11 @@
@font-face {
font-family: 'fontello';
src: url('fontello.eot?tWLiAlAX5i');
src: url('fontello.eot?tWLiAlAX5i#iefix') format('embedded-opentype'),
url('fontello.woff2?tWLiAlAX5i') format('woff2'),
url('fontello.woff?tWLiAlAX5i') format('woff'),
url('fontello.ttf?tWLiAlAX5i') format('truetype'),
url('fontello.svg?tWLiAlAX5i#fontello') format('svg');
src: url('fontello.eot?fFS2CGH95j');
src: url('fontello.eot?fFS2CGH95j#iefix') format('embedded-opentype'),
url('fontello.woff2?fFS2CGH95j') format('woff2'),
url('fontello.woff?fFS2CGH95j') format('woff'),
url('fontello.ttf?fFS2CGH95j') format('truetype'),
url('fontello.svg?fFS2CGH95j#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@ -15,7 +15,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
src: url('fontello.svg?tWLiAlAX5i#fontello') format('svg');
src: url('fontello.svg?fFS2CGH95j#fontello') format('svg');
}
}
*/
@ -59,35 +59,36 @@
font-size: 2rem;
}
.icon-pencil-1:before { content: '\e800'; } /* '' */
.icon-archive:before { content: '\e800'; } /* '' */
.icon-sharex:before { content: '\e801'; } /* '' */
.icon-upload-cloud:before { content: '\e802'; } /* '' */
.icon-picture-1:before { content: '\e803'; } /* '' */
.icon-th-list:before { content: '\e804'; } /* '' */
.icon-trash:before { content: '\e805'; } /* '' */
.icon-th-large:before { content: '\e806'; } /* '' */
.icon-arrows-cw:before { content: '\e807'; } /* '' */
.icon-plus:before { content: '\e808'; } /* '' */
.icon-cancel:before { content: '\e809'; } /* '' */
.icon-archive:before { content: '\e80a'; } /* '' */
.icon-clipboard-1:before { content: '\e80b'; } /* '' */
.icon-login:before { content: '\e80c'; } /* '' */
.icon-home:before { content: '\e80d'; } /* '' */
.icon-download:before { content: '\e80e'; } /* '' */
.icon-help-circled:before { content: '\e80f'; } /* '' */
.icon-picture:before { content: '\e802'; } /* '' */
.icon-th-list:before { content: '\e803'; } /* '' */
.icon-trash:before { content: '\e804'; } /* '' */
.icon-cancel:before { content: '\e805'; } /* '' */
.icon-arrows-cw:before { content: '\e806'; } /* '' */
.icon-plus:before { content: '\e807'; } /* '' */
.icon-clipboard:before { content: '\e808'; } /* '' */
.icon-login:before { content: '\e809'; } /* '' */
.icon-home:before { content: '\e80a'; } /* '' */
.icon-gauge:before { content: '\e80b'; } /* '' */
.icon-help-circled:before { content: '\e80d'; } /* '' */
.icon-github-circled:before { content: '\e80e'; } /* '' */
.icon-pencil:before { content: '\e80f'; } /* '' */
.icon-terminal:before { content: '\e810'; } /* '' */
.icon-hammer:before { content: '\e811'; } /* '' */
.icon-block:before { content: '\e812'; } /* '' */
.icon-link:before { content: '\e813'; } /* '' */
.icon-cog-alt:before { content: '\e814'; } /* '' */
.icon-floppy:before { content: '\e815'; } /* '' */
.icon-user-plus:before { content: '\e816'; } /* '' */
.icon-privatebin:before { content: '\e817'; } /* '' */
.icon-github-circled:before { content: '\f09b'; } /* '' */
.icon-upload-cloud:before { content: '\e819'; } /* '' */
.icon-th-large:before { content: '\e81a'; } /* '' */
.icon-download:before { content: '\e81b'; } /* '' */
.icon-gatsby:before { content: '\e81c'; } /* '' */
.icon-filter:before { content: '\f0b0'; } /* '' */
.icon-docs:before { content: '\f0c5'; } /* '' */
.icon-gauge:before { content: '\f0e4'; } /* '' */
.icon-doc-inv:before { content: '\f15b'; } /* '' */
.icon-paper-plane-empty:before { content: '\f1d9'; } /* '' */
.icon-user-plus:before { content: '\f234'; } /* '' */
.icon-paper-plane:before { content: '\f1d8'; } /* '' */
.icon-chrome:before { content: '\f268'; } /* '' */
.icon-firefox:before { content: '\f269'; } /* '' */

Binary file not shown.

View File

@ -6,37 +6,35 @@
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="pencil-1" unicode="&#xe800;" d="M0-143l68 343 274-273z m137 392l422 422 259-260-421-422z m531 494q2 39 31 69t69 31 66-25l131-131q25-26 24-66t-30-69-69-30-66 24l-131 131q-27 27-25 66z" horiz-adv-x="989" />
<glyph glyph-name="archive" unicode="&#xe800;" d="M840 600l0-50-696 0 0 50q0 22 13 35t25 15l608 0q6 0 14-1t22-14 14-35z m-148 150q6 0 14-1t22-14 14-35l-498 0q0 22 13 35t25 15l410 0z m248-200q34-32 38-46 6-18 0-54l-76-450q-4-22-20-35t-28-15l-710 0q-52 0-60 50-6 26-39 223t-39 227q-10 22-3 44t10 26 21 20l10 10 30 30 0-80 836 0 0 80z m-248-270l0 100-70 0 0-80-260 0 0 80-68 0 0-100q0-50 48-50l300 0q22 0 35 12t13 24z" horiz-adv-x="981" />
<glyph glyph-name="sharex" unicode="&#xe801;" d="M328-73c-98 10-183 74-229 171-52 110-43 246 24 346 44 66 107 110 181 126 21 4 70 4 91 0 45-10 86-30 120-59 7-5 12-10 12-10-1 0-10-2-20-4-122-17-223-98-257-205-10-29-12-45-12-79 0-34 2-50 12-80 14-41 35-75 70-109 32-33 64-55 107-72l16-7-7-3c-12-5-45-13-65-15-20-2-25-2-43 0z m248-11c-64 5-121 24-170 56-66 44-110 108-126 182-4 21-4 70 1 91 9 45 29 86 58 120 5 7 10 12 10 12 1-1 2-10 4-20 17-122 98-223 205-257 29-10 45-12 79-12 46 0 74 7 117 28 62 31 115 90 144 161l7 16 3-7c10-23 18-74 16-99-8-103-72-190-172-238-53-25-120-38-176-33z m42 212c-45 7-90 27-127 55-20 16-20 17-9 18 129 16 233 97 268 207 10 29 12 45 12 79 0 46-7 74-28 117-30 61-88 114-157 142-13 6-19 9-17 10 4 3 35 12 50 14 24 5 42 5 62 3 65-7 122-35 170-85 24-25 39-47 55-78 22-43 33-84 37-134 6-77-15-157-56-220-44-65-107-109-180-125-15-4-64-5-80-3z m31 204c-16 129-97 233-207 268-29 10-45 12-79 12-44 0-72-7-112-25-30-15-51-30-77-56-33-33-55-65-72-108l-7-16-3 7c-10 23-18 74-16 99 9 103 72 190 172 238 81 39 178 44 264 16 38-12 67-27 98-50 55-42 95-103 109-169 4-18 6-57 3-76-6-47-25-92-55-131-16-20-16-20-18-9z" horiz-adv-x="1000" />
<glyph glyph-name="upload-cloud" unicode="&#xe802;" d="M781 506q108 0 184-76t76-184-76-184-184-77l-208 0 0 239 67-66q16-17 38-17 20 0 36 17 15 15 15 36t-15 36l-156 156q-14 14-37 15t-37-15l-156-156q-15-15-15-36t15-36q16-17 37-17 20 0 36 17l68 66 0-239-260 0q-86 0-148 61t-61 148q0 72 44 128t112 73l0 8q0 130 92 221t221 91q100 0 180-58t114-152q2 0 8 1t10 0z" horiz-adv-x="1041" />
<glyph glyph-name="picture" unicode="&#xe802;" d="M0-68l0 836 1000 0 0-836-1000 0z m76 78l848 0 0 680-848 0 0-680z m90 80l0 59 150 195 102-86 193 291 223-228 0-231-668 0z m0 416q0 37 24 62t62 24q33 0 58-24t24-62q0-33-24-57t-58-25q-37 0-62 25t-24 57z" horiz-adv-x="1000" />
<glyph glyph-name="picture-1" unicode="&#xe803;" d="M0-68l0 836 1000 0 0-836-1000 0z m76 78l848 0 0 680-848 0 0-680z m90 80l0 59 150 195 102-86 193 291 223-228 0-231-668 0z m0 416q0 37 24 62t62 24q33 0 58-24t24-62q0-33-24-57t-58-25q-37 0-62 25t-24 57z" horiz-adv-x="1000" />
<glyph glyph-name="th-list" unicode="&#xe803;" d="M0-150l0 250 250 0 0-250-250 0z m0 375l0 250 250 0 0-250-250 0z m0 375l0 250 250 0 0-250-250 0z m391-750l0 250 609 0 0-250-609 0z m0 375l0 250 609 0 0-250-609 0z m0 375l0 250 609 0 0-250-609 0z" horiz-adv-x="1000" />
<glyph glyph-name="th-list" unicode="&#xe804;" d="M860 90q43 0 73-31t31-74q0-43-31-73t-73-31l-365 0q-44 0-74 31t-31 73 31 74 74 31l365 0z m0 364q43 0 73-31t31-73-31-73-73-31l-365 0q-44 0-74 31t-31 73 31 73 74 31l365 0z m0 365q43 0 73-31t31-73q0-44-31-74t-73-31l-365 0q-42 0-74 31t-31 74 31 73 74 31l365 0z m-860-834q0 130 130 130t130-130-130-130-130 130z m0 365q0 130 130 130t130-130-130-130-130 130z m0 365q0 130 130 130t130-130-130-130-130 130z" horiz-adv-x="964" />
<glyph glyph-name="trash" unicode="&#xe804;" d="M0 633l0 141 289 0 0 76 246 0 0-76 289 0 0-141-824 0z m43-783l0 676 738 0 0-676-738 0z" horiz-adv-x="824" />
<glyph glyph-name="trash" unicode="&#xe805;" d="M0 633l0 141 289 0 0 76 246 0 0-76 289 0 0-141-824 0z m43-783l0 676 738 0 0-676-738 0z" horiz-adv-x="824" />
<glyph glyph-name="cancel" unicode="&#xe805;" d="M0 71l279 279-279 279 221 221 279-279 279 279 221-221-279-279 279-279-221-221-279 279-279-279z" horiz-adv-x="1000" />
<glyph glyph-name="th-large" unicode="&#xe806;" d="M0 663q0 65 46 110t110 46l104 0q65 0 111-46t45-110l0-104q0-65-45-111t-111-45l-104 0q-65 0-110 45t-46 111l0 104z m521 0q0 65 46 110t111 46l103 0q65 0 111-46t46-110l0-104q0-65-46-111t-111-45l-103 0q-65 0-111 45t-46 111l0 104z m-521-521q0 65 46 110t110 46l104 0q65 0 111-46t45-110l0-104q0-65-45-111t-111-46l-104 0q-65 0-110 46t-46 111l0 104z m521 0q0 65 46 110t111 46l103 0q65 0 111-46t46-110l0-104q0-65-46-111t-111-46l-103 0q-65 0-111 46t-46 111l0 104z" horiz-adv-x="938" />
<glyph glyph-name="arrows-cw" unicode="&#xe806;" d="M843 261q0-3 0-4-36-150-150-243t-267-93q-81 0-157 31t-136 88l-72-72q-11-11-25-11t-25 11-11 25v250q0 14 11 25t25 11h250q14 0 25-11t10-25-10-25l-77-77q40-36 90-57t105-20q74 0 139 37t104 99q6 10 30 66 4 13 16 13h107q8 0 13-6t5-12z m14 446v-250q0-14-10-25t-26-11h-250q-14 0-25 11t-10 25 10 25l77 77q-82 77-194 77-75 0-140-37t-104-99q-6-10-29-66-5-13-17-13h-111q-7 0-13 6t-5 12v4q36 150 151 243t268 93q81 0 158-31t137-88l72 72q11 11 25 11t26-11 10-25z" horiz-adv-x="857.1" />
<glyph glyph-name="arrows-cw" unicode="&#xe807;" d="M843 261q0-3 0-4-36-150-150-243t-267-93q-81 0-157 31t-136 88l-72-72q-11-11-25-11t-25 11-11 25v250q0 14 11 25t25 11h250q14 0 25-11t10-25-10-25l-77-77q40-36 90-57t105-20q74 0 139 37t104 99q6 10 30 66 4 13 16 13h107q8 0 13-6t5-12z m14 446v-250q0-14-10-25t-26-11h-250q-14 0-25 11t-10 25 10 25l77 77q-82 77-194 77-75 0-140-37t-104-99q-6-10-29-66-5-13-17-13h-111q-7 0-13 6t-5 12v4q36 150 151 243t268 93q81 0 158-31t137-88l72 72q11 11 25 11t26-11 10-25z" horiz-adv-x="857.1" />
<glyph glyph-name="plus" unicode="&#xe807;" d="M0 209l0 282 359 0 0 359 282 0 0-359 359 0 0-282-359 0 0-359-282 0 0 359-359 0z" horiz-adv-x="1000" />
<glyph glyph-name="plus" unicode="&#xe808;" d="M0 209l0 282 359 0 0 359 282 0 0-359 359 0 0-282-359 0 0-359-282 0 0 359-359 0z" horiz-adv-x="1000" />
<glyph glyph-name="clipboard" unicode="&#xe808;" d="M678 819q65 0 110-46t46-110l0-625q0-65-46-111t-110-46l-522 0q-65 0-110 46t-46 111l0 625q0 65 46 110t110 46l522 0z m-418-104l0-52q0-21 16-37t37-16l208 0q22 0 37 16t15 37l0 52-313 0z m469-677l0 625q0 21-15 37t-36 15l-53 0 0-52q0-43-30-73t-74-31l-208 0q-43 0-74 31t-30 73l0 52-53 0q-21 0-37-15t-15-37l0-625q0-21 15-37t37-16l522 0q21 0 36 16t15 37z m-104 52l-416 0q-26 0-26 25 0 12 7 19t19 8l416 0q11 0 19-8t7-19q0-25-26-25z m0 157l-416 0q-11 0-19 7t-7 19q0 25 26 25l416 0q26 0 26-25 0-11-7-19t-19-7z m0 156l-416 0q-26 0-26 25 0 11 7 19t19 7l416 0q11 0 19-7t7-19q0-25-26-25z" horiz-adv-x="834" />
<glyph glyph-name="cancel" unicode="&#xe809;" d="M0 71l279 279-279 279 221 221 279-279 279 279 221-221-279-279 279-279-221-221-279 279-279-279z" horiz-adv-x="1000" />
<glyph glyph-name="login" unicode="&#xe809;" d="M661 350q0-14-11-25l-303-304q-11-10-26-10t-25 10-10 25v161h-250q-15 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 10 25t25 10 26-10l303-304q11-10 11-25z m196 196v-392q0-67-47-114t-114-47h-178q-7 0-13 5t-5 13q0 2-1 11t0 15 2 13 5 11 12 3h178q37 0 64 27t26 63v392q0 37-26 64t-64 26h-174t-6 0-6 2-5 3-4 5-1 8q0 2-1 11t0 15 2 13 5 11 12 3h178q67 0 114-47t47-114z" horiz-adv-x="857.1" />
<glyph glyph-name="archive" unicode="&#xe80a;" d="M840 600l0-50-696 0 0 50q0 22 13 35t25 15l608 0q6 0 14-1t22-14 14-35z m-148 150q6 0 14-1t22-14 14-35l-498 0q0 22 13 35t25 15l410 0z m248-200q34-32 38-46 6-18 0-54l-76-450q-4-22-20-35t-28-15l-710 0q-52 0-60 50-6 26-39 223t-39 227q-10 22-3 44t10 26 21 20l10 10 30 30 0-80 836 0 0 80z m-248-270l0 100-70 0 0-80-260 0 0 80-68 0 0-100q0-50 48-50l300 0q22 0 35 12t13 24z" horiz-adv-x="981" />
<glyph glyph-name="home" unicode="&#xe80a;" d="M786 296v-267q0-15-11-25t-25-11h-214v214h-143v-214h-214q-15 0-25 11t-11 25v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-3-7 1-12 6l-35 41q-4 6-3 13t6 12l401 334q18 15 42 15t43-15l136-113v108q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q6-4 6-12t-4-13z" horiz-adv-x="928.6" />
<glyph glyph-name="clipboard-1" unicode="&#xe80b;" d="M678 819q65 0 110-46t46-110l0-625q0-65-46-111t-110-46l-522 0q-65 0-110 46t-46 111l0 625q0 65 46 110t110 46l522 0z m-418-104l0-52q0-21 16-37t37-16l208 0q22 0 37 16t15 37l0 52-313 0z m469-677l0 625q0 21-15 37t-36 15l-53 0 0-52q0-43-30-73t-74-31l-208 0q-43 0-74 31t-30 73l0 52-53 0q-21 0-37-15t-15-37l0-625q0-21 15-37t37-16l522 0q21 0 36 16t15 37z m-104 52l-416 0q-26 0-26 25 0 12 7 19t19 8l416 0q11 0 19-8t7-19q0-25-26-25z m0 157l-416 0q-11 0-19 7t-7 19q0 25 26 25l416 0q26 0 26-25 0-11-7-19t-19-7z m0 156l-416 0q-26 0-26 25 0 11 7 19t19 7l416 0q11 0 19-7t7-19q0-25-26-25z" horiz-adv-x="834" />
<glyph glyph-name="gauge" unicode="&#xe80b;" d="M214 207q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m107 250q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m239-268l57 213q3 14-5 27t-21 16-27-3-17-22l-56-213q-33-3-60-25t-35-55q-11-43 11-81t66-50 81 11 50 66q9 33-4 65t-40 51z m369 18q0 30-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m-358 357q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m250-107q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m179-250q0-145-79-269-10-17-30-17h-782q-20 0-30 17-79 123-79 269 0 102 40 194t106 160 160 107 194 39 194-39 160-107 106-160 40-194z" horiz-adv-x="1000" />
<glyph glyph-name="login" unicode="&#xe80c;" d="M661 350q0-14-11-25l-303-304q-11-10-26-10t-25 10-10 25v161h-250q-15 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 10 25t25 10 26-10l303-304q11-10 11-25z m196 196v-392q0-67-47-114t-114-47h-178q-7 0-13 5t-5 13q0 2-1 11t0 15 2 13 5 11 12 3h178q37 0 64 27t26 63v392q0 37-26 64t-64 26h-174t-6 0-6 2-5 3-4 5-1 8q0 2-1 11t0 15 2 13 5 11 12 3h178q67 0 114-47t47-114z" horiz-adv-x="857.1" />
<glyph glyph-name="help-circled" unicode="&#xe80d;" d="M500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-13 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-15-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
<glyph glyph-name="home" unicode="&#xe80d;" d="M786 296v-267q0-15-11-25t-25-11h-214v214h-143v-214h-214q-15 0-25 11t-11 25v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-3-7 1-12 6l-35 41q-4 6-3 13t6 12l401 334q18 15 42 15t43-15l136-113v108q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q6-4 6-12t-4-13z" horiz-adv-x="928.6" />
<glyph glyph-name="github-circled" unicode="&#xe80e;" d="M429 779q116 0 215-58t156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17q0 1 0 43t0 75q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 67-44 115 21 51-4 114-16 5-46-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-47 7q-25-63-5-114-44-48-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-21-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l6-13q7-21 24-34t37-17 39-3 31 1l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58z m-267-616q2 4-3 7-6 1-8-1-1-4 4-7 5-3 7 1z m18-19q4 3-1 9-6 5-9 2-4-3 1-9 5-6 9-2z m16-25q6 4 0 11-4 7-9 3-5-3 0-10t9-4z m24-23q4 4-2 10-7 7-11 2-5-5 2-11 6-6 11-1z m32-14q1 6-8 9-8 2-10-4t7-9q8-3 11 4z m35-3q0 7-10 6-9 0-9-6 0-7 10-6 9 0 9 6z m32 5q-1 7-10 5-9-1-8-8t10-4 8 7z" horiz-adv-x="857.1" />
<glyph glyph-name="download" unicode="&#xe80e;" d="M714 100q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-39l-250-250q-10-11-25-11t-25 11l-250 250q-17 16-8 39 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
<glyph glyph-name="help-circled" unicode="&#xe80f;" d="M500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-13 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-15-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
<glyph glyph-name="pencil" unicode="&#xe80f;" d="M0-143l68 343 274-273z m137 392l422 422 259-260-421-422z m531 494q2 39 31 69t69 31 66-25l131-131q25-26 24-66t-30-69-69-30-66 24l-131 131q-27 27-25 66z" horiz-adv-x="989" />
<glyph glyph-name="terminal" unicode="&#xe810;" d="M929 779h-858c-39 0-71-32-71-72v-714c0-40 32-72 71-72h858c39 0 71 32 71 72v714c0 40-32 72-71 72z m-786-500l143 142-143 143 71 72 215-215-215-214-71 72z m571-72h-285v72h285v-72z" horiz-adv-x="1000" />
@ -50,21 +48,25 @@
<glyph glyph-name="floppy" unicode="&#xe815;" d="M214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-7 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z" horiz-adv-x="857.1" />
<glyph glyph-name="user-plus" unicode="&#xe816;" d="M393 350q-89 0-152 63t-62 151 62 152 152 63 151-63 63-152-63-151-151-63z m536-71h196q7 0 13-6t5-12v-107q0-8-5-13t-13-5h-196v-197q0-7-6-12t-12-6h-107q-8 0-13 6t-5 12v197h-197q-7 0-12 5t-6 13v107q0 7 6 12t12 6h197v196q0 7 5 13t13 5h107q7 0 12-5t6-13v-196z m-411-125q0-29 21-51t50-21h143v-133q-38-28-95-28h-488q-67 0-108 39t-41 106q0 30 2 58t8 61 15 60 24 55 34 45 48 30 62 11q11 0 22-10 44-34 86-51t92-17 92 17 86 51q11 10 22 10 73 0 121-54h-125q-29 0-50-21t-21-50v-107z" horiz-adv-x="1142.9" />
<glyph glyph-name="privatebin" unicode="&#xe817;" d="M484-131c-7 4-107 58-221 121-151 82-209 115-211 118-2 4-2 48-1 245 1 221 2 240 5 243 2 2 101 57 221 122 151 82 220 118 224 118 4 0 15-4 27-11 12-7 110-61 219-120 143-78 199-109 201-113 2-4 2-48 1-245-1-221-1-240-5-243-3-4-436-239-442-241-2 0-9 2-18 6z m138 213c0 1-8 31-17 67-31 119-46 187-48 216l-2 19 21 21c37 39 56 74 58 105 0 13 0 18-4 28-9 25-37 53-67 67-50 24-102 18-142-16-34-28-51-62-48-96 2-28 17-55 49-87 11-11 21-22 21-25 2-9 0-38-6-67-7-34-29-123-46-184-7-26-13-48-13-49 0 0 55-1 122-1 78 0 122 1 122 2z" horiz-adv-x="1000" />
<glyph glyph-name="github-circled" unicode="&#xf09b;" d="M429 779q116 0 215-58t156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17q0 1 0 43t0 75q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 67-44 115 21 51-4 114-16 5-46-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-47 7q-25-63-5-114-44-48-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-21-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l6-13q7-21 24-34t37-17 39-3 31 1l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58z m-267-616q2 4-3 7-6 1-8-1-1-4 4-7 5-3 7 1z m18-19q4 3-1 9-6 5-9 2-4-3 1-9 5-6 9-2z m16-25q6 4 0 11-4 7-9 3-5-3 0-10t9-4z m24-23q4 4-2 10-7 7-11 2-5-5 2-11 6-6 11-1z m32-14q1 6-8 9-8 2-10-4t7-9q8-3 11 4z m35-3q0 7-10 6-9 0-9-6 0-7 10-6 9 0 9 6z m32 5q-1 7-10 5-9-1-8-8t10-4 8 7z" horiz-adv-x="857.1" />
<glyph glyph-name="upload-cloud" unicode="&#xe819;" d="M760 494q100 0 170-68t70-166-70-166-170-68l-190 0 0 190 106 0-176 230-174-230 104 0 0-190-248 0q-74 0-128 52t-54 124q0 74 53 126t129 52q14 0 20-2-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z" horiz-adv-x="1000" />
<glyph glyph-name="th-large" unicode="&#xe81a;" d="M0-150l0 438 438 0 0-438-438 0z m0 563l0 437 438 0 0-437-438 0z m563-563l0 438 437 0 0-438-437 0z m0 563l0 437 437 0 0-437-437 0z" horiz-adv-x="1000" />
<glyph glyph-name="download" unicode="&#xe81b;" d="M714 100q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-39l-250-250q-10-11-25-11t-25 11l-250 250q-17 16-8 39 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
<glyph glyph-name="gatsby" unicode="&#xe81c;" d="M500 817c-257 0-467-210-467-467s210-467 467-467 467 210 467 467-210 467-467 467z m-260-727c-70 70-107 163-107 253l364-360c-94 4-187 37-257 107z m340-97l-437 437c37 163 184 287 357 287 123 0 230-60 297-150l-50-44c-57 77-147 127-247 127-130 0-240-83-283-200l383-383c97 33 170 116 193 216h-160v67h234c0-173-124-320-287-357z" horiz-adv-x="1000" />
<glyph glyph-name="filter" unicode="&#xf0b0;" d="M783 685q9-22-8-39l-275-275v-414q0-23-22-33-7-3-14-3-15 0-25 11l-143 143q-10 11-10 25v271l-275 275q-18 17-8 39 9 22 33 22h714q23 0 33-22z" horiz-adv-x="785.7" />
<glyph glyph-name="docs" unicode="&#xf0c5;" d="M946 636q23 0 38-16t16-38v-678q0-23-16-38t-38-16h-535q-23 0-38 16t-16 38v160h-303q-23 0-38 16t-16 38v375q0 22 11 49t27 42l228 228q15 16 42 27t49 11h232q23 0 38-16t16-38v-183q38 23 71 23h232z m-303-119l-167-167h167v167z m-357 214l-167-167h167v167z m109-361l176 176v233h-214v-233q0-22-15-37t-38-16h-233v-357h286v143q0 22 11 49t27 42z m534-449v643h-215v-232q0-22-15-38t-38-15h-232v-358h500z" horiz-adv-x="1000" />
<glyph glyph-name="gauge" unicode="&#xf0e4;" d="M214 207q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m107 250q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m239-268l57 213q3 14-5 27t-21 16-27-3-17-22l-56-213q-33-3-60-25t-35-55q-11-43 11-81t66-50 81 11 50 66q9 33-4 65t-40 51z m369 18q0 30-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m-358 357q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m250-107q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m179-250q0-145-79-269-10-17-30-17h-782q-20 0-30 17-79 123-79 269 0 102 40 194t106 160 160 107 194 39 194-39 160-107 106-160 40-194z" horiz-adv-x="1000" />
<glyph glyph-name="doc-inv" unicode="&#xf15b;" d="M571 564v264q13-8 21-16l227-228q8-7 16-20h-264z m-71-18q0-22 16-37t38-16h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304z" horiz-adv-x="857.1" />
<glyph glyph-name="paper-plane-empty" unicode="&#xf1d9;" d="M984 844q19-13 15-36l-142-857q-3-16-18-25-8-5-18-5-6 0-13 3l-294 120-166-182q-10-12-27-12-7 0-12 2-11 4-17 13t-6 21v252l-264 108q-20 8-22 30-2 22 18 33l928 536q20 12 38-1z m-190-837l123 739-800-462 187-76 482 356-267-444z" horiz-adv-x="1000" />
<glyph glyph-name="user-plus" unicode="&#xf234;" d="M393 350q-89 0-152 63t-62 151 62 152 152 63 151-63 63-152-63-151-151-63z m536-71h196q7 0 13-6t5-12v-107q0-8-5-13t-13-5h-196v-197q0-7-6-12t-12-6h-107q-8 0-13 6t-5 12v197h-197q-7 0-12 5t-6 13v107q0 7 6 12t12 6h197v196q0 7 5 13t13 5h107q7 0 12-5t6-13v-196z m-411-125q0-29 21-51t50-21h143v-133q-38-28-95-28h-488q-67 0-108 39t-41 106q0 30 2 58t8 61 15 60 24 55 34 45 48 30 62 11q11 0 22-10 44-34 86-51t92-17 92 17 86 51q11 10 22 10 73 0 121-54h-125q-29 0-50-21t-21-50v-107z" horiz-adv-x="1142.9" />
<glyph glyph-name="paper-plane" unicode="&#xf1d8;" d="M984 844q19-13 15-36l-142-857q-3-16-18-25-8-5-18-5-6 0-13 3l-253 104-135-165q-10-13-27-13-7 0-12 2-11 4-17 13t-7 21v195l482 590-596-516-221 91q-20 8-22 30-1 23 18 33l928 536q9 5 18 5 11 0 20-6z" horiz-adv-x="1000" />
<glyph glyph-name="chrome" unicode="&#xf268;" d="M498 850q134 1 252-67 130-75 196-208l-414 22q-89 5-164-41t-103-128l-154 236q72 89 174 137t213 49z m-416-226l188-370q40-80 117-121t164-25l-129-252q-118 19-214 88t-152 176-56 230q0 149 82 274z m885-94q32-84 33-174t-27-170-86-152-137-117q-128-74-278-66l226 347q49 73 46 162t-59 155z m-467-11q70 0 119-50t50-119-50-119-119-49-119 49-49 119 49 119 119 50z" horiz-adv-x="1000" />

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,9 @@
const config = require('./../config')
const db = require('knex')(config.database)
const routes = require('express').Router()
const path = require('path')
const paths = require('./../controllers/pathsController')
const routes = require('express').Router()
const utils = require('./../controllers/utilsController')
const config = require('./../config')
const db = require('knex')(config.database)
const homeDomain = config.homeDomain || config.domain

View File

@ -1,10 +1,10 @@
const config = require('./../config')
const routes = require('express').Router()
const uploadController = require('./../controllers/uploadController')
const albumsController = require('./../controllers/albumsController')
const tokenController = require('./../controllers/tokenController')
const authController = require('./../controllers/authController')
const tokenController = require('./../controllers/tokenController')
const uploadController = require('./../controllers/uploadController')
const utilsController = require('./../controllers/utilsController')
const config = require('./../config')
routes.get('/check', (req, res, next) => {
return res.json({

View File

@ -1,7 +1,7 @@
const config = require('./../config')
const routes = require('express').Router()
const uploadController = require('./../controllers/uploadController')
const utils = require('./../controllers/utilsController')
const config = require('./../config')
const renderOptions = {
uploadDisabled: false,

View File

@ -1,13 +0,0 @@
module.exports = {
stripIndents (string) {
if (!string) return
const result = string.replace(/^[^\S\n]+/gm, '')
const match = result.match(/^[^\S\n]*(?=\S)/gm)
const indent = match && Math.min(...match.map(el => el.length))
if (indent) {
const regexp = new RegExp(`^.{${indent}}`, 'gm')
return result.replace(regexp, '')
}
return result
}
}

View File

@ -1,4 +1,3 @@
const { stripIndents } = require('./_utils')
const utils = require('./../controllers/utilsController')
;(async () => {
@ -6,7 +5,7 @@ const utils = require('./../controllers/utilsController')
const args = process.argv.slice(2)
if (!args.length || args.includes('--help') || args.includes('-h'))
return console.log(stripIndents(`
return console.log(utils.stripIndents(`
Purge Cloudflare's cache.
Usage:

View File

@ -1,8 +1,8 @@
const { stripIndents } = require('./_utils')
const path = require('path')
const paths = require('../controllers/pathsController')
const utils = require('../controllers/utilsController')
const config = require('./../config')
const db = require('knex')(config.database)
const path = require('path')
const paths = require('./../controllers/pathsController')
const self = {
mode: null
@ -26,7 +26,7 @@ self.getFiles = async directory => {
self.mode = parseInt(args[0]) || 0
if (args.includes('--help') || args.includes('-h'))
return console.log(stripIndents(`
return console.log(utils.stripIndents(`
Clean up files that are not in the database.
Usage:

View File

@ -1,5 +1,4 @@
const { stripIndents } = require('./_utils')
const utils = require('./../controllers/utilsController')
const utils = require('../controllers/utilsController')
const self = {
mode: null
@ -12,7 +11,7 @@ const self = {
self.mode = parseInt(args[0]) || 0
if (args.includes('--help') || args.includes('-h'))
return console.log(stripIndents(`
return console.log(utils.stripIndents(`
Bulk delete expired files.
Usage:

View File

@ -1,7 +1,6 @@
const { stripIndents } = require('./_utils')
const path = require('path')
const paths = require('./../controllers/pathsController')
const utils = require('./../controllers/utilsController')
const paths = require('../controllers/pathsController')
const utils = require('../controllers/utilsController')
const self = {
mode: null,
@ -40,7 +39,7 @@ self.getFiles = async directory => {
![0, 1].includes(self.verbose) ||
args.includes('--help') ||
args.includes('-h'))
return console.log(stripIndents(`
return console.log(utils.stripIndents(`
Generate thumbnails.
Usage :

View File

@ -1,10 +1,8 @@
body {
-webkit-animation: none;
animation: none
}
#dashboard {
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
@ -13,12 +11,7 @@ body {
}
.menu-list a {
color: #3794d2;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
color: #3794d2
}
.menu-list a:hover {
@ -48,15 +41,17 @@ ul#albumsContainer {
ul#albumsContainer li {
border-left: 1px solid #898b8d;
padding-left: 0.75em;
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
#page.fade-in {
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
.pagination {
margin-bottom: 1.25rem
}
.pagination a:not([disabled]) {
color: #eff0f1;
border-color: #4d4d4d;
@ -118,10 +113,6 @@ li[data-action="page-ellipsis"] {
min-width: 0
}
.table-container {
overflow-x: auto
}
.table {
color: #bdc3c7;
background-color: #31363b;
@ -163,3 +154,11 @@ li[data-action="page-ellipsis"] {
.is-linethrough {
text-decoration: line-through
}
#menu.is-loading li a {
cursor: progress
}
#statistics tr *:nth-child(2) {
min-width: 50%
}

View File

@ -4,19 +4,12 @@
border-radius: 100%;
display: inline-block;
margin-bottom: 40px;
position: relative;
vertical-align: top;
-webkit-animation-delay: 0.5s;
animation-delay: 0.5s;
-webkit-animation-duration: 1.5s;
animation-duration: 1.5s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-name: floatUp;
animation-name: floatUp;
-webkit-animation-timing-function: cubic-bezier(0, 0.71, 0.29, 1);
animation-timing-function: cubic-bezier(0, 0.71, 0.29, 1);
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2)
}
@ -38,15 +31,11 @@
}
.dz-preview .dz-details {
display: -webkit-box;
display: -ms-flexbox;
display: flex
}
.dz-preview .dz-details .dz-size,
.dz-preview .dz-details .dz-filename {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1
}
@ -59,9 +48,7 @@
@-webkit-keyframes floatUp {
0% {
opacity: 0;
-webkit-box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0);
box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0);
-webkit-transform: scale(0.86);
transform: scale(0.86)
}
@ -70,16 +57,12 @@
}
67% {
-webkit-box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
-webkit-transform: scale(1);
transform: scale(1)
}
100% {
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
-webkit-transform: scale(1);
transform: scale(1)
}
}
@ -87,9 +70,7 @@
@keyframes floatUp {
0% {
opacity: 0;
-webkit-box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0);
box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0), 0 0 0 rgba(10, 10, 10, 0);
-webkit-transform: scale(0.86);
transform: scale(0.86)
}
@ -98,22 +79,17 @@
}
67% {
-webkit-box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
box-shadow: 0 0 0 rgba(10, 10, 10, 0), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
-webkit-transform: scale(1);
transform: scale(1)
}
100% {
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
-webkit-transform: scale(1);
transform: scale(1)
}
}
.uploads > div {
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s;
margin: 1rem
}
@ -126,11 +102,11 @@
margin-bottom: 0
}
.uploads .icon:not(.icon-block) {
.uploads .field > .icon:not(.icon-block) {
color: #3794d2
}
.uploads .icon.icon-block {
.uploads .field > .icon.icon-block {
color: #da4453
}
@ -158,7 +134,6 @@
}
#albumDiv {
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
@ -170,7 +145,6 @@
margin-top: -0.25rem;
margin-left: -0.25rem;
margin-right: -0.25rem;
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
@ -190,7 +164,6 @@
#tabs {
margin-bottom: 1rem;
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
@ -216,7 +189,6 @@
.tab-content {
margin-bottom: -0.75rem;
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
@ -247,7 +219,6 @@
border-bottom-right-radius: 0;
right: 1%;
opacity: 0.25;
-webkit-transition: opacity 0.25s;
transition: opacity 0.25s
}

View File

@ -5,7 +5,6 @@ html {
body {
color: #eff0f1;
-webkit-animation: fadeInOpacity 0.5s;
animation: fadeInOpacity 0.5s
}
@ -103,30 +102,11 @@ code,
color: #7f8c8d
}
.button.is-breeze {
background-color: #3794d2;
border-color: transparent;
color: #fff
}
.button.is-breeze.is-hovered,
.button.is-breeze:hover {
background-color: #60a8dc;
border-color: transparent;
color: #fff
}
.button.is-breeze.is-active,
.button.is-breeze:active {
background-color: #60a8dc;
border-color: transparent;
color: #fff
}
.button.is-breeze.is-focus,
.button.is-breeze:focus {
border-color: transparent;
color: #fff
.button.is-info.is-hovered [class^="icon-"]::before,
.button.is-info.is-hovered [class*=" icon-"]::before,
.button.is-info:hover [class^="icon-"]::before,
.button.is-info:hover [class*=" icon-"]::before {
fill: #fff
}
.checkbox:hover,
@ -134,11 +114,6 @@ code,
color: #7f8c8d
}
.progress.is-breeze:indeterminate {
background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #60a8dc), color-stop(30%, #eff0f1));
background-image: linear-gradient(to right, #60a8dc 30%, #eff0f1 30%)
}
.message {
background-color: #31363b
}
@ -146,6 +121,20 @@ code,
.message-body {
color: #eff0f1;
border: 0;
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2)
}
.menu-list a.is-loading::after {
animation: spinAround 0.5s infinite linear;
border: 2px solid #dbdbdb;
border-radius: 290486px;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: block;
height: 1em;
width: 1em;
right: calc(0% + (1em / 2));
top: calc(50% - (1em / 2));
position: absolute !important
}

View File

@ -41,7 +41,6 @@
}
.swal-button:focus {
-webkit-box-shadow: 0 0 0 1px #31363b, 0 0 0 3px rgba(55, 148, 210, 0.29);
box-shadow: 0 0 0 1px #31363b, 0 0 0 3px rgba(55, 148, 210, 0.29)
}
@ -72,14 +71,12 @@
.swal-icon--warning {
border-color: #f67400;
-webkit-animation: pulseWarning 0.5s infinite alternate;
animation: pulseWarning 0.5s infinite alternate
}
.swal-icon--warning__body,
.swal-icon--warning__dot {
background-color: #f67400;
-webkit-animation: pulseWarningBody 0.5s infinite alternate;
animation: pulseWarningBody 0.5s infinite alternate
}
@ -143,13 +140,7 @@
.swal-display-thumb-container {
min-width: 200px;
min-height: 200px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center
}

View File

@ -1,17 +1,11 @@
.image-container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
width: 200px;
height: 200px;
margin: 9px;
background-color: #31363b;
overflow: hidden;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
position: relative;
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2)
}
@ -21,16 +15,10 @@
}
.image-container .image {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
height: 100%;
width: 100%;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center
}
@ -42,8 +30,6 @@
}
.image-container .controls {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: absolute;
top: 0.75rem;

View File

@ -1,13 +1,15 @@
{
"root": true,
"parserOptions": {
"ecmaVersion": 6
"ecmaVersion": 6,
"sourceType": "script"
},
"env": {
"browser": true
},
"extends": [
"standard"
"standard",
"plugin:compat/recommended"
],
"rules": {
"curly": [

View File

@ -7,7 +7,7 @@ const page = {
lazyLoad: null
}
window.onload = function () {
window.onload = () => {
const elements = document.querySelectorAll('.file-size')
for (let i = 0; i < elements.length; i++)
elements[i].innerHTML = page.getPrettyBytes(parseInt(elements[i].innerHTML.replace(/\s*B$/i, '')))

View File

@ -13,7 +13,7 @@ const page = {
pass: null
}
page.do = function (dest) {
page.do = (dest, trigger) => {
const user = page.user.value.trim()
if (!user)
return swal('An error occurred!', 'You need to specify a username.', 'error')
@ -22,32 +22,36 @@ page.do = function (dest) {
if (!pass)
return swal('An error occurred!', 'You need to specify a password.', 'error')
trigger.classList.add('is-loading')
axios.post(`api/${dest}`, {
username: user,
password: pass
}).then(function (response) {
if (response.data.success === false)
}).then(response => {
if (response.data.success === false) {
trigger.classList.remove('is-loading')
return swal(`Unable to ${dest}!`, response.data.description, 'error')
}
localStorage.token = response.data.token
window.location = 'dashboard'
}).catch(function (error) {
}).catch(error => {
console.error(error)
trigger.classList.remove('is-loading')
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
})
}
page.verify = function () {
page.verify = () => {
if (!page.token) return
axios.post('api/tokens/verify', {
token: page.token
}).then(function (response) {
}).then(response => {
if (response.data.success === false)
return swal('An error occurred!', response.data.description, 'error')
window.location = 'dashboard'
}).catch(function (error) {
}).catch(error => {
console.error(error)
const description = error.response.data && error.response.data.description
? error.response.data.description
@ -56,22 +60,22 @@ page.verify = function () {
})
}
window.onload = function () {
window.onload = () => {
page.verify()
page.user = document.querySelector('#user')
page.pass = document.querySelector('#pass')
// Prevent default form's submit action
document.querySelector('#authForm').addEventListener('submit', function (event) {
document.querySelector('#authForm').addEventListener('submit', event => {
event.preventDefault()
})
document.querySelector('#loginBtn').addEventListener('click', function () {
page.do('login')
document.querySelector('#loginBtn').addEventListener('click', event => {
page.do('login', event.currentTarget)
})
document.querySelector('#registerBtn').addEventListener('click', function () {
page.do('register')
document.querySelector('#registerBtn').addEventListener('click', event => {
page.do('register', event.currentTarget)
})
}

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@ const page = {
urlMaxSize: null,
urlMaxSizeBytes: null,
tabs: null,
tabs: [],
activeTab: null,
albumSelect: null,
previewTemplate: null,
@ -43,56 +43,46 @@ const page = {
imageExtensions: ['.webp', '.jpg', '.jpeg', '.bmp', '.gif', '.png', '.svg']
}
page.checkIfPublic = function () {
axios.get('api/check').then(function (response) {
page.private = response.data.private
page.enableUserAccounts = response.data.enableUserAccounts
page.maxSize = parseInt(response.data.maxSize)
page.maxSizeBytes = page.maxSize * 1e6
page.chunkSize = parseInt(response.data.chunkSize)
page.temporaryUploadAges = response.data.temporaryUploadAges
page.fileIdentifierLength = response.data.fileIdentifierLength
page.preparePage()
}).catch(function (error) {
console.error(error)
document.querySelector('#albumDiv').classList.add('is-hidden')
document.querySelector('#tabs').classList.add('is-hidden')
const button = document.querySelector('#loginToUpload')
button.innerText = 'Error occurred. Reload the page?'
button.classList.remove('is-loading')
button.classList.remove('is-hidden')
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
})
page.checkIfPublic = onFailure => {
return axios.get('api/check')
.then(response => {
page.private = response.data.private
page.enableUserAccounts = response.data.enableUserAccounts
page.maxSize = parseInt(response.data.maxSize)
page.maxSizeBytes = page.maxSize * 1e6
page.chunkSize = parseInt(response.data.chunkSize)
page.temporaryUploadAges = response.data.temporaryUploadAges
page.fileIdentifierLength = response.data.fileIdentifierLength
return page.preparePage(onFailure)
})
.catch(onFailure)
}
page.preparePage = function () {
page.preparePage = onFailure => {
if (page.private)
if (page.token) {
return page.verifyToken(page.token, true)
return page.verifyToken(page.token, onFailure, true)
} else {
const button = document.querySelector('#loginToUpload')
button.href = 'auth'
button.classList.remove('is-loading')
if (page.enableUserAccounts)
button.innerText = 'Anonymous upload is disabled. Log in to upload.'
else
button.innerText = 'Running in private mode. Log in to upload.'
}
else
return page.prepareUpload()
return page.prepareUpload(onFailure)
}
page.verifyToken = function (token, reloadOnError) {
if (reloadOnError === undefined) reloadOnError = false
axios.post('api/tokens/verify', { token }).then(function (response) {
page.verifyToken = (token, onFailure, reloadOnError) => {
return axios.post('api/tokens/verify', { token }).then(response => {
if (response.data.success === false)
return swal({
title: 'An error occurred!',
text: response.data.description,
icon: 'error'
}).then(function () {
}).then(() => {
if (!reloadOnError) return
localStorage.removeItem('token')
location.reload()
@ -100,120 +90,113 @@ page.verifyToken = function (token, reloadOnError) {
localStorage.token = token
page.token = token
return page.prepareUpload()
}).catch(function (error) {
console.error(error)
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
})
return page.prepareUpload(onFailure)
}).catch(onFailure)
}
page.prepareUpload = function () {
page.prepareUpload = onFailure => {
// I think this fits best here because we need to check for a valid token before we can get the albums
if (page.token) {
// Display the album selection
document.querySelector('#albumDiv').classList.remove('is-hidden')
page.albumSelect = document.querySelector('#albumSelect')
page.albumSelect.addEventListener('change', function () {
page.albumSelect.addEventListener('change', () => {
page.album = parseInt(page.albumSelect.value)
// Re-generate ShareX config file
if (typeof page.prepareShareX === 'function')
page.prepareShareX()
})
page.prepareAlbums()
// Display the album selection
document.querySelector('#albumDiv').classList.remove('is-hidden')
// Fetch albums
page.fetchAlbums(onFailure)
}
// Prepare & generate config tab
page.prepareUploadConfig()
document.querySelector('#maxSize').innerHTML = `Maximum upload size per file is ${page.getPrettyBytes(page.maxSizeBytes)}`
// Update elements wherever applicable
document.querySelector('#maxSize > span').innerHTML = page.getPrettyBytes(page.maxSizeBytes)
document.querySelector('#loginToUpload').classList.add('is-hidden')
if (!page.token && page.enableUserAccounts)
document.querySelector('#loginLinkText').innerHTML = 'Create an account and keep track of your uploads'
const previewNode = document.querySelector('#tpl')
page.previewTemplate = previewNode.innerHTML
previewNode.parentNode.removeChild(previewNode)
// Prepare & generate files upload tab
page.prepareDropzone()
// Generate ShareX config file
if (typeof page.prepareShareX === 'function')
page.prepareShareX()
// Prepare urls upload tab
const urlMaxSize = document.querySelector('#urlMaxSize')
if (urlMaxSize) {
page.urlMaxSize = parseInt(urlMaxSize.innerHTML)
page.urlMaxSizeBytes = page.urlMaxSize * 1e6
urlMaxSize.innerHTML = page.getPrettyBytes(page.urlMaxSizeBytes)
document.querySelector('#uploadUrls').addEventListener('click', function () {
page.uploadUrls(this)
document.querySelector('#uploadUrls').addEventListener('click', event => {
page.uploadUrls(event.currentTarget)
})
}
const tabs = document.querySelector('#tabs')
page.tabs = tabs.querySelectorAll('li')
for (let i = 0; i < page.tabs.length; i++)
page.tabs[i].addEventListener('click', function () {
page.setActiveTab(this.dataset.id)
// Get all tabs
const tabsContainer = document.querySelector('#tabs')
const tabs = tabsContainer.querySelectorAll('li')
for (let i = 0; i < tabs.length; i++) {
const id = tabs[i].dataset.id
const tabContent = document.querySelector(`#${id}`)
if (!tabContent) continue
tabs[i].addEventListener('click', () => {
page.setActiveTab(i)
})
page.setActiveTab('tab-files')
tabs.classList.remove('is-hidden')
page.tabs.push({ tab: tabs[i], content: tabContent })
}
// Set first valid tab as the default active tab
if (page.tabs.length) {
page.setActiveTab(0)
tabsContainer.classList.remove('is-hidden')
}
}
page.prepareAlbums = function () {
const option = document.createElement('option')
option.value = ''
option.innerHTML = 'Upload to album'
option.selected = true
page.albumSelect.appendChild(option)
axios.get('api/albums', {
headers: {
token: page.token
page.setActiveTab = index => {
for (let i = 0; i < page.tabs.length; i++)
if (i === index) {
page.tabs[i].tab.classList.add('is-active')
page.tabs[i].content.classList.remove('is-hidden')
page.activeTab = index
} else {
page.tabs[i].tab.classList.remove('is-active')
page.tabs[i].content.classList.add('is-hidden')
}
}).then(function (response) {
}
page.fetchAlbums = onFailure => {
return axios.get('api/albums', { headers: { token: page.token } }).then(response => {
if (response.data.success === false)
return swal('An error occurred!', response.data.description, 'error')
// If the user doesn't have any albums we don't really need to display
// an album selection
if (!response.data.albums.length) return
// Loop through the albums and create an option for each album
for (let i = 0; i < response.data.albums.length; i++) {
const album = response.data.albums[i]
const option = document.createElement('option')
option.value = album.id
option.innerHTML = album.name
page.albumSelect.appendChild(option)
}
}).catch(function (error) {
console.error(error)
const description = error.response.data && error.response.data.description
? error.response.data.description
: 'There was an error with the request, please check the console for more information.'
return swal(`${error.response.status} ${error.response.statusText}`, description, 'error')
})
// Create an option for each album
if (Array.isArray(response.data.albums) && response.data.albums.length)
for (let i = 0; i < response.data.albums.length; i++) {
const album = response.data.albums[i]
const option = document.createElement('option')
option.value = album.id
option.innerHTML = album.name
page.albumSelect.appendChild(option)
}
}).catch(onFailure)
}
page.setActiveTab = function (tabId) {
if (tabId === page.activeTab) return
for (let i = 0; i < page.tabs.length; i++) {
const id = page.tabs[i].dataset.id
if (id === tabId) {
page.tabs[i].classList.add('is-active')
document.querySelector(`#${id}`).classList.remove('is-hidden')
} else {
page.tabs[i].classList.remove('is-active')
document.querySelector(`#${id}`).classList.add('is-hidden')
}
}
page.activeTab = tabId
}
page.prepareDropzone = () => {
// Parse template element
const previewNode = document.querySelector('#tpl')
page.previewTemplate = previewNode.innerHTML
previewNode.parentNode.removeChild(previewNode)
page.prepareDropzone = function () {
// Generate files upload tab
const tabDiv = document.querySelector('#tab-files')
const div = document.createElement('div')
div.className = 'control is-expanded'
@ -258,17 +241,15 @@ page.prepareDropzone = function () {
filelength: page.fileLength,
age: page.uploadAge
}]
}, {
headers: { token: page.token }
}).catch(function (error) {
if (error.response.data) return error.response
return {
}, { headers: { token: page.token } }).catch(error => {
// Format error for display purpose
return error.response.data ? error.response : {
data: {
success: false,
description: error.toString()
}
}
}).then(function (response) {
}).then(response => {
file.previewElement.querySelector('.progress').classList.add('is-hidden')
if (response.data.success === false)
@ -282,15 +263,16 @@ page.prepareDropzone = function () {
}
})
page.dropzone.on('addedfile', function (file) {
// Set active tab to file uploads
page.setActiveTab('tab-files')
page.dropzone.on('addedfile', file => {
// Set active tab to file uploads, if necessary
if (page.activeTab !== 0)
page.setActiveTab(0)
// Add file entry
tabDiv.querySelector('.uploads').classList.remove('is-hidden')
file.previewElement.querySelector('.name').innerHTML = file.name
})
page.dropzone.on('sending', function (file, xhr) {
page.dropzone.on('sending', (file, xhr) => {
if (file.upload.chunked) return
// Add headers if not uploading chunks
if (page.album !== null) xhr.setRequestHeader('albumid', page.album)
@ -299,7 +281,7 @@ page.prepareDropzone = function () {
})
// Update the total progress bar
page.dropzone.on('uploadprogress', function (file, progress) {
page.dropzone.on('uploadprogress', (file, progress) => {
// For some reason, chunked uploads fire 100% progress event
// for each chunk's successful uploads
if (file.upload.chunked && progress === 100) return
@ -307,7 +289,7 @@ page.prepareDropzone = function () {
file.previewElement.querySelector('.progress').innerHTML = `${progress}%`
})
page.dropzone.on('success', function (file, response) {
page.dropzone.on('success', (file, response) => {
if (!response) return
file.previewElement.querySelector('.progress').classList.add('is-hidden')
@ -318,7 +300,7 @@ page.prepareDropzone = function () {
page.updateTemplate(file, response.files[0])
})
page.dropzone.on('error', function (file, error) {
page.dropzone.on('error', (file, error) => {
// Clean up file size errors
if ((typeof error === 'string' && /^File is too big/.test(error)) ||
(typeof error === 'object' && /File too large/.test(error.description)))
@ -331,11 +313,11 @@ page.prepareDropzone = function () {
})
}
page.uploadUrls = function (button) {
page.uploadUrls = button => {
const tabDiv = document.querySelector('#tab-urls')
if (!tabDiv) return
if (!tabDiv || button.classList.contains('is-loading'))
return
if (button.classList.contains('is-loading')) return
button.classList.add('is-loading')
function done (error) {
@ -354,17 +336,16 @@ page.uploadUrls = function (button) {
const previewsContainer = tabDiv.querySelector('.uploads')
const urls = document.querySelector('#urls').value
.split(/\r?\n/)
.filter(function (url) {
.filter(url => {
return url.trim().length
})
document.querySelector('#urls').value = urls.join('\n')
if (!urls.length)
// eslint-disable-next-line prefer-promise-reject-errors
return done('You have not entered any URLs.')
tabDiv.querySelector('.uploads').classList.remove('is-hidden')
const files = urls.map(function (url) {
const files = urls.map(url => {
const previewTemplate = document.createElement('template')
previewTemplate.innerHTML = page.previewTemplate.trim()
const previewElement = previewTemplate.content.firstChild
@ -391,9 +372,9 @@ page.uploadUrls = function (button) {
// Animate progress bar
files[i].previewElement.querySelector('.progress').removeAttribute('value')
axios.post('api/upload', { urls: [files[i].url] }, { headers }).then(function (response) {
return axios.post('api/upload', { urls: [files[i].url] }, { headers }).then(response => {
return posted(response.data)
}).catch(function (error) {
}).catch(error => {
return posted({
success: false,
description: error.response ? error.response.data.description : error.toString()
@ -405,14 +386,14 @@ page.uploadUrls = function (button) {
return run()
}
page.updateTemplateIcon = function (templateElement, iconClass) {
page.updateTemplateIcon = (templateElement, iconClass) => {
const iconElement = templateElement.querySelector('.icon')
if (!iconElement) return
iconElement.classList.add(iconClass)
iconElement.classList.remove('is-hidden')
}
page.updateTemplate = function (file, response) {
page.updateTemplate = (file, response) => {
if (!response.url) return
const a = file.previewElement.querySelector('.link > a')
@ -426,11 +407,11 @@ page.updateTemplate = function (file, response) {
img.setAttribute('alt', response.name || '')
img.dataset.src = response.url
img.classList.remove('is-hidden')
img.onerror = function () {
img.onerror = event => {
// Hide image elements that fail to load
// Consequently include WEBP in browsers that do not have WEBP support (Firefox/IE)
this.classList.add('is-hidden')
file.previewElement.querySelector('.icon').classList.remove('is-hidden')
// Consequently include WEBP in browsers that do not have WEBP support (e.i. IE)
event.currentTarget.classList.add('is-hidden')
page.updateTemplateIcon(file.previewElement, 'icon-picture')
}
page.lazyLoad.update(file.previewElement.querySelectorAll('img'))
} else {
@ -444,7 +425,7 @@ page.updateTemplate = function (file, response) {
}
}
page.createAlbum = function () {
page.createAlbum = () => {
const div = document.createElement('div')
div.innerHTML = `
<div class="field">
@ -485,7 +466,7 @@ page.createAlbum = function () {
closeModal: false
}
}
}).then(function (value) {
}).then(value => {
if (!value) return
const name = document.querySelector('#swalName').value.trim()
@ -498,7 +479,7 @@ page.createAlbum = function () {
headers: {
token: page.token
}
}).then(function (response) {
}).then(response => {
if (response.data.success === false)
return swal('An error occurred!', response.data.description, 'error')
@ -509,14 +490,14 @@ page.createAlbum = function () {
option.selected = true
swal('Woohoo!', 'Album was created successfully.', 'success')
}).catch(function (error) {
}).catch(error => {
console.error(error)
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
})
})
}
page.prepareUploadConfig = function () {
page.prepareUploadConfig = () => {
const fallback = {
chunkSize: page.chunkSize,
parallelUploads: 2
@ -529,13 +510,13 @@ page.prepareUploadConfig = function () {
const numConfig = {
chunkSize: { min: 1, max: 95 },
parallelUploads: { min: 1, max: Number.MAX_SAFE_INTEGER }
parallelUploads: { min: 1, max: 8 }
}
document.querySelector('#chunkSizeDiv .help').innerHTML =
`Default is ${fallback.chunkSize} MB. Max is ${numConfig.chunkSize.max}.`
`Default is ${fallback.chunkSize} MB. Max is ${numConfig.chunkSize.max} MB.`
document.querySelector('#parallelUploadsDiv .help').innerHTML =
`Default is ${fallback.parallelUploads}.`
`Default is ${fallback.parallelUploads}. Max is ${numConfig.parallelUploads.max}.`
const fileLengthDiv = document.querySelector('#fileLengthDiv')
if (page.fileIdentifierLength && fileLengthDiv) {
@ -577,7 +558,7 @@ page.prepareUploadConfig = function () {
fileLengthDiv.querySelector('.help').innerHTML = helpText
}
Object.keys(numConfig).forEach(function (key) {
Object.keys(numConfig).forEach(key => {
document.querySelector(`#${key}`).setAttribute('min', numConfig[key].min)
document.querySelector(`#${key}`).setAttribute('max', numConfig[key].max)
})
@ -603,14 +584,14 @@ page.prepareUploadConfig = function () {
const tabContent = document.querySelector('#tab-config')
const form = tabContent.querySelector('form')
form.addEventListener('submit', function (event) {
form.addEventListener('submit', event => {
event.preventDefault()
})
const siBytes = localStorage[lsKeys.siBytes] !== '0'
if (!siBytes) document.querySelector('#siBytes').value = '0'
document.querySelector('#saveConfig').addEventListener('click', function () {
document.querySelector('#saveConfig').addEventListener('click', () => {
if (!form.checkValidity())
return
@ -637,13 +618,13 @@ page.prepareUploadConfig = function () {
title: 'Woohoo!',
text: 'Configuration saved into this browser.',
icon: 'success'
}).then(function () {
}).then(() => {
location.reload()
})
})
}
page.getPrettyUploadAge = function (hours) {
page.getPrettyUploadAge = hours => {
if (hours === 0) {
return 'Permanent'
} else if (hours < 1) {
@ -658,7 +639,7 @@ page.getPrettyUploadAge = function (hours) {
}
// Handle image paste event
window.addEventListener('paste', function (event) {
window.addEventListener('paste', event => {
const items = (event.clipboardData || event.originalEvent.clipboardData).items
const index = Object.keys(items)
for (let i = 0; i < index.length; i++) {
@ -673,25 +654,75 @@ window.addEventListener('paste', function (event) {
}
})
window.onload = function () {
page.checkIfPublic()
window.onload = () => {
// Global error callback
function onFailure (error) {
if (error === undefined) return
console.error(error)
// Hide these elements
document.querySelector('#albumDiv').classList.add('is-hidden')
document.querySelector('#tabs').classList.add('is-hidden')
document.querySelectorAll('.tab-content').forEach(element => {
return element.classList.add('is-hidden')
})
// Update upload button
const uploadButton = document.querySelector('#loginToUpload')
uploadButton.innerText = 'An error occurred. Try to reload?'
uploadButton.classList.remove('is-loading')
uploadButton.classList.remove('is-hidden')
uploadButton.addEventListener('click', () => {
location.reload()
})
// Show alert modal
if (error.response) {
console.error(error.response)
// Better error messages for Cloudflare errors
const cloudflareErrors = {
520: 'Unknown Error',
521: 'Web Server Is Down',
522: 'Connection Timed Out',
523: 'Origin Is Unreachable',
524: 'A Timeout Occurred',
525: 'SSL Handshake Failed',
526: 'Invalid SSL Certificate',
527: 'Railgun Error',
530: 'Origin DNS Error'
}
const statusText = cloudflareErrors[error.response.status] || error.response.statusText
const description = error.response.data && error.response.data.description
? error.response.data.description
: 'Please check the console for more information.'
return swal(`${error.response.status} ${statusText}`, description, 'error')
} else {
const content = document.createElement('div')
content.innerHTML = `<code>${error.toString()}</code>`
return swal({
title: 'An error occurred!',
icon: 'error',
content
})
}
}
page.checkIfPublic(onFailure)
page.clipboardJS = new ClipboardJS('.clipboard-js')
page.clipboardJS.on('success', function () {
page.clipboardJS.on('success', () => {
return swal('Copied!', 'The link has been copied to clipboard.', 'success')
})
page.clipboardJS.on('error', function (event) {
console.error(event)
return swal('An error occurred!', 'There was an error when trying to copy the link to clipboard, please check the console for more information.', 'error')
})
page.clipboardJS.on('error', onFailure)
page.lazyLoad = new LazyLoad({
elements_selector: '.field.uploads img'
})
document.querySelector('#createAlbum').addEventListener('click', function () {
document.querySelector('#createAlbum').addEventListener('click', () => {
page.createAlbum()
})
}

View File

@ -63,7 +63,7 @@ for (let i = 1; i <= 50; i++)
page.config = null
page.render = null
page.doRenderSwal = function () {
page.doRenderSwal = () => {
const div = document.createElement('div')
div.innerHTML = `
<div class="field">
@ -82,7 +82,7 @@ page.doRenderSwal = function () {
buttons: {
confirm: true
}
}).then(function (value) {
}).then(value => {
if (!value) return
const newValue = div.querySelector('#swalRender').checked ? undefined : '0'
if (newValue !== localStorage[lsKeys.render]) {
@ -98,23 +98,23 @@ page.doRenderSwal = function () {
})
}
page.getRenderVersion = function () {
page.getRenderVersion = () => {
const renderScript = document.querySelector('#renderScript')
if (renderScript && renderScript.dataset.version)
return `?v=${renderScript.dataset.version}`
return ''
}
page.doRender = function () {
page.doRender = () => {
page.config = page.renderConfig[page.renderType]
if (!page.config || !page.config.array.length) return
let element
if (localStorage[lsKeys.render] === '0') {
element = document.createElement('a')
element.className = 'button is-breeze is-hidden-mobile'
element.className = 'button is-info is-hidden-mobile'
element.title = page.config.name
element.innerHTML = '<i class="icon-picture-1"></i>'
element.innerHTML = '<i class="icon-picture"></i>'
} else {
// Let us just allow people to get new render when toggling the option
page.render = page.config.array[Math.floor(Math.random() * page.config.array.length)]

View File

@ -3,7 +3,7 @@
// keys for localStorage
lsKeys.siBytes = 'siBytes'
page.prepareShareX = function () {
page.prepareShareX = () => {
const values = page.token ? {
token: page.token || '',
albumid: page.album || ''
@ -40,7 +40,7 @@ ${headers.join(',\n')}
sharexElement.setAttribute('download', `${originClean}.sxcu`)
}
page.getPrettyDate = function (date) {
page.getPrettyDate = date => {
return date.getFullYear() + '-' +
(date.getMonth() < 9 ? '0' : '') + // month's index starts from zero
(date.getMonth() + 1) + '-' +
@ -54,10 +54,10 @@ page.getPrettyDate = function (date) {
date.getSeconds()
}
page.getPrettyBytes = function (num) {
page.getPrettyBytes = num => {
// MIT License
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
if (!Number.isFinite(num)) return num
if (typeof num !== 'number' && !isFinite(num)) return num
const si = localStorage[lsKeys.siBytes] !== '0'
const neg = num < 0 ? '-' : ''
@ -65,7 +65,7 @@ page.getPrettyBytes = function (num) {
if (neg) num = -num
if (num < scale) return `${neg}${num} B`
const exponent = Math.min(Math.floor(Math.log10(num) / 3), 8) // 8 is count of KMGTPEZY
const exponent = Math.min(Math.floor((Math.log(num) * Math.LOG10E) / 3), 8) // 8 is count of KMGTPEZY
const numStr = Number((num / Math.pow(scale, exponent)).toPrecision(3))
const pre = (si ? 'kMGTPEZY' : 'KMGTPEZY').charAt(exponent - 1) + (si ? '' : 'i')
return `${neg}${numStr} ${pre}B`

View File

@ -7,12 +7,13 @@ Normal priority:
* [ ] Use incremental version numbering instead of randomized strings.
* [ ] Use versioning in APIs, somehow.
* [ ] Better `df` handling (system disk stats).
* [ ] Use loading spinners on dashboard's sidebar menus.
* [ ] Disable all other sidebar menus when a menu is still loading.
* [*] Use loading spinners on dashboard's sidebar menus.
* [*] Disable all other sidebar menus when a menu is still loading.
* [ ] Collapsible dashboard's sidebar albums menus.
* [ ] Change `title` attribute of disabled control buttons in uploads & users lists.
* [ ] Use Gatsby logo for link to [blog.fiery.me](https://blog.fiery.me/) on the homepage.
* [*] Change `title` attribute of disabled control buttons in uploads & users lists.
* [*] Use Gatsby logo for link to [blog.fiery.me](https://blog.fiery.me/) on the homepage.
* [ ] Auto-detect missing columns in `database/db.js`.
* [*] Better error message when server is down.
Low priority:

View File

@ -16,9 +16,9 @@
v3: CSS and JS files (libs such as bulma, lazyload, etc).
v4: Renders in /public/render/* directories (to be used by render.js).
#}
{% set v1 = "gI6ZM0Tg0t" %}
{% set v1 = "fFS2CGH95j" %}
{% set v2 = "hiboQUzAzp" %}
{% set v3 = "tWLiAlAX5i" %}
{% set v3 = "fFS2CGH95j" %}
{% set v4 = "S3TAWpPeFS" %}
{#
@ -38,14 +38,14 @@
},
{
attrs: {
title: 'Blog',
title: 'Blog (Gatsby)',
href: 'https://blog.fiery.me'
},
icon: 'icon-archive icon-2x'
icon: 'icon-gatsby icon-2x'
},
{
attrs: {
title: 'PrivateBin',
title: 'Paste (PrivateBin)',
href: 'https://paste.fiery.me'
},
icon: 'icon-privatebin icon-2x'
@ -53,7 +53,7 @@
{
attrs: {
id: 'ShareX',
title: 'ShareX',
title: 'ShareX user profile',
href: 'https://safe.fiery.me/safe.fiery.me.sxcu?v=' + v2
},
icon: 'icon-sharex icon-2x'

View File

@ -13,7 +13,7 @@
<!-- Scripts -->
<script src="../libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
<script src="../js/album.js?v={{ globals.v1 }}"></script>
<script src="../js/s/utils.js?v={{ globals.v1 }}"></script>
<script src="../js/misc/utils.js?v={{ globals.v1 }}"></script>
{% endif %}
{% endblock %}
@ -83,7 +83,7 @@
{% if files.length -%}
<div id="table" class="columns is-multiline is-mobile is-centered has-text-centered">
{% for file in files %}
<div class="image-container column is-narrow">
<div class="image-container column is-narrow is-relative">
<a class="image" href="{{ file.file }}" target="_blank" rel="noopener">
{% if file.thumb -%}
{% if nojs -%}

View File

@ -4,7 +4,6 @@
{{ super() }}
<link rel="stylesheet" href="libs/fontello/fontello.css?v={{ globals.v3 }}">
<link rel="stylesheet" href="css/sweetalert.css?v={{ globals.v1 }}">
<link rel="stylesheet" href="css/auth.css?v={{ globals.v1 }}">
{% endblock %}
{% block scripts %}
@ -53,7 +52,7 @@
</button>
</div>
<div class="control">
<button id="loginBtn" type="submit" class="button">
<button id="loginBtn" type="submit" class="button is-info">
<span class="icon">
<i class="icon-login"></i>
</span>

View File

@ -15,7 +15,7 @@
<script src="libs/clipboard.js/clipboard.min.js?v={{ globals.v3 }}"></script>
<script src="libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
<script src="js/dashboard.js?v={{ globals.v1 }}"></script>
<script src="js/s/utils.js?v={{ globals.v1 }}"></script>
<script src="js/misc/utils.js?v={{ globals.v1 }}"></script>
{% endblock %}
{% block content %}
@ -34,51 +34,51 @@
<div class="column is-one-quarter">
<aside id="menu" class="menu">
<p class="menu-label">General</p>
<ul class="menu-list">
<ul class="menu-list is-unselectable">
<li>
<a href=".">Frontpage</a>
<a href="." class="is-relative">Frontpage</a>
</li>
<li>
<a id="itemUploads">Uploads</a>
<a id="itemUploads" class="is-relative">Uploads</a>
</li>
<li>
<a id="itemDeleteUploadsByNames">Delete uploads by names</a>
<a id="itemDeleteUploadsByNames" class="is-relative">Delete uploads by names</a>
</li>
</ul>
<p class="menu-label">Albums</p>
<ul class="menu-list">
<ul class="menu-list is-unselectable">
<li>
<a id="itemManageAlbums">Manage your albums</a>
<a id="itemManageAlbums" class="is-relative">Manage your albums</a>
</li>
<li>
<ul id="albumsContainer"></ul>
</li>
</ul>
<p id="itemLabelAdmin" class="menu-label is-hidden">Administration</p>
<ul id="itemListAdmin" class="menu-list is-hidden">
<ul id="itemListAdmin" class="menu-list is-unselectable is-hidden">
<li>
<a id="itemStatistics" class="is-hidden">Statistics</a>
<a id="itemStatistics" class="is-relative is-hidden">Statistics</a>
</li>
<li>
<a id="itemManageUploads" class="is-hidden">Manage uploads</a>
<a id="itemManageUploads" class="is-relative is-hidden">Manage uploads</a>
</li>
<li>
<a id="itemManageUsers" class="is-hidden">Manage users</a>
<a id="itemManageUsers" class="is-relative is-hidden">Manage users</a>
</li>
</ul>
<p class="menu-label">Configuration</p>
<ul class="menu-list">
<ul class="menu-list is-unselectable">
<li>
<a id="ShareX">ShareX user profile</a>
<a id="ShareX" class="is-relative">ShareX user profile</a>
</li>
<li>
<a id="itemManageToken">Manage your token</a>
<a id="itemManageToken" class="is-relative">Manage your token</a>
</li>
<li>
<a id="itemChangePassword">Change your password</a>
<a id="itemChangePassword" class="is-relative">Change your password</a>
</li>
<li>
<a id="itemLogout">Logout</a>
<a id="itemLogout" class="is-relative">Logout</a>
</li>
</ul>
</aside>

View File

@ -22,9 +22,9 @@
<script src="libs/clipboard.js/clipboard.min.js?v={{ globals.v3 }}"></script>
<script src="libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
<script src="js/home.js?v={{ globals.v1 }}"></script>
<script src="js/s/utils.js?v={{ globals.v1 }}"></script>
<script src="js/misc/utils.js?v={{ globals.v1 }}"></script>
{# We assign an ID for this so that the script can find out version string for render images #}
<script id="renderScript" data-version="{{ globals.v4 }}" src="js/s/render.js?v={{ globals.v1 }}"></script>
<script id="renderScript" data-version="{{ globals.v4 }}" src="js/misc/render.js?v={{ globals.v1 }}"></script>
{% endblock %}
{% block content %}
@ -32,13 +32,15 @@
<section id="home" class="hero is-fullheight">
<div class="hero-body">
<div class="container has-text-centered">
<p id="b">
<p id="b" class="is-relative">
<img class="logo" alt="logo" src="images/logo_smol.png?v={{ globals.v2 }}">
</p>
<h1 class="title">{{ globals.name }}</h1>
<h2 class="subtitle">{{ globals.home_subtitle | safe }}</h2>
<h3 id="maxSize" class="subtitle"></h3>
<h3 id="maxSize" class="subtitle">
Maximum upload size per file is <span>{{ maxSize }} MB</span>
</h3>
<div class="columns is-gapless">
<div class="column is-hidden-mobile"></div>
@ -47,11 +49,13 @@
<div id="albumDiv" class="field has-addons is-hidden">
<div class="control is-expanded">
<div class="select is-fullwidth">
<select id="albumSelect"></select>
<select id="albumSelect">
<option value="" selected>Upload to album</option>
</select>
</div>
</div>
<div class="control">
<a id="createAlbum" class="button is-breeze" title="Create new album">
<a id="createAlbum" class="button is-info" title="Create new album">
<i class="icon-plus"></i>
</a>
</div>
@ -92,7 +96,7 @@
</div>
<p class="help">
{% if urlMaxSize !== maxSize -%}
Maximum file size per URL is <span id="urlMaxSize">{{ urlMaxSize }}</span>.
Maximum file size per URL is <span id="urlMaxSize">{{ urlMaxSize }} MB</span>.
{%- endif %}
{% if urlExtensionsFilter.length and (urlExtensionsFilterMode === 'blacklist') -%}
@ -197,9 +201,9 @@
</p>
<p class="help expiry-date is-hidden"></p>
<p class="clipboard-mobile is-hidden">
<a class="button is-small is-info is-outlined clipboard-js" style="display: flex">
<a class="button is-small is-info is-outlined is-flex clipboard-js">
<span class="icon">
<i class="icon-clipboard-1"></i>
<i class="icon-clipboard"></i>
</span>
<span>Copy link to clipboard</span>
</a>

View File

@ -23,18 +23,24 @@
<div class="columns is-gapless">
<div class="column is-hidden-mobile"></div>
<div class="column">
<p class="subtitle" style="font-size: 1rem">
Files uploaded through this No-JS uploader will not be associated to your account, if you have any.
</p>
{% if renderOptions.uploadDisabled -%}
<a class="button is-danger" style="display: flex" href="auth">{{ renderOptions.uploadDisabled }}</a>
<a class="button is-danger is-flex" href="auth">
{{ renderOptions.uploadDisabled }}
</a>
{%- else -%}
<form id="form" class="field" action="" method="post" enctype="multipart/form-data">
<form id="form" class="field" action="?no-cache" method="post" enctype="multipart/form-data">
<div class="field">
<input type="file" name="files[]" multiple="multiple" style="width: 100%">
<p class="control is-expanded">
<input type="file" name="files[]" multiple="multiple">
</p>
</div>
<div class="field">
<input type="submit" class="button is-danger" value="Upload" style="width: 100%">
<p class="control is-expanded">
<input type="submit" class="button is-danger is-fullwidth" value="Upload">
</p>
<p class="help">
Files uploaded through this form will not be associated with your account, if you have any.
</p>
</div>
</form>
{%- endif %}

2820
yarn.lock

File diff suppressed because it is too large Load Diff