initial commit

This commit is contained in:
malloc62 2022-10-06 18:00:27 -04:00
commit a384da0f9d
39 changed files with 6193 additions and 0 deletions

10
.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
.vercel
.output

1
.npmrc Normal file
View file

@ -0,0 +1 @@
engine-strict=true

38
README.md Normal file
View file

@ -0,0 +1,38 @@
# create-svelte
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm create svelte@latest
# create a new project in my-app
npm create svelte@latest my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.

4567
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

27
package.json Normal file
View file

@ -0,0 +1,27 @@
{
"name": "allof-space",
"version": "0.0.1",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"server": "node build/index.js --port 3000",
},
"devDependencies": {
"@fontsource/fira-mono": "^4.5.0",
"@neoconfetti/svelte": "^1.0.0",
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"svelte": "^3.46.0",
"vite": "^3.1.0"
},
"type": "module",
"dependencies": {
"@sveltejs/adapter-node": "^1.0.0-next.96",
"bcrypt": "^5.0.1",
"cookie": "^0.5.0",
"sqlite": "^4.1.2",
"sqlite3": "^5.1.1",
"svelte-preprocess": "^4.10.7"
}
}

24
src/app.html Normal file
View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" href="/img/logo.svg">
<title>Aloreia</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<meta name="description" content="Create your community's hub on Aloreia" />
<link rel="stylesheet" href="/css/index.css">
<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=Noto+Sans:wght@400;700;900&display=swap" rel="stylesheet">
%sveltekit.head%
</head>
<body data-sveltekit-prefetch>
%sveltekit.body%
</body>
</html>

View file

@ -0,0 +1,5 @@
<div class="footer">
<div class='header-section button-section'>
<a href="/about">About Us</a>
</div>
</div>

View file

@ -0,0 +1,56 @@
<script>
export let params, header, data;
export let action = '';
export let id = '';
export let form = '';
export let submit = function(e) {
var request = new XMLHttpRequest();
request.addEventListener('load', function() {
form = request.responseText;
});
request.open('POST', this.action, true);
request.send(new FormData(e.target));
e.preventDefault();
};
</script>
<div class="content-main form">
<div>
{#if form?.success == 'login'}
<p><i>Account successfully created. <a href='/login'>Log into an account to use it.</a></i></p>
{:else if form == 'exists'}
<p><i>Account already exists.</i></p>
{:else if form == 'missing'}
<p><i>Some parameters are missing.</i></p>
{:else if form == 'long'}
<p><i>Some parameters exceed the character limit.</i></p>
{:else if form == 'nouser'}
<p><i>This user does not exist.</i></p>
{:else if form == 'loggedin'}
<p><i>Successfully logged in.</i></p>
{:else if form == 'wrongpass'}
<p><i>Password is incorrect.</i></p>
{:else if form == 'invalid'}
<p><i>Username uses invalid characters.</i></p>
{:else if form == 'noauth'}
<p><i>User is not properly authenticated.</i></p>
{/if}
<form on:submit='{submit}' method="POST" id='{id}' action="{action}">
<h1>{header}</h1>
{#each params as param}
<p class='formleft'><input type='{param.type}' name='{param.name}' placeholder='{param.desc}'></p>
{/each}
<p class='formleft'><input type='submit' class='button' value='Submit'></p>
<slot name='extraInfo' />
</form>
</div>
<div>
<p>
<slot />
</p>
</div>
</div>

View file

@ -0,0 +1,31 @@
<script>
import { dev } from '$app/environment';
var authJson = "";
async function main() {
if (dev) {
var authUser = await fetch('http://localhost:5173/api/auth/session',{method: 'POST'});
} else {
var authUser = await fetch('https://allof.space/api/auth/session',{method: 'POST'});
}
try {
authJson = await authUser.text();
} catch(error) {
}
}
main();
</script>
<div class="header">
<div class='header-section button-section'>
<img src="/img/logo-alt.svg" align="left" class="icon-logo">
<a href="/">Aloreia</a>
</div>
<div class='header-section button-section'>
{#if authJson == ""}
<a href="/register">Register</a>
<a href="/login">Login</a>
{:else}
<a href='/hub'>Explore</a>
<a href="/user/{authJson}">{authJson}</a>
{/if}
</div>
</div>

View file

@ -0,0 +1,101 @@
<script>
import Form from '$lib/components/Form.svelte';
import { dev } from '$app/environment';
let newhub, joinhub;
let popup = "nodisplay";
let hubJson = [];
function openForm() {
popup = '';
}
function closeForm() {
popup = 'nodisplay';
}
let upload;
let icon = '/img/logo.svg';
function changeProfile(e) {
upload.dispatchEvent(new MouseEvent('click'));
}
function newIcon(e) {
icon = URL.createObjectURL(upload.files[0]);
}
function submitFunc(e, url, form) {
e.preventDefault();
const dataArray = new FormData(e.submitter.parentElement.parentElement);
for (const file of upload.files) {
dataArray.append('img', file);
}
fetch(url, {
method: 'POST',
body: dataArray
});
closeForm();
}
async function main() {
if (dev) {
var hubFetch = await fetch('http://localhost:5173/api/hub/list',{method: 'POST'});
} else {
var hubFetch = await fetch('https://allof.space/api/hub/list',{method: 'POST'});
}
try {
hubJson = await hubFetch.json();
} catch(error) {
}
}
main();
</script>
<div class='content-wrapper'>
<div class='content-main'>
<h1><div class='button-section sbig'>
Your Hubs
<a href='#'><img src="/img/new.svg" class="icon-player" on:click={openForm}></a>
</div>
{#each hubJson as hubEntry}
<a href='#'><img src="/api/hub/img?q={hubEntry.hub}" class="icon-hub pfp"></a>
{/each}
</h1>
</div>
<div class='content-main'>
<slot />
</div>
<div class='content-main'>
<h1><div class='button-sections sbig'>
Directories
</div></h1>
</div>
</div>
<div class='popup {popup}' on:click|self={closeForm}>
<Form params="{[
{
"type": "text",
"name": 'name',
'desc': 'Name of hub'
}
]}" submit='{(e) => submitFunc(e,"/api/hub/new")}' action='/api/hub/new' id='newhub' header="Create a hub...">
<input slot='extraInfo' form='newhub' type='file' accept='image/png' name='img' on:change='{newIcon}' bind:this='{upload}'>
<img src="{icon}" align='right' class="image-inline pfp" on:click={changeProfile}>
</Form>
<Form params="{[
{
"type": "text",
"name": 'invite',
'desc': 'Invite code'
}
]}" submit='{(e) => submitFunc(e,"/api/hub/join")}' bind:this='{joinhub}' action='/api/hub/join' header="Or join a hub">
</Form>
</div>

View file

@ -0,0 +1,61 @@
<script>
export let videoSource = "/";
import { onMount } from 'svelte';
let displayPlay = 'block', displayPause = 'none';
let prog = 0, duration = 0, time = 0;
let video;
function play() {
displayPause = 'none';
displayPlay = 'block';
video.pause();
};
function pause() {
displayPause = 'block';
displayPlay = 'none';
video.play();
};
function bar(e) {
var pos = (e.pageX - (this.offsetLeft + this.offsetParent.offsetLeft)) / this.offsetWidth;
video.currentTime = pos * video.duration;
}
function parseTime(time) {
let h = Math.floor(time / 60 / 60) + "";
let m = Math.floor(time / 60 % 60) + "";
let s = Math.floor(time % 60) + "";
var outString = s.padStart(2,"0");
outString = m.padStart(2,"0") + ":" + outString;
outString = h.padStart(2,"0") + ":" + outString;
return outString;
}
function progress() {
prog = video.currentTime / video.duration * 100;
duration = parseTime(video.duration);
time = parseTime(video.currentTime);
}
</script>
<div class='content-main center'><div class='video-wrapper'>
<video class='video' bind:this='{video}' on:timeupdate='{progress}'>
<source
src="{videoSource}">
</video>
<div class='button-section'>
<img on:click='{pause}' src='/img/play.svg' class='icon-player' style='display: {displayPlay};'>
<img on:click='{play}' src='/img/pause.svg' class='icon-player' style='display: {displayPause};'>
<div on:click='{bar}' class='progress'>
<div class='progress-bar' style='width: {prog}%'></div>
<div class='progress-text'>
{time} / {duration}
</div>
</div>
</div>
</div></div>

14
src/lib/db/auth.js Normal file
View file

@ -0,0 +1,14 @@
export async function auth(event,db) {
var token = event.cookies.get('token');
var user = await db.all("SELECT user FROM token WHERE token = ?",token);
if (user && user.length > 0) {
user = user[0].user;
} else {
user = "";
}
return user;
}

21
src/lib/db/db.js Normal file
View file

@ -0,0 +1,21 @@
import { open } from 'sqlite'
import sqlite3 from 'sqlite3'
var initDb = async _ => {
var db = await open({
filename: '../space-data/main.sql',
driver: sqlite3.Database
});
db.run("CREATE TABLE IF NOT EXISTS auth (user TEXT, email TEXT, password TEXT)");
db.run("CREATE TABLE IF NOT EXISTS token (user TEXT, token TEXT)");
db.run("CREATE TABLE IF NOT EXISTS hubpairs (hub TEXT, user TEXT)");
db.run("CREATE TABLE IF NOT EXISTS hub (hub TEXT, invite TEXT)");
return db;
};
export {initDb};

12
src/routes/+layout.svelte Normal file
View file

@ -0,0 +1,12 @@
<script>
import Header from '$lib/components/Header.svelte'
import Footer from '$lib/components/Footer.svelte'
</script>
<Header />
<div class='main'>
<slot />
</div>
<Footer />

26
src/routes/+page.svelte Normal file
View file

@ -0,0 +1,26 @@
<h1 class='big'>Create Your Hub</h1>
<div class="landing-wrapper">
<div class='sbig'>
<p>
We are a platform where anyone can build up their community and chat with others. This isn't just another basic messaging application, a wide array of features (i.e. Videos, Forms, Websites, Chat, Permissions, Automation) will also present for you to take advantage of.
</p>
<p><i>
This network is in an extremely early stage of development (pre-beta), most features will be missing or barely usable.
</i></p>
</div><div class='landing-logo'>
<img src='/img/logo.svg' class='image-inline' />
</div>
</div>
<div class="content-main">
<h1>Socialize with others</h1>
<p>
Hubs on Aloreia feature chat rooms, where anyone can discuss their favorite topics.
</p>
</div>
<div class="content-main">
<h1>Easily design a website</h1>
<p>
With the Website feature, anyone can make their community have a public facing source of information that will stand out to the world.
</p>
</div>

View file

@ -0,0 +1,46 @@
/** @type {import('./$types').Actions} */
import {hash} from 'bcrypt';
import {initDb} from '$lib/db/db.js';
const db = await initDb();
const saltRounds = 10;
/** @type {import('./$types').RequestHandler} */
export async function POST(event) {
var data = await event.request.formData();
var user = data.get("username");
var rows = await db.all(
"SELECT * from auth WHERE user = ?",
[user]
);
if (rows.length == 0) {
var state = await register(data);
return {success: state};
} else {
return {success: 'exists'};
}
};
async function register(data) {
var user = data.get("username");
var email = data.get("email");
var password = data.get("password");
if (!password || !email || !user) return 'missing';
if (password.length > 256 || email.length > 64 || user.length > 32) return 'long';
const userTest = new RegExp("^[A-Za-z0-9_-]+$");
if (!userTest.test(user)) return 'invalid';
var passHash = await hash(password,saltRounds);
await db.run(
"INSERT INTO auth (user,email,password) VALUES (?,?,?)",
[user,email,passHash]
);
return 'login';
}

View file

@ -0,0 +1,44 @@
/** @type {import('./$types').Actions} */
import {compare} from 'bcrypt';
import {initDb} from '$lib/db/db.js';
import {randomBytes} from 'crypto';
import { serialize } from 'cookie';
const db = await initDb();
/** @type {import('./$types').RequestHandler} */
export async function POST(event) {
var data = await event.request.formData();
var user = data.get("username");
var password = data.get("password");
var rows = await db.all(
"SELECT * from auth WHERE user = ?",
[user]
);
if (rows && rows.length > 0) {
var isPass = await compare(password,rows[0].password);
} else {
return new Response('nouser');
}
if (isPass) {
var token = randomBytes(64).toString('hex');
await db.run("DELETE FROM token WHERE user = ?",user);
await db.run("INSERT INTO token (user,token) VALUES (?,?)",user,token);
event.cookies.set('token',token,{
path: '/',
httpOnly: true,
sameSite: 'strict',
secure: true,
maxAge: 60 * 60 * 24 * 7
})
return new Response('loggedin');
} else {
return new Response('wrongpass');
}
};

View file

@ -0,0 +1,14 @@
/** @type {import('./$types').Actions} */
import {initDb} from '$lib/db/db.js';
import {auth} from '$lib/db/auth.js';
const db = await initDb();
/** @type {import('./$types').RequestHandler} */
export async function POST(event) {
var user = await auth(event,db);
return new Response(user);
}

View file

@ -0,0 +1,13 @@
/** @type {import('./$types').Actions} */
import {readFileSync} from 'fs';
import {initDb} from '$lib/db/db.js';
const db = await initDb();
/** @type {import('./$types').RequestHandler} */
export async function GET(event) {
let hub = event.url.searchParams.get('q') + '.png';
return new Response(readFileSync(`${process.cwd()}/../space-data/hub/${hub}`));
}

View file

@ -0,0 +1,29 @@
/** @type {import('./$types').Actions} */
import {initDb} from '$lib/db/db.js';
import {auth} from '$lib/db/auth.js';
const db = await initDb();
/** @type {import('./$types').RequestHandler} */
export async function POST(event) {
var user = await auth(event,db);
if (!user) return new Response('authfail');
const dat = await event.request.formData();
var name = '';
dat.forEach(async (file, key) => {
if (key == 'invite') {
name = file.trim();
}
});
var hub = await db.all("SELECT hub FROM hub WHERE invite = ?",name);
if (!hub || hub.length < 1) return new Response('nohub');
await db.run("DELETE FROM hubpairs WHERE hub = ? AND user = ?",hub[0].hub,user);
await db.run("INSERT INTO hubpairs (hub,user) VALUES (?,?)",hub[0].hub,user);
return new Response('success');
};

View file

@ -0,0 +1,13 @@
/** @type {import('./$types').Actions} */
import {initDb} from '$lib/db/db.js';
import {auth} from '$lib/db/auth.js';
const db = await initDb();
/** @type {import('./$types').RequestHandler} */
export async function POST(event) {
var user = await auth(event,db);
var hubs = await db.all("SELECT hub FROM hubpairs WHERE user = ?",user);
return new Response(JSON.stringify(hubs));
}

View file

@ -0,0 +1,46 @@
/** @type {import('./$types').Actions} */
import {auth} from '$lib/db/auth.js';
import {initDb} from '$lib/db/db.js';
import {writeFileSync} from 'fs';
import {randomBytes} from 'crypto';
const db = await initDb();
/** @type {import('./$types').RequestHandler} */
export async function POST(event) {
var user = await auth(event,db);
if (!user) return new Response('authfail');
const dat = await event.request.formData();
var name = '';
dat.forEach(async (file, key) => {
if (key == 'name') {
name = file.trim();
}
});
if (name.length > 64) return new Response('long');
const userTest = new RegExp("^[A-Za-z0-9_ -]+$");
if (!userTest.test(name)) return new Response('invalid');
var hubs = await db.all("SELECT hub FROM hubpairs WHERE hub = ?",name);
if (hubs && hubs.length > 0) return new Response('hubexists');
const file = '';
dat.forEach(async (file, key) => {
if (key == 'img' && file.arrayBuffer) {
writeFileSync(`${process.cwd()}/../space-data/hub/${name}.png`, Buffer.from(await file.arrayBuffer()));
}
});
var invite = randomBytes(16).toString('hex');
await db.run("INSERT INTO hubpairs (hub,user) VALUES (?,?)",name,user);
await db.run("INSERT INTO hub (hub,invite) VALUES (?,?)",name,invite);
return new Response('success');
};

View file

@ -0,0 +1,9 @@
<script>
import Hub from '$lib/components/Hub.svelte';
</script>
<Hub>
<h1><div class='button-section sbig'>
Explore
</div></h1>
</Hub>

View file

@ -0,0 +1,6 @@
<div class='content-wrapper'>
<div class='content-main'><p>test</p></div>
<div class='content-main'><p>test</p></div>
<div class='content-main'><p>test</p></div>
<div class='content-main'><p>test</p></div>
</div>

View file

@ -0,0 +1,18 @@
<script>
import Form from '$lib/components/Form.svelte';
</script>
<Form params="{[
{
"type": "text",
"name": 'username',
'desc': 'Username'
},
{
"type": "password",
"name": 'password',
'desc': 'Password'
},
]}" action='/api/auth/login' header="Log in">
</Form>

View file

@ -0,0 +1,24 @@
<script>
import Form from '$lib/components/Form.svelte';
</script>
<Form params="{[
{
"type": "email",
"name": 'email',
'desc': 'Email address'
},
{
"type": "text",
"name": 'username',
'desc': 'Username'
},
{
"type": "password",
"name": 'password',
'desc': 'Password'
},
]}" action="/api/account/register" header="Register">
By creating an account, you are consenting to permanently follow the <a href='/tos'>Terms of Service</a> and <a href='/guidelines'>Community Guidelines</a>.
</Form>

View file

@ -0,0 +1 @@

353
static/css/index.css Normal file
View file

@ -0,0 +1,353 @@
:root {
--bg-1: #2b2323;
--bg-2: #181515;
--fg-1: #ffffff;
--shadow-1: rgba(0,0,0,1);
--primary-1: #cd3030;
--primary-2: #2b2323;
--box-1: #edddab;
--shadow-box-1: 0 2px 10px -4px var(--shadow-1);
font-family: "Noto Sans", sans-serif;
font-size: 0.85rem;
}
.main {
min-height: calc(100vh - 6rem);
width: 100vw;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
}
body {
padding: 0;
margin: 0;
font-size: 0.8rem;
background: var(--bg-2);
height: 100vh;
background-size: 1.5rem 1.5rem;
overflow-y: scroll;
overflow-x: hidden;
color: var(--fg-1);
}
.content-main {
display: flex;
flex-direction: column;
margin: 1rem;
background: var(--bg-1);
max-width: 80vw;
width: 800px;
border-radius: 8px;
box-shadow: var(--shadow-box-1);
}
.icon {
width: auto;
height: 1rem;
margin-right: 0.5rem;
}
.icon-logo {
width: auto;
height: 3rem;
margin-right: 0rem;
margin-left: 0.5rem;
}
.icon-player {
width: auto;
height: 2rem;
margin: 0.3rem;
margin-left: 0;
}
.icon-hub {
width: 4rem;
height: 4rem;
margin: 0.3rem;
}
.button {
padding: 0.5rem;
border-radius: 0.5rem;
background-color: var(--primary-1);
color: var(--fg-1);
display: flex;
align-items: center;
justify-content: space-between;
width: 10rem;
font-weight: 700;
}
input, .button {
font-family: inherit;
padding: 0.5rem;
border-radius: 8px;
margin: 0.3rem;
border: none;
}
input {
width: 100%;
border: none;
}
.button-section {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
}
.form {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.form div {
width: 45%;
padding: 0 0 0 5%;
}
.form form {
width: 100%;
}
.formleft {
display: flex;
align-items: center;
flex-direction: column;
}
p, .p {
margin-left: 20px;
margin-right: 20px;
margin-top: 1rem;
margin-bottom: 1rem;
}
.p {
display: flex;
flex-direction: row;
align-items: center;
}
.header, .footer {
background: var(--primary-2);
justify-content: space-between;
display: flex;
width: 100%;
box-shadow: var(--shadow-box-1);
}
.footer {
background-color: var(--bg-1);
}
.header {
position: sticky;
top: 0;
}
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
width: 100%;
text-align: center;
}
.big {
font-size: 300%;
}
.sbig {
font-size: 150%;
}
a {
text-decoration: none;
color: #40acff;
}
.button a {
text-decoration: none;
color: white;
}
.header a, .footer a {
font-weight: 700;
color: var(--dark-1);
padding-right: 1.0rem;
padding-left: 1.0rem;
white-space: pre-wrap;
height: 3rem;
display: flex;
align-items: center;
}
.image-inline {
height: 10rem;
width: 10rem;
aspect-ratio: 1 / 1;
}
.video {
width: 700px;
height: auto;
aspect-ratio: 16 / 9;
max-width: 70vw;
margin: 2rem;
margin-bottom: 2rem;
border-radius: 16px;
}
.full {
width: 100%;
}
.landing-wrapper {
display: flex;
width: 70vw;
justify-content: space-between;
}
@media screen and (max-width: 800px) {
.landing-wrapper {
flex-direction: column;
}
.landing-logo {
align-items: center;
display: flex;
flex-direction: column;
}
}
.center {
align-items: center;
display: flex;
flex-direction: column;
}
.progress {
width: 80%;
height: 0.8rem;
border-radius: 3px;
background-color: var(--dark-1);
}
.progress-bar {
background-color: var(--primary-1);
height: 0.8rem;
border-radius: 3px;
display: flex;
overflow: hidden;
font-weight: bold;
transition: width 0.2s linear;
}
.progress-text {
display: flex;
justify-content: center;
align-items: center;
position: relative;
font-weight: bold;
top: -3.5rem;
}
.video-wrapper {
width: calc(700px+4rem);
margin: 1rem;
}
.content-wrapper {
display: grid;
grid-template-columns: 1fr 3fr 1fr;
width: 95%;
}
.content-wrapper .content-main {
width: calc(100% - 2rem);
max-width: none;
height: 85vh;
overflow-y: scroll;
-ms-overflow-style: none;
scrollbar-width: none;
}
.content-wrapper .content-main::-webkit-scrollbar {
display: none;
}
.content-wrapper .content-main h1 {
position: sticky;
top: 0;
font-size: 1rem;
background-color: var(--light-1);
}
@media screen and (max-width:1000px) {
.content-wrapper {
grid-template-columns: 1fr;
}
.form {
}
.form div {
width: 100%;
}
}
.button-section a {
display: flex;
}
h1 .button-section {
height: 2rem;
}
.popup {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0,0,0,0.7);
flex-direction: column;
}
.popup.nodisplay {
display: none;
}
.landing-logo {
filter: drop-shadow(0 0 20px var(--primary-1));
}
input[type="file"] {
display: none;
}
.pfp {
object-fit: cover;
}

0
static/img/favicon.svg Normal file
View file

100
static/img/logo-alt.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9 KiB

136
static/img/logo-legacy.svg Normal file
View file

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="250mm"
height="250mm"
viewBox="0 0 250 250"
version="1.1"
id="svg5"
sodipodi:docname="logo-legacy.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
inkscape:export-filename="malloc62d-icon.png"
inkscape:export-xdpi="24.379999"
inkscape:export-ydpi="24.379999"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.77593294"
inkscape:cx="459.44692"
inkscape:cy="521.30794"
inkscape:window-width="1880"
inkscape:window-height="1018"
inkscape:window-x="20"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" /><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient2647"><stop
style="stop-color:#ffb51f;stop-opacity:1;"
offset="0"
id="stop2643" /><stop
style="stop-color:#efe32f;stop-opacity:1;"
offset="1"
id="stop2645" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient2639"><stop
style="stop-color:#ff1f9b;stop-opacity:1;"
offset="0"
id="stop2635" /><stop
style="stop-color:#f42a2a;stop-opacity:1;"
offset="1"
id="stop2637" /></linearGradient><pattern
patternUnits="userSpaceOnUse"
width="188.97637"
height="188.97638"
patternTransform="translate(-5.5364173e-6,1.2364665e-5)"
id="pattern14822"><rect
style="fill:#e5e5e5;fill-opacity:1;stroke:none;stroke-width:50.0001;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect14409"
width="94.488182"
height="94.48819"
x="0"
y="0" /><rect
style="fill:#e5e5e5;fill-opacity:1;stroke:none;stroke-width:50.0001;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect14456"
width="94.488182"
height="94.48819"
x="94.48819"
y="94.48819" /></pattern><pattern
patternUnits="userSpaceOnUse"
width="208.68852"
height="146.2949"
patternTransform="translate(-328.73275,43.524551)"
id="pattern4915"><rect
style="fill:#000000;fill-opacity:0.536381;stroke:none;stroke-width:42.081;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4911"
width="79.975555"
height="79.07309"
x="-11.229265"
y="27.470825"
transform="matrix(0.92917028,-0.36965198,0.37981747,0.92506145,0,0)" /><rect
style="fill:#000000;fill-opacity:0.536381;stroke:none;stroke-width:42.081;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4913"
width="79.975555"
height="79.07309"
x="68.746323"
y="106.54388"
transform="matrix(0.92917028,-0.36965198,0.37981747,0.92506145,0,0)" /></pattern><pattern
patternUnits="userSpaceOnUse"
width="151.1811"
height="151.18111"
patternTransform="translate(1.2322854e-5,-1.0464052e-5)"
id="pattern4985"><rect
style="opacity:0.475458;fill:#000000;fill-opacity:0.65538;stroke:none;stroke-width:27.4349;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1"
id="rect4979"
width="75.590553"
height="75.590553"
x="0"
y="0"
ry="0" /><rect
style="opacity:0.475458;fill:#000000;fill-opacity:0.65538;stroke:none;stroke-width:27.4349;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1"
id="rect4983"
width="75.590553"
height="75.590553"
x="75.590546"
y="75.590553"
ry="0" /></pattern><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2639"
id="linearGradient2641"
x1="161.15768"
y1="210.52983"
x2="129.85103"
y2="130.7025"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2647"
id="linearGradient2649"
x1="132.88432"
y1="116.86043"
x2="108.41238"
y2="27.568117"
gradientUnits="userSpaceOnUse" /></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"><path
id="path4678"
style="fill:url(#linearGradient2649);fill-opacity:1;fill-rule:evenodd;stroke-width:2.64583333;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke:none;stroke-opacity:1;stroke-dasharray:none;paint-order:stroke fill markers"
d="M 125.00012 23.91792 L 113.24063 35.677409 L 98.837895 27.362154 L 90.52264 41.764376 L 74.459021 37.460246 L 70.154891 53.524382 L 53.524382 53.524382 L 53.524382 70.154891 L 37.460246 74.459021 L 41.764376 90.52264 L 27.362154 98.837895 L 35.677409 113.24063 L 23.91792 125.00012 L 35.677409 136.75961 L 27.362154 151.16183 L 85.23304 135.65529 L 66.777319 125.00012 L 85.23304 114.34444 L 74.57736 95.888721 L 95.888721 95.888721 L 95.888721 74.57736 L 114.34444 85.23304 L 125.00012 66.777319 L 135.65529 85.23304 L 154.11152 74.57736 L 154.11152 95.888721 L 175.42237 95.888721 L 164.7672 114.34444 L 222.63757 98.837895 L 208.23535 90.52264 L 212.53948 74.459021 L 196.47586 70.154891 L 196.47586 53.524382 L 179.84535 53.524382 L 175.54122 37.460246 L 159.47709 41.764893 L 151.16183 27.362154 L 136.75961 35.677409 L 125.00012 23.91792 z " /><path
id="path1375"
style="fill:url(#linearGradient2641);fill-opacity:1;fill-rule:evenodd;stroke-width:2.64583333;stroke-linecap:round;stroke-miterlimit:10;paint-order:stroke fill markers;stroke:none;stroke-opacity:1;stroke-dasharray:none;stroke-linejoin:round"
d="M 222.63757 98.837895 L 164.7672 114.34444 L 183.22292 125.00012 L 164.76669 135.6558 L 175.42237 154.11152 L 154.11152 154.11152 L 154.11152 175.42237 L 135.6558 164.7672 L 125.00012 183.22292 L 114.34444 164.7672 L 95.888721 175.42237 L 95.888721 154.11152 L 74.57736 154.11152 L 85.23304 135.65529 L 27.362154 151.16183 L 41.764376 159.47709 L 37.460246 175.54122 L 53.524382 179.84535 L 53.524382 196.47586 L 70.154891 196.47586 L 74.459021 212.53948 L 90.52264 208.23535 L 98.837895 222.63757 L 113.24063 214.32232 L 125.00012 226.08181 L 136.75961 214.32232 L 151.16183 222.63757 L 159.47709 208.23535 L 175.54122 212.53948 L 179.84535 196.47586 L 196.47586 196.47586 L 196.47586 179.84535 L 212.53948 175.54122 L 208.23535 159.47709 L 222.63757 151.16183 L 214.32232 136.75961 L 226.08181 125.00012 L 214.32232 113.24063 L 222.63757 98.837895 z " /></g></svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

132
static/img/logo.svg Normal file
View file

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="250mm"
height="250mm"
viewBox="0 0 250 250"
version="1.1"
id="svg5"
sodipodi:docname="logo.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
inkscape:export-filename="malloc62d-icon.png"
inkscape:export-xdpi="24.379999"
inkscape:export-ydpi="24.379999"
xml:space="preserve"
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="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.78"
inkscape:cx="243.58974"
inkscape:cy="496.79487"
inkscape:window-width="1880"
inkscape:window-height="1018"
inkscape:window-x="20"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" /><defs
id="defs2"><pattern
patternUnits="userSpaceOnUse"
width="188.97637"
height="188.97638"
patternTransform="translate(-5.5364173e-6,1.2364665e-5)"
id="pattern14822"><rect
style="fill:#e5e5e5;fill-opacity:1;stroke:none;stroke-width:50.0001;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect14409"
width="94.488182"
height="94.48819"
x="0"
y="0" /><rect
style="fill:#e5e5e5;fill-opacity:1;stroke:none;stroke-width:50.0001;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect14456"
width="94.488182"
height="94.48819"
x="94.48819"
y="94.48819" /></pattern><pattern
patternUnits="userSpaceOnUse"
width="208.68852"
height="146.2949"
patternTransform="translate(-328.73275,43.524551)"
id="pattern4915"><rect
style="fill:#000000;fill-opacity:0.536381;stroke:none;stroke-width:42.081;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4911"
width="79.975555"
height="79.07309"
x="-11.229265"
y="27.470825"
transform="matrix(0.92917028,-0.36965198,0.37981747,0.92506145,0,0)" /><rect
style="fill:#000000;fill-opacity:0.536381;stroke:none;stroke-width:42.081;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4913"
width="79.975555"
height="79.07309"
x="68.746323"
y="106.54388"
transform="matrix(0.92917028,-0.36965198,0.37981747,0.92506145,0,0)" /></pattern><pattern
patternUnits="userSpaceOnUse"
width="151.1811"
height="151.18111"
patternTransform="translate(1.2322854e-5,-1.0464052e-5)"
id="pattern4985"><rect
style="opacity:0.475458;fill:#000000;fill-opacity:0.65538;stroke:none;stroke-width:27.4349;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1"
id="rect4979"
width="75.590553"
height="75.590553"
x="0"
y="0"
ry="0" /><rect
style="opacity:0.475458;fill:#000000;fill-opacity:0.65538;stroke:none;stroke-width:27.4349;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1"
id="rect4983"
width="75.590553"
height="75.590553"
x="75.590546"
y="75.590553"
ry="0" /></pattern></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"><circle
style="fill:#cd4040;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:13.2292;stroke-linecap:square;stroke-miterlimit:10;paint-order:stroke fill markers"
id="path1451"
cx="124.99999"
cy="124.99999"
r="93.44413" /><path
id="circle1549"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.29166667;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="M 193.29392,152.89987 C 186.67696,120.42905 158.11878,97.102143 124.98063,97.100146 91.857022,97.120573 63.320135,120.44331 56.706085,152.89987"
sodipodi:nodetypes="ccc" /><path
id="path2113"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.29166667;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="M 193.29392,152.89987 C 186.67696,120.42905 158.11878,97.102143 124.98063,97.100146 91.857022,97.120573 63.320135,120.44331 56.706085,152.89987"
sodipodi:nodetypes="ccc" /><path
id="path2135"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.29166667;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="M 97.100136,193.29393 C 129.57095,186.67697 152.89786,158.11879 152.89986,124.98063 152.87943,91.857018 129.55669,63.320131 97.100136,56.706076"
sodipodi:nodetypes="ccc" /><path
id="path2137"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.29166667;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 56.706077,97.100146 c 6.616963,32.470814 35.175142,55.797724 68.313313,55.799724 33.12359,-0.0204 61.66048,-23.34317 68.27453,-55.799724"
sodipodi:nodetypes="ccc" /><path
id="path2139"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.29166667;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 152.89986,56.706076 c -32.47081,6.616963 -55.797716,35.175142 -55.799724,68.313314 0.02043,33.1236 23.343164,61.66049 55.799724,68.27454"
sodipodi:nodetypes="ccc" /><g
id="g2280"
transform="matrix(0.27663061,0,0,0.27787109,61.191721,88.428483)"
style="stroke-width:19.08625315;stroke-dasharray:none"><path
id="path1533"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:19.08625315;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;paint-order:stroke fill markers"
d="m 267.23201,106.75292 a 36.586533,36.586533 0 0 1 -36.58653,36.58653 36.586533,36.586533 0 0 1 -36.58653,-36.58653 36.586533,36.586533 0 0 1 36.58653,-36.586537 36.586533,36.586533 0 0 1 36.58653,36.586537 z" /><path
id="circle1549-3"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:19.08625315;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 289.84044,192.58508 c -5.73373,-28.13661 -30.47996,-48.34984 -59.19484,-48.35157 -28.70226,0.0177 -53.43004,20.22732 -59.16125,48.35157"
sodipodi:nodetypes="ccc" /></g></g></svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

81
static/img/new.svg Normal file
View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="89.562248mm"
height="90.684998mm"
viewBox="0 0 89.562248 90.684997"
version="1.1"
id="svg1433"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
sodipodi:docname="new.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="namedview1435"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.79909512"
inkscape:cx="102.61607"
inkscape:cy="124.51584"
inkscape:window-width="1880"
inkscape:window-height="1018"
inkscape:window-x="20"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="rect1660" />
<defs
id="defs1430" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-64.066106,-129.18941)">
<g
id="rect1660"
transform="translate(2.835344,-26.818262)">
<rect
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:13.2292;stroke-linecap:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect1979"
width="64.751602"
height="10.947486"
x="73.636078"
y="195.87643"
ry="5.473743" />
<path
d="m 100.56141,189.28258 m 0,0 c 0,3.70038 -2.978677,6.6795 -6.67905,6.6795 h 6.67905 z m -6.67905,6.6795"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.29169;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;paint-order:stroke fill markers"
id="path1184" />
<rect
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:13.2292;stroke-linecap:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect1998"
width="64.751602"
height="10.947486"
x="168.97438"
y="-111.48564"
ry="5.473743"
transform="rotate(90)" />
<path
d="m 111.34599,189.24806 m 0,0 c 0,3.70038 2.97867,6.6795 6.67905,6.6795 h -6.67905 z m 6.67905,6.6795"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.29169;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;paint-order:stroke fill markers"
id="path1209" />
<path
d="m 100.63886,213.22883 m 0,0 c 0,-3.70037 -2.978675,-6.67949 -6.679048,-6.67949 h 6.679048 z m -6.679048,-6.67949"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.29169;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;paint-order:stroke fill markers"
id="path1211" />
<path
d="m 111.42344,213.26335 m 0,0 c 0,-3.70038 2.97867,-6.67949 6.67905,-6.67949 h -6.67905 z m 6.67905,-6.67949"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.29169;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;paint-order:stroke fill markers"
id="path1213" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

56
static/img/pause.svg Normal file
View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="89.562248mm"
height="90.684998mm"
viewBox="0 0 89.562248 90.684997"
version="1.1"
id="svg1433"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
sodipodi:docname="pause.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="namedview1435"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.79909512"
inkscape:cx="23.776894"
inkscape:cy="95.733284"
inkscape:window-width="1880"
inkscape:window-height="1018"
inkscape:window-x="20"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="rect1660" />
<defs
id="defs1430" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-64.066106,-129.18941)">
<g
id="rect1660"
transform="translate(2.835344,-26.818262)">
<path
style="color:#000000;fill:#000000;fill-rule:evenodd;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10;-inkscape-stroke:none;paint-order:stroke fill markers"
d="m 70.822582,158.5625 v 6.61523 70.96485 6.61328 h 24.071635 v -6.61328 -70.96485 -6.61523 z"
id="path3217" />
<path
style="color:#000000;fill:#000000;fill-rule:evenodd;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10;-inkscape-stroke:none;paint-order:stroke fill markers"
d="m 118.44759,158.5625 v 6.61523 70.96485 6.61328 h 24.07165 v -6.61328 -70.96485 -6.61523 z"
id="path5540" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

53
static/img/play.svg Normal file
View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="96.923981mm"
height="116.49903mm"
viewBox="0 0 96.923981 116.49903"
version="1.1"
id="svg1433"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
sodipodi:docname="play.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="namedview1435"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.1300912"
inkscape:cx="-7.963959"
inkscape:cy="208.39026"
inkscape:window-width="1880"
inkscape:window-height="1018"
inkscape:window-x="20"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="rect1660" />
<defs
id="defs1430" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-60.400215,-116.38079)">
<g
id="rect1660"
transform="translate(2.835344,-26.818262)">
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:7.9375;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="M 76.874192,243.57895 139.0562,202.45448 76.874192,160.46218 Z"
id="path3217"
sodipodi:nodetypes="ccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

0
static/js/editor.js Normal file
View file

5
static/robots.txt Normal file
View file

@ -0,0 +1,5 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow: /login/
Disallow: /register/
Disallow: /auth/

13
svelte.config.js Normal file
View file

@ -0,0 +1,13 @@
import adapter from '@sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: preprocess(),
kit: {
adapter: adapter({out: 'build'}),
csrf: false
}
};
export default config;

7
vite.config.js Normal file
View file

@ -0,0 +1,7 @@
import { sveltekit } from '@sveltejs/kit/vite';
const config = {
plugins: [sveltekit()]
};
export default config;