Initialized project
This is bad
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
/db
|
0
README.md
Normal file
23
package.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "sanifae",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^1.0.0",
|
||||
"@sveltejs/kit": "^1.0.0",
|
||||
"svelte": "^3.54.0",
|
||||
"vite": "^4.0.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@sveltejs/adapter-node": "^1.1.4",
|
||||
"bcrypt": "^5.1.0",
|
||||
"sqlite": "^4.1.2",
|
||||
"sqlite3": "^5.1.4"
|
||||
}
|
||||
}
|
15
src/app.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/icon_sanifae_black.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap" rel="stylesheet">
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover" style="margin: 0; padding: 0; overflow: hidden;">
|
||||
<div>%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
71
src/lib/components/Area.svelte
Normal file
|
@ -0,0 +1,71 @@
|
|||
<style>
|
||||
#content {
|
||||
background: var(--light-1);
|
||||
box-shadow: 0px 3px 5px 3px var(--dark-2);
|
||||
|
||||
width: min(700px, 90vw);
|
||||
padding-top: 8px;
|
||||
margin: 25px;
|
||||
|
||||
border-radius: 25px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#content > div {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
#header {
|
||||
font-weight: bold;
|
||||
|
||||
font-size: 2rem;
|
||||
|
||||
width: 100%;
|
||||
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#header {
|
||||
border-bottom: var(--dark-2) solid 2px;
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
#main {
|
||||
min-height: 250px;
|
||||
max-height: 500px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#main.tiny {
|
||||
min-height: initial;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
export let tiny = false;
|
||||
|
||||
let form;
|
||||
</script>
|
||||
|
||||
<div id='content'>
|
||||
<div id='header'>
|
||||
<slot name="header">
|
||||
Header
|
||||
</slot>
|
||||
</div>
|
||||
<div id='main' class='{tiny ? "tiny" : ""}'>
|
||||
<slot name="main">
|
||||
<p>Content</p>
|
||||
</slot>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
<slot name="footer">
|
||||
<p>Footer</p>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
28
src/lib/components/Button.svelte
Normal file
|
@ -0,0 +1,28 @@
|
|||
<style>
|
||||
.button {
|
||||
padding: 0.5rem;
|
||||
background-color: var(--dark-3);
|
||||
border: none;
|
||||
|
||||
font-family: 'Open Sans';
|
||||
|
||||
border-radius: 2rem;
|
||||
|
||||
margin: 0.2rem;
|
||||
}
|
||||
|
||||
.button a {
|
||||
color: var(--light-1);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export let clickFunc = () => {};
|
||||
export let button = '';
|
||||
</script>
|
||||
|
||||
<button on:click={clickFunc} class='button'>
|
||||
<a href='#'><slot/></a>
|
||||
</button>
|
80
src/lib/components/FileUpload.svelte
Normal file
|
@ -0,0 +1,80 @@
|
|||
<script>
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
|
||||
export let form;
|
||||
|
||||
let fileInput;
|
||||
let files;
|
||||
let preview;
|
||||
|
||||
let progress = 0;
|
||||
|
||||
function getBase64(image) {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(image);
|
||||
reader.onload = e => {
|
||||
preview = e.target.result;
|
||||
uploadFunction(e.target.result);
|
||||
};
|
||||
};
|
||||
async function uploadFunction(imageD) {
|
||||
const imgData = imageD.split(',').pop();
|
||||
|
||||
var images = [];
|
||||
|
||||
var fSize = 1024 * 256;
|
||||
|
||||
for (var i = 0; i * fSize < imgData.length + 1; i++) {
|
||||
images.push(imgData.substring(i * fSize, i * fSize + fSize));
|
||||
}
|
||||
|
||||
var rId = (Math.random() + 1).toString(36).substring(7);;
|
||||
var extension = fileInput.value.split('.').pop();
|
||||
|
||||
for (var i = 0; i < images.length; i++) {
|
||||
var fData = (new FormData());
|
||||
|
||||
var image = images[i];
|
||||
|
||||
fData.append('img',image);
|
||||
fData.append('extension',extension);
|
||||
fData.append('last',i == (images.length - 1));
|
||||
fData.append('id',rId);
|
||||
|
||||
form = await fetch(`/api/fileCreate`, {
|
||||
method: 'POST',
|
||||
body: fData,
|
||||
}).then(x => x.json());
|
||||
|
||||
progress = (i+1) / (images.length);
|
||||
|
||||
await setTimeout(() => new Promise.resolve(),100);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 250px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<form action='#' method='GET' >
|
||||
{#if preview}
|
||||
<img src={preview} alt="Image preview"/>
|
||||
{:else}
|
||||
<img src='/YourOC.svg' alt="Image preview"/>
|
||||
{/if}
|
||||
<input class="hidden" id="file-to-upload" type="file" bind:files bind:this={fileInput} on:change={() => getBase64(files[0])}/>
|
||||
<p>
|
||||
Progress: {progress * 100}%
|
||||
</p>
|
||||
<p>
|
||||
<Button class="upload-btn" clickFunc={ () => fileInput.click() }>Upload</Button>
|
||||
</p>
|
||||
</form>
|
58
src/lib/components/Header.svelte
Normal file
|
@ -0,0 +1,58 @@
|
|||
<script>
|
||||
export let data = '';
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
#logo {
|
||||
|
||||
width: calc(100vw - 20px);
|
||||
|
||||
background: var(--dark-1);
|
||||
|
||||
padding: 5px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#logo a {
|
||||
padding: 10px;
|
||||
color: var(--light-1);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#logo img {
|
||||
height: 30px;
|
||||
width: auto;
|
||||
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id='logo'>
|
||||
<a href='/'>
|
||||
<img src='/icon_sanifae.svg' alt='Sanifae Logo'>
|
||||
</a>
|
||||
{#if data.username && data.username != 'false'}
|
||||
<a href='/user/{data.username}'>
|
||||
{data.username}
|
||||
</a>
|
||||
<a href='/logout'>
|
||||
Log out
|
||||
</a>
|
||||
<a href='/new_post'>
|
||||
Create
|
||||
</a>
|
||||
{:else}
|
||||
<a href='/account'>
|
||||
Log in / Register
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
95
src/lib/db/db.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
const FILE_SIZE_LIMIT = 1024*1024*16;
|
||||
|
||||
const VALID_EXTENSIONS = ['png','jpg','jpeg','svg'];
|
||||
|
||||
var ridArray = {};
|
||||
|
||||
import sqlite3 from 'sqlite3'
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
import { safePath, user } from '../util.js';
|
||||
import { open } from 'sqlite'
|
||||
import { createHash } from 'node:crypto';
|
||||
|
||||
var db;
|
||||
async function initDb() {
|
||||
db = await open({
|
||||
filename: `${process.cwd()}/db/main.db`,
|
||||
driver: sqlite3.Database
|
||||
});
|
||||
|
||||
await db.run('CREATE TABLE IF NOT EXISTS rating (id CHAR(256), rating INTEGER)');
|
||||
}
|
||||
|
||||
let backendProxy = async ({route, backendParams,}) => {
|
||||
if (!db) await initDb();
|
||||
|
||||
const res = await fetch(`https://sanifae.insfa.net/api/token`,{
|
||||
'method': 'GET', 'headers': {
|
||||
'cookie': backendParams.cookie
|
||||
}
|
||||
});
|
||||
|
||||
backendParams['admin'] = ((await res.json()).data == user);
|
||||
|
||||
return backend[route](backendParams);
|
||||
}
|
||||
|
||||
var backend = {};
|
||||
|
||||
|
||||
backend.rateOc = async ({admin,id,rating}) => {
|
||||
if (admin) {
|
||||
await db.run('UPDATE rating SET rating = ? WHERE id = ?', [
|
||||
rating,
|
||||
id
|
||||
])
|
||||
}
|
||||
};
|
||||
|
||||
backend.oc = async ({admin}) => {
|
||||
return await db.all('SELECT * FROM rating WHERE rating > ? ORDER BY rating DESC', [
|
||||
(admin) ? -1000 : -1
|
||||
]);
|
||||
}
|
||||
|
||||
backend.fileCreate = async({img, extension,id, last }) => {
|
||||
if (ridArray[id] !== '' && !(ridArray[id])) {
|
||||
ridArray[id] = img;
|
||||
} else {
|
||||
ridArray[id] += img;
|
||||
}
|
||||
|
||||
const imgData = ridArray[id];
|
||||
|
||||
if (last != 'true') {
|
||||
return {'success': 'Image still proccessing...'}
|
||||
} else {
|
||||
ridArray[id] = false;
|
||||
}
|
||||
|
||||
const imgHash = createHash('md5').update(imgData).digest('hex');
|
||||
|
||||
if (!imgHash)
|
||||
return {'success': 'Image not provided.'}
|
||||
|
||||
if (imgHash.length > FILE_SIZE_LIMIT)
|
||||
return {'success': 'Image too big.'}
|
||||
|
||||
const extensionSafe = safePath(extension);
|
||||
|
||||
if (VALID_EXTENSIONS.indexOf(extensionSafe) == -1)
|
||||
return { success: 'Illegal file extension. Permitted file extensions are: ' + VALID_EXTENSIONS.join(', ') };
|
||||
|
||||
writeFile(`${process.cwd()}/db/post-${imgHash}.${extensionSafe}`,imgData,{encoding: 'base64'});
|
||||
|
||||
await db.run('INSERT INTO rating (id,rating) VALUES (?,?)', [
|
||||
`${imgHash}.${extensionSafe}`,
|
||||
-1
|
||||
]);
|
||||
|
||||
return { success: 'Successfully uploaded file.', 'href': `/img/${imgHash}.${extensionSafe}`};
|
||||
}
|
||||
export {
|
||||
backendProxy,
|
||||
backend
|
||||
}
|
85
src/lib/util.js
Normal file
|
@ -0,0 +1,85 @@
|
|||
const EXTENSION_MAP = {
|
||||
'png': 'img',
|
||||
'jpg': 'img',
|
||||
'jpeg': 'img',
|
||||
'gif': 'img',
|
||||
'svg': 'img',
|
||||
'mp4': 'video'
|
||||
}
|
||||
|
||||
let checkLength = function(string, field, lowerBound, upperBound) {
|
||||
if (string.length < lowerBound) {
|
||||
if (string.length == 0) {
|
||||
return { success: `${field} cannot be blank.` }
|
||||
}
|
||||
return { success: `${field} is too short (minimum length: ${lowerBound} characters).` }
|
||||
}
|
||||
|
||||
if (string.length > upperBound) {
|
||||
return { success: `${field} is too long (maximum length: ${upperBound} characters).` }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let checkRegex = function(string, field, regex) {
|
||||
if (string.search(regex) != -1) {
|
||||
return { success: `${field} contains illegal characters.` }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
let handleSubmitGet = async e => {
|
||||
const ACTION_URL = e.target.action
|
||||
|
||||
const formData = new FormData(e.target);
|
||||
const asString = new URLSearchParams(formData).toString();
|
||||
|
||||
return await fetch(ACTION_URL + '?' + asString, {
|
||||
method: 'GET',
|
||||
}).then(x => x.text());
|
||||
}
|
||||
|
||||
let handleSubmit = async e => {
|
||||
const ACTION_URL = e.target.action
|
||||
|
||||
const formData = new FormData(e.target);
|
||||
|
||||
return await fetch(ACTION_URL, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
}).then(x => x.text());
|
||||
}
|
||||
|
||||
let safeName = function (text) {
|
||||
return text.replaceAll(/[^A-Za-z0-9\-\_]/g, '');
|
||||
}
|
||||
|
||||
let block = function(bool) {
|
||||
return (bool) ? 'block' : 'inline';
|
||||
}
|
||||
|
||||
let safePath = function(path) {
|
||||
if (path == '..' || path == '.') return '';
|
||||
return path.replace(/[\/]+/g, '')
|
||||
}
|
||||
|
||||
let setLocation = function(location, key, value) {
|
||||
var loc = new URL(location).searchParams;
|
||||
|
||||
loc.set(key,value);
|
||||
return loc.toString();
|
||||
}
|
||||
|
||||
let user = 'derv';
|
||||
|
||||
export {
|
||||
checkLength,
|
||||
checkRegex,
|
||||
handleSubmit,
|
||||
handleSubmitGet,
|
||||
block,
|
||||
safePath,
|
||||
setLocation,
|
||||
user
|
||||
};
|
8
src/routes/+layout.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
/** @type {import('./$types').PageLoad} */
|
||||
export async function load({ fetch }) {
|
||||
const res = await fetch(`/api/token`);
|
||||
|
||||
const username = await res.json();
|
||||
|
||||
return { username: username.data };
|
||||
}
|
46
src/routes/+layout.svelte
Normal file
|
@ -0,0 +1,46 @@
|
|||
<style>
|
||||
#content {
|
||||
background: var(--light-2);
|
||||
|
||||
height: 100vh;
|
||||
width: calc(100vw - 50px);
|
||||
padding: 25px;
|
||||
padding-top: 0px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
:global(:root) {
|
||||
--dark-1: #2b2f36;
|
||||
--dark-2: #d8d8d8;
|
||||
--dark-3: rgb(73, 138, 236);
|
||||
|
||||
--light-1: #ffffff;
|
||||
--light-2: #f8f8f8;
|
||||
|
||||
--hyperlink: rgb(139, 171, 219);
|
||||
|
||||
font-family: 'Open Sans';
|
||||
}
|
||||
|
||||
:global(a) {
|
||||
color: var(--hyperlink);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
:global(input, textarea) {
|
||||
border: 0;
|
||||
border-radius: 0.2rem;
|
||||
box-shadow: 0px 2px 2.5px 0px var(--dark-2);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div id='content'>
|
||||
<slot />
|
||||
</div>
|
||||
|
19
src/routes/+page.server.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { user } from '$lib/util.js';
|
||||
|
||||
/** @type {import('./$types').PageServerLoad} */
|
||||
export async function load({ fetch, params, url, cookies, request }) {
|
||||
|
||||
const res = await fetch(`https://sanifae.insfa.net/api/token`,{
|
||||
'method': 'GET', 'headers': {
|
||||
'cookie': request.headers.get('cookie')
|
||||
}
|
||||
});
|
||||
|
||||
const userJson = await res.json();
|
||||
|
||||
const oc = await fetch(`/api/oc?user=${encodeURIComponent(user)}`,{
|
||||
'method': 'GET'
|
||||
}).then(x => x.json());
|
||||
|
||||
return { data: userJson.data == user, oc, token: request.headers.get('cookie') };
|
||||
}
|
62
src/routes/+page.svelte
Normal file
|
@ -0,0 +1,62 @@
|
|||
<script>
|
||||
import Area from '$lib/components/Area.svelte';
|
||||
import FileUpload from '$lib/components/FileUpload.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
|
||||
/** @type {import('./$types').PageData} */
|
||||
export let data;
|
||||
|
||||
let editable = {};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
img {
|
||||
max-width: 200px;
|
||||
max-height: 500px;
|
||||
margin: 5px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-auto-flow: row;
|
||||
}
|
||||
</style>
|
||||
|
||||
<Area>
|
||||
<div slot='header'>
|
||||
OC Rating Stand
|
||||
</div>
|
||||
<div slot='main' >
|
||||
<p>Put your OC and wait for it to be rated! SVGs (vector), PNGs (bitmap), and other image formats can be uploaded.</p>
|
||||
<FileUpload />
|
||||
</div>
|
||||
<div slot='footer'>
|
||||
Project of <a href='https://insfa.net/'>INSFA</a>
|
||||
</div>
|
||||
</Area>
|
||||
|
||||
<Area>
|
||||
<div slot='header'>
|
||||
Rated OCs
|
||||
</div>
|
||||
<div slot='main' class='wrapper'>
|
||||
{#each data.oc as ocData}
|
||||
<div>
|
||||
<img src='/img/{ocData.id}'>
|
||||
<p>
|
||||
<span contenteditable='{data.data}' bind:this={editable[ocData.id]}>
|
||||
{ocData.rating == '-1' ? 'Unrated' : ocData.rating}
|
||||
</span> / 10
|
||||
</p>
|
||||
<Button clickFunc={async () => await fetch(`/api/rateOc?rating=${encodeURIComponent(editable[ocData.id].textContent)}&id=${encodeURIComponent(ocData.id)}`)}>
|
||||
Update
|
||||
</Button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div slot='footer'>
|
||||
|
||||
</div>
|
||||
</Area>
|
51
src/routes/api/[route]/+server.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { backend, backendProxy } from '../../../lib/db/db.js';
|
||||
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function GET({ url, cookies, params, fetch, request }) {
|
||||
var formEntries = url.searchParams;
|
||||
|
||||
formEntries = [...formEntries,['cookie',request.headers.get('cookie')]];
|
||||
|
||||
return await handleReq({
|
||||
cookies,
|
||||
params: formEntries,
|
||||
route: params.route,
|
||||
fetch
|
||||
});
|
||||
}
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function POST({ cookies, request, params, fetch }) {
|
||||
|
||||
var formEntries = (await request.formData()).entries();
|
||||
|
||||
formEntries = [...formEntries,['cookie',request.headers.get('cookie')]];
|
||||
|
||||
return await handleReq({
|
||||
cookies,
|
||||
params: formEntries,
|
||||
route: params.route,
|
||||
fetch
|
||||
});
|
||||
}
|
||||
|
||||
async function handleReq({ cookies, params, route, fetch }) {
|
||||
var backendParams = {cookies,fetch};
|
||||
|
||||
for (const [key, value] of params) {
|
||||
backendParams[key] = value + '';
|
||||
}
|
||||
|
||||
return await mainApi({backendParams, route: route});
|
||||
}
|
||||
|
||||
async function mainApi({backendParams, route, fetch}) {
|
||||
if (Object.keys(backend).indexOf(route) == -1) {
|
||||
return new Response(JSON.stringify({success: 'route doesn\'t exist'}));
|
||||
}
|
||||
|
||||
var resData = await backendProxy({ route, backendParams });
|
||||
|
||||
return new Response(JSON.stringify(resData));
|
||||
};
|
20
src/routes/img/[img]/+server.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function GET({ url, cookies, params }) {
|
||||
var imgName = params['img'];
|
||||
|
||||
imgName = imgName.replace(/(\s+)/g, '\\$1');
|
||||
|
||||
var res = await readFile(`${process.cwd()}/db/post-${imgName}`);
|
||||
|
||||
var response = new Response(res);
|
||||
var extension = imgName.split('.').pop();
|
||||
|
||||
if (extension == 'svg') {
|
||||
response = new Response(res, {'headers': {
|
||||
'Content-Type': 'image/svg+xml'
|
||||
}});
|
||||
}
|
||||
return response;
|
||||
}
|
43
src/routes/login/+page.svelte
Normal file
|
@ -0,0 +1,43 @@
|
|||
<script>
|
||||
import Area from '$lib/components/Area.svelte';
|
||||
import { handleSubmitGet } from '$lib/util.js';
|
||||
|
||||
export let form = {};
|
||||
|
||||
let submitFunc = async e => {
|
||||
var form = JSON.parse(await handleSubmitGet(e));
|
||||
document.cookie = `token=${form.data}`
|
||||
|
||||
if (form.data)
|
||||
window.location.href='/';
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<Area handleSubmit=''>
|
||||
<p slot="header">
|
||||
Log in
|
||||
</p>
|
||||
|
||||
<span slot='main'>
|
||||
<h2>Login with <a href='https://sanifae.insfa.net/'>Sanifae</a></h2>
|
||||
<form action='https://sanifae.insfa.net/api/login' on:submit|preventDefault={submitFunc} method='GET'>
|
||||
<p>
|
||||
Username: <input name='user'>
|
||||
</p>
|
||||
<p>
|
||||
Password: <input type='password' name='pass'>
|
||||
</p>
|
||||
<p>
|
||||
<input type='submit' value='Log in'>
|
||||
</p>
|
||||
</form>
|
||||
</span>
|
||||
<p slot="footer">
|
||||
{#if form?.success}
|
||||
<p>{form?.success}</p>
|
||||
{/if}
|
||||
By using the Sanifae service, you agree to the <a href='https://insfa.net/rules'>Terms of Service</a>.
|
||||
</p>
|
||||
</Area>
|
1
static/YourOC.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="137.27948" height="140.24416" viewBox="0,0,137.27948,140.24416"><defs><radialGradient cx="240" cy="180" r="68.63974" gradientUnits="userSpaceOnUse" id="color-1"><stop offset="0" stop-color="#a5ffa5"/><stop offset="1" stop-color="#a5ffa5" stop-opacity="0"/></radialGradient></defs><g transform="translate(-171.36026,-108.39558)"><g data-paper-data="{"isPaintingLayer":true}" fill-rule="nonzero" stroke="none" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" style="mix-blend-mode: normal"><path d="M171.36026,180c0,-37.90868 30.73107,-68.63974 68.63974,-68.63974c37.90868,0 68.63974,30.73107 68.63974,68.63974c0,37.90868 -30.73107,68.63974 -68.63974,68.63974c-37.90868,0 -68.63974,-30.73107 -68.63974,-68.63974z" fill="url(#color-1)" stroke-width="NaN"/><path d="M192.83702,180c0,-26.04739 21.11559,-47.16298 47.16298,-47.16298c26.04739,0 47.16298,21.11559 47.16298,47.16298c0,26.04739 -21.11559,47.16298 -47.16298,47.16298c-26.04739,0 -47.16298,-21.11559 -47.16298,-47.16298z" fill="#6bad6b" stroke-width="NaN"/><path d="M217.92371,161.18498c0,-12.1924 9.88389,-22.07628 22.07629,-22.07628c12.1924,0 22.07629,9.88388 22.07629,22.07628c0,12.1924 -9.88389,22.07629 -22.07629,22.07629c-12.1924,0 -22.07629,-9.88389 -22.07629,-22.07629z" fill="#c8fcc2" stroke-width="NaN"/><path d="M240,185.26821c26.04739,0 41.51177,20.89527 32.09919,29.51768c-8.39103,7.68661 -19.82278,12.37709 -32.09919,12.37709c-12.64275,0 -24.12363,-4.97459 -32.59202,-13.07318c-8.97873,-8.58664 6.54462,-28.82159 32.59202,-28.82159z" fill="#c8fcc2" stroke-width="NaN"/><text transform="translate(209.02688,124.93559) scale(0.38023,0.38023)" font-size="40" xml:space="preserve" fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="Sans Serif" font-weight="normal" text-anchor="start" style="mix-blend-mode: normal"><tspan x="0" dy="0">Your OC</tspan></text></g></g></svg>
|
After Width: | Height: | Size: 2.1 KiB |
50
static/delete.svg
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="39.749512mm"
|
||||
height="34.423737mm"
|
||||
viewBox="0 0 39.749511 34.423736"
|
||||
version="1.1"
|
||||
id="svg14062"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="delete.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview14064"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0560856"
|
||||
inkscape:cx="40.367969"
|
||||
inkscape:cy="68.333731"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="996"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs14059" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-48.152692,-141.96593)">
|
||||
<path
|
||||
id="path33180"
|
||||
style="fill:#aaaaaa;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.96999"
|
||||
inkscape:transform-center-y="-5.7373187"
|
||||
d="M -65.658893,-122.24195 -140.77608,7.8635183 H 9.458295 Z m -12.876954,35.990233 h 25.753907 l -3.041016,56.396485 h -19.671875 z m 12.81836,65.816407 c 3.378213,0 6.27876,0.853521 8.703125,2.5625 2.424365,1.708978 3.636719,4.669982 3.636719,8.8828125 0,4.0141122 -1.212354,6.9166124 -3.636719,8.70507821 -2.424365,1.78846589 -5.324912,2.68164069 -8.703125,2.68164069 -3.417957,0 -6.378961,-0.8931748 -8.882813,-2.68164069 -2.464108,-1.78846581 -3.697266,-4.69096601 -3.697266,-8.70507821 0,-4.2128305 1.233158,-7.1738345 3.697266,-8.8828125 2.503852,-1.708979 5.464856,-2.5625 8.882813,-2.5625 z"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,85.399696,174.30911)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
52
static/downvote.svg
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="38.195164mm"
|
||||
height="62.605831mm"
|
||||
viewBox="0 0 38.195163 62.605831"
|
||||
version="1.1"
|
||||
id="svg14062"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="downvote.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview14064"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0560856"
|
||||
inkscape:cx="0.48636107"
|
||||
inkscape:cy="32.829372"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="996"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs14059" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-48.929905,-129.52741)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#aaa;stroke-width:11.90625;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 56.684592,149.59814 10.887303,12.1325 13.600048,-26.2501"
|
||||
id="path3462" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#aaa;stroke-width:11.90625;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 79.370381,172.06252 68.483078,159.93002 54.88303,186.18012"
|
||||
id="path8000" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
BIN
static/favicon.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
61
static/icon_sanifae.svg
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="69.642113mm"
|
||||
height="77.026108mm"
|
||||
viewBox="0 0 69.642113 77.026108"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="template.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.18173401"
|
||||
inkscape:cx="2517.4155"
|
||||
inkscape:cy="1532.4595"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="996"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="true" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-41.180676,-30.027448)">
|
||||
<g
|
||||
id="g20517"
|
||||
transform="matrix(0.68756186,0,0,0.68756186,-44.467038,-7.6059692)"
|
||||
inkscape:export-filename="icon_sanifae.svg"
|
||||
inkscape:export-xdpi="1031.03"
|
||||
inkscape:export-ydpi="1031.03">
|
||||
<path
|
||||
id="path20351"
|
||||
style="opacity:1;fill:#ffffff;stroke:#e5a8ff;stroke-width:0;stroke-miterlimit:3.96999"
|
||||
d="m -179.12012,71.140402 a 38.853859,39.608299 0 0 1 38.85342,39.608018 38.853859,39.608299 0 0 1 -38.85342,39.60877 38.853859,39.608299 0 0 1 -38.85418,-39.60877 38.853859,39.608299 0 0 1 38.85418,-39.608018 z m -2.6689,2.086413 c -1.81603,0 -3.30098,1.484955 -3.30098,3.300981 0,1.816023 1.48495,3.301733 3.30098,3.301733 1.81603,0 3.30173,-1.48571 3.30173,-3.301733 0,-1.816026 -1.4857,-3.300981 -3.30173,-3.300981 z m 0,1.220581 c 1.15641,0 2.08115,0.923986 2.08115,2.0804 0,1.15641 -0.92474,2.081152 -2.08115,2.081152 -1.15641,0 -2.0804,-0.924742 -2.0804,-2.081152 0,-1.156414 0.92399,-2.0804 2.0804,-2.0804 z m 10.24266,4.441143 c -9.52749,0 -17.31963,7.79214 -17.31963,17.31963 0,9.527481 7.79214,17.319631 17.31963,17.319631 9.5275,0 17.32039,-7.79215 17.32039,-17.319631 0,-9.52749 -7.79289,-17.31963 -17.32039,-17.31963 z m 0,6.403543 c 6.06693,0 10.91684,4.849162 10.91684,10.916087 0,6.066921 -4.84991,10.916841 -10.91684,10.916841 -6.06692,0 -10.91608,-4.84992 -10.91608,-10.916841 0,-6.066925 4.84916,-10.916087 10.91608,-10.916087 z m -34.39424,8.417803 c -2.94896,0 -5.36109,2.411367 -5.36109,5.360337 0,2.948968 2.41213,5.361088 5.36109,5.361088 2.94898,0 5.36109,-2.41212 5.36109,-5.361088 0,-2.94897 -2.41211,-5.360337 -5.36109,-5.360337 z m 0,1.981942 c 1.87785,0 3.37915,1.500546 3.37915,3.378395 0,1.877858 -1.5013,3.379148 -3.37915,3.379148 -1.87785,0 -3.37914,-1.50129 -3.37914,-3.379148 0,-1.877849 1.50129,-3.378395 3.37914,-3.378395 z m 4.52081,14.621423 c -6.05882,0 -11.01454,4.95497 -11.01454,11.01379 0,6.05882 4.95572,11.01455 11.01454,11.01455 6.05883,0 11.0138,-4.95573 11.0138,-11.01455 0,-6.05882 -4.95497,-11.01379 -11.0138,-11.01379 z m 48.6271,3.30775 c -4.10155,0 -7.45577,3.35422 -7.45577,7.45576 0,4.10155 3.35422,7.45577 7.45577,7.45577 4.10153,0 7.45652,-3.35422 7.45652,-7.45577 0,-4.10154 -3.35499,-7.45576 -7.45652,-7.45576 z m -48.6271,0.76436 c 3.85814,0 6.94169,3.08354 6.94169,6.94168 0,3.85814 -3.08355,6.94244 -6.94169,6.94244 -3.85814,0 -6.94243,-3.0843 -6.94243,-6.94244 0,-3.85814 3.08429,-6.94168 6.94243,-6.94168 z m 25.33008,0.68245 c -5.772,0 -10.49295,4.72093 -10.49295,10.49294 0,5.77199 4.72095,10.49294 10.49295,10.49294 5.772,0 10.49294,-4.72095 10.49294,-10.49294 0,-5.77201 -4.72094,-10.49294 -10.49294,-10.49294 z m 23.29702,1.30927 c 2.61177,0 4.69969,2.0879 4.69969,4.69968 0,2.61179 -2.08792,4.69969 -4.69969,4.69969 -2.61179,0 -4.69969,-2.0879 -4.69969,-4.69969 0,-2.61178 2.0879,-4.69968 4.69969,-4.69968 z m -23.29702,2.57043 c 3.67549,0 6.61323,2.93773 6.61323,6.61324 0,3.67549 -2.93774,6.61323 -6.61323,6.61323 -3.6755,0 -6.61324,-2.93774 -6.61324,-6.61323 0,-3.67551 2.93774,-6.61324 6.61324,-6.61324 z m -14.74093,15.1776 c -2.09552,0 -3.80981,1.71429 -3.80981,3.80981 0,2.09552 1.71429,3.80905 3.80981,3.80905 2.09552,0 3.80906,-1.71353 3.80906,-3.80905 0,-2.09552 -1.71354,-3.80981 -3.80906,-3.80981 z m 0,1.40848 c 1.33439,0 2.40058,1.06694 2.40058,2.40133 0,1.33439 -1.06619,2.40058 -2.40058,2.40058 -1.33439,0 -2.40133,-1.06619 -2.40133,-2.40058 0,-1.33439 1.06694,-2.40133 2.40133,-2.40133 z m 20.57101,5.23708 c -1.99632,0 -3.62943,1.63235 -3.62943,3.62867 0,1.99632 1.63311,3.62943 3.62943,3.62943 1.99631,0 3.62867,-1.63311 3.62867,-3.62943 0,-1.99632 -1.63236,-3.62867 -3.62867,-3.62867 z m 0,1.34158 c 1.27121,0 2.28708,1.01587 2.28708,2.28709 0,1.27122 -1.01587,2.28784 -2.28708,2.28784 -1.27122,0 -2.28709,-1.01662 -2.28709,-2.28784 0,-1.27122 1.01587,-2.28709 2.28709,-2.28709 z"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
id="ellipse20462"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#e5a8ff;stroke-width:0;stroke-miterlimit:3.96999;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 179.51388,54.73459 a 54.946752,56.013673 0 0 0 -54.9466,56.01424 54.946752,56.013673 0 0 0 54.9466,56.01365 54.946752,56.013673 0 0 0 46.32654,-25.93699 l -8.72245,-5.66291 a 44.605491,45.471613 0 0 1 -37.60409,21.05732 44.605491,45.471613 0 0 1 -44.60536,-45.47107 44.605491,45.471613 0 0 1 44.60536,-45.471649 44.605491,45.471613 0 0 1 37.61888,21.048209 l 8.72302,-5.662909 A 54.946752,56.013673 0 0 0 179.51388,54.73459 Z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.7 KiB |
61
static/icon_sanifae_black.svg
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="69.642113mm"
|
||||
height="77.026108mm"
|
||||
viewBox="0 0 69.642113 77.026108"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="template.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.18173401"
|
||||
inkscape:cx="2517.4155"
|
||||
inkscape:cy="1532.4595"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="996"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="true" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-41.180676,-30.027448)">
|
||||
<g
|
||||
id="g20517"
|
||||
transform="matrix(0.68756186,0,0,0.68756186,-44.467038,-7.6059692)"
|
||||
inkscape:export-filename="icon_sanifae.svg"
|
||||
inkscape:export-xdpi="1031.03"
|
||||
inkscape:export-ydpi="1031.03">
|
||||
<path
|
||||
id="path20351"
|
||||
style="opacity:1;fill:#000000;stroke:#e5a8ff;stroke-width:0;stroke-miterlimit:3.96999"
|
||||
d="m -179.12012,71.140402 a 38.853859,39.608299 0 0 1 38.85342,39.608018 38.853859,39.608299 0 0 1 -38.85342,39.60877 38.853859,39.608299 0 0 1 -38.85418,-39.60877 38.853859,39.608299 0 0 1 38.85418,-39.608018 z m -2.6689,2.086413 c -1.81603,0 -3.30098,1.484955 -3.30098,3.300981 0,1.816023 1.48495,3.301733 3.30098,3.301733 1.81603,0 3.30173,-1.48571 3.30173,-3.301733 0,-1.816026 -1.4857,-3.300981 -3.30173,-3.300981 z m 0,1.220581 c 1.15641,0 2.08115,0.923986 2.08115,2.0804 0,1.15641 -0.92474,2.081152 -2.08115,2.081152 -1.15641,0 -2.0804,-0.924742 -2.0804,-2.081152 0,-1.156414 0.92399,-2.0804 2.0804,-2.0804 z m 10.24266,4.441143 c -9.52749,0 -17.31963,7.79214 -17.31963,17.31963 0,9.527481 7.79214,17.319631 17.31963,17.319631 9.5275,0 17.32039,-7.79215 17.32039,-17.319631 0,-9.52749 -7.79289,-17.31963 -17.32039,-17.31963 z m 0,6.403543 c 6.06693,0 10.91684,4.849162 10.91684,10.916087 0,6.066921 -4.84991,10.916841 -10.91684,10.916841 -6.06692,0 -10.91608,-4.84992 -10.91608,-10.916841 0,-6.066925 4.84916,-10.916087 10.91608,-10.916087 z m -34.39424,8.417803 c -2.94896,0 -5.36109,2.411367 -5.36109,5.360337 0,2.948968 2.41213,5.361088 5.36109,5.361088 2.94898,0 5.36109,-2.41212 5.36109,-5.361088 0,-2.94897 -2.41211,-5.360337 -5.36109,-5.360337 z m 0,1.981942 c 1.87785,0 3.37915,1.500546 3.37915,3.378395 0,1.877858 -1.5013,3.379148 -3.37915,3.379148 -1.87785,0 -3.37914,-1.50129 -3.37914,-3.379148 0,-1.877849 1.50129,-3.378395 3.37914,-3.378395 z m 4.52081,14.621423 c -6.05882,0 -11.01454,4.95497 -11.01454,11.01379 0,6.05882 4.95572,11.01455 11.01454,11.01455 6.05883,0 11.0138,-4.95573 11.0138,-11.01455 0,-6.05882 -4.95497,-11.01379 -11.0138,-11.01379 z m 48.6271,3.30775 c -4.10155,0 -7.45577,3.35422 -7.45577,7.45576 0,4.10155 3.35422,7.45577 7.45577,7.45577 4.10153,0 7.45652,-3.35422 7.45652,-7.45577 0,-4.10154 -3.35499,-7.45576 -7.45652,-7.45576 z m -48.6271,0.76436 c 3.85814,0 6.94169,3.08354 6.94169,6.94168 0,3.85814 -3.08355,6.94244 -6.94169,6.94244 -3.85814,0 -6.94243,-3.0843 -6.94243,-6.94244 0,-3.85814 3.08429,-6.94168 6.94243,-6.94168 z m 25.33008,0.68245 c -5.772,0 -10.49295,4.72093 -10.49295,10.49294 0,5.77199 4.72095,10.49294 10.49295,10.49294 5.772,0 10.49294,-4.72095 10.49294,-10.49294 0,-5.77201 -4.72094,-10.49294 -10.49294,-10.49294 z m 23.29702,1.30927 c 2.61177,0 4.69969,2.0879 4.69969,4.69968 0,2.61179 -2.08792,4.69969 -4.69969,4.69969 -2.61179,0 -4.69969,-2.0879 -4.69969,-4.69969 0,-2.61178 2.0879,-4.69968 4.69969,-4.69968 z m -23.29702,2.57043 c 3.67549,0 6.61323,2.93773 6.61323,6.61324 0,3.67549 -2.93774,6.61323 -6.61323,6.61323 -3.6755,0 -6.61324,-2.93774 -6.61324,-6.61323 0,-3.67551 2.93774,-6.61324 6.61324,-6.61324 z m -14.74093,15.1776 c -2.09552,0 -3.80981,1.71429 -3.80981,3.80981 0,2.09552 1.71429,3.80905 3.80981,3.80905 2.09552,0 3.80906,-1.71353 3.80906,-3.80905 0,-2.09552 -1.71354,-3.80981 -3.80906,-3.80981 z m 0,1.40848 c 1.33439,0 2.40058,1.06694 2.40058,2.40133 0,1.33439 -1.06619,2.40058 -2.40058,2.40058 -1.33439,0 -2.40133,-1.06619 -2.40133,-2.40058 0,-1.33439 1.06694,-2.40133 2.40133,-2.40133 z m 20.57101,5.23708 c -1.99632,0 -3.62943,1.63235 -3.62943,3.62867 0,1.99632 1.63311,3.62943 3.62943,3.62943 1.99631,0 3.62867,-1.63311 3.62867,-3.62943 0,-1.99632 -1.63236,-3.62867 -3.62867,-3.62867 z m 0,1.34158 c 1.27121,0 2.28708,1.01587 2.28708,2.28709 0,1.27122 -1.01587,2.28784 -2.28708,2.28784 -1.27122,0 -2.28709,-1.01662 -2.28709,-2.28784 0,-1.27122 1.01587,-2.28709 2.28709,-2.28709 z"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
id="ellipse20462"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#e5a8ff;stroke-width:0;stroke-miterlimit:3.96999;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 179.51388,54.73459 a 54.946752,56.013673 0 0 0 -54.9466,56.01424 54.946752,56.013673 0 0 0 54.9466,56.01365 54.946752,56.013673 0 0 0 46.32654,-25.93699 l -8.72245,-5.66291 a 44.605491,45.471613 0 0 1 -37.60409,21.05732 44.605491,45.471613 0 0 1 -44.60536,-45.47107 44.605491,45.471613 0 0 1 44.60536,-45.471649 44.605491,45.471613 0 0 1 37.61888,21.048209 l 8.72302,-5.662909 A 54.946752,56.013673 0 0 0 179.51388,54.73459 Z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.7 KiB |
66
static/logo_sanifae.svg
Normal file
After Width: | Height: | Size: 14 KiB |
48
static/upvote.svg
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="32.42485mm"
|
||||
height="34.187305mm"
|
||||
viewBox="0 0 32.42485 34.187306"
|
||||
version="1.1"
|
||||
id="svg14062"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="upvote.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview14064"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0560856"
|
||||
inkscape:cx="58.84969"
|
||||
inkscape:cy="76.601869"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="996"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs14059" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-47.715969,-129.48962)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#aaa;stroke-width:7.9375;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 51.684719,147.57597 10.887303,12.1325 13.600048,-26.2501"
|
||||
id="path3462" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
54
static/view.svg
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="84.203423mm"
|
||||
height="84.203423mm"
|
||||
viewBox="0 0 84.203423 84.203423"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="view.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.72693603"
|
||||
inkscape:cx="-20.634553"
|
||||
inkscape:cy="273.06392"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="996"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-53.804537,-76.370715)">
|
||||
<path
|
||||
style="color:#000000;fill:#aaa;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.96999;-inkscape-stroke:none"
|
||||
d="m 95.90625,76.370863 c -23.173772,0 -42.101563,18.92779 -42.101563,42.101567 0,23.17377 18.927791,42.10156 42.101563,42.10156 23.17377,0 42.10156,-18.92779 42.10156,-42.10156 0,-23.173777 -18.92779,-42.101567 -42.10156,-42.101567 z m 0,13.228515 c 16.02419,0 28.87305,12.848862 28.87305,28.873052 0,16.02419 -12.84886,28.87304 -28.87305,28.87304 -16.024189,0 -28.873047,-12.84885 -28.873047,-28.87304 0,-16.02419 12.848858,-28.873052 28.873047,-28.873052 z"
|
||||
id="path234" />
|
||||
<circle
|
||||
style="fill:#aaa;fill-opacity:1;stroke:#aaa;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.96999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path3020"
|
||||
cx="95.90625"
|
||||
cy="118.47243"
|
||||
r="9.6452198" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
10
svelte.config.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import adapter from '@sveltejs/adapter-node';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
7
vite.config.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
|
||||
const config = {
|
||||
plugins: [sveltekit()]
|
||||
};
|
||||
|
||||
export default config;
|