finish up the atom news feed API
This commit is contained in:
parent
26e8909998
commit
337e56de78
@ -65,8 +65,8 @@ class AdminAPI:
|
||||
return title.lower().replace(" ", "_")
|
||||
|
||||
def _check_multilang_field(self, ml: Dict[str, str]) -> bool:
|
||||
for l in self.languages:
|
||||
if l in ml and ml[l] != "":
|
||||
for lang in self.languages:
|
||||
if lang in ml and ml[lang] != "":
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -114,24 +114,26 @@ class AdminAPI:
|
||||
)
|
||||
|
||||
def add_service(self, service: Dict[str, str]):
|
||||
if not "name" in service or service["name"] == "":
|
||||
if "name" not in service or service["name"] == "":
|
||||
raise Exception('Service structure is missing required "name" field')
|
||||
|
||||
if not "desc" in service:
|
||||
if "desc" not in service:
|
||||
raise Exception('Service structure is missing required "desc" field')
|
||||
|
||||
if (
|
||||
(not "clear" in service or service["clear"] == "")
|
||||
and (not "onion" in service or service["onion"] == "")
|
||||
and (not "i2p" in service or service["i2p"] == "")
|
||||
("clear" not in service or service["clear"] == "")
|
||||
and ("onion" not in service or service["onion"] == "")
|
||||
and ("i2p" not in service or service["i2p"] == "")
|
||||
):
|
||||
raise Exception(
|
||||
'Service structure is missing "clear", "onion" and "i2p" field, at least one needed'
|
||||
'Service structure is missing "clear", "onion" '
|
||||
+ 'and "i2p" field, at least one needed'
|
||||
)
|
||||
|
||||
if not self._check_multilang_field(service["desc"]):
|
||||
raise Exception(
|
||||
'Service structure field "desc" needs at least one supported language entry'
|
||||
'Service structure field "desc" needs at least '
|
||||
+ "one supported language entry"
|
||||
)
|
||||
|
||||
self.PUT("/v1/admin/service/add", service)
|
||||
@ -146,26 +148,28 @@ class AdminAPI:
|
||||
self.GET("/v1/admin/service/check")
|
||||
|
||||
def add_news(self, news: Dict[str, str]):
|
||||
if not "id" in news or news["id"] == "":
|
||||
if "id" not in news or news["id"] == "":
|
||||
raise Exception('News structure is missing required "id" field')
|
||||
|
||||
if not "author" in news or news["author"] == "":
|
||||
if "author" not in news or news["author"] == "":
|
||||
raise Exception('News structure is missing required "author" field')
|
||||
|
||||
if not "title" in news:
|
||||
if "title" not in news:
|
||||
raise Exception('News structure is missing required "title" field')
|
||||
|
||||
if not "content" in news:
|
||||
if "content" not in news:
|
||||
raise Exception('News structure is missing required "content" field')
|
||||
|
||||
if not self._check_multilang_field(news["title"]):
|
||||
raise Exception(
|
||||
'News structure field "title" needs at least one supported language entry'
|
||||
'News structure field "title" needs at least '
|
||||
+ "one supported language entry"
|
||||
)
|
||||
|
||||
if not self._check_multilang_field(news["content"]):
|
||||
raise Exception(
|
||||
'News structure field "content" needs at least one supported language entry'
|
||||
'News structure field "content" needs at least '
|
||||
+ "one supported language entry"
|
||||
)
|
||||
|
||||
self.PUT("/v1/admin/news/add", news)
|
||||
@ -205,8 +209,8 @@ def __handle_command(log: Log, api: AdminAPI, cmd: str) -> None:
|
||||
data["desc"] = {}
|
||||
|
||||
data["name"] = log.input("Serivce name")
|
||||
for l in api.languages:
|
||||
data["desc"][l] = log.input("Serivce desc (%s)" % l)
|
||||
for lang in api.languages:
|
||||
data["desc"][lang] = log.input("Serivce desc (%s)" % lang)
|
||||
data["check_url"] = log.input("Serivce status check URL")
|
||||
data["clear"] = log.input("Serivce clearnet URL")
|
||||
data["onion"] = log.input("Serivce onion URL")
|
||||
@ -216,7 +220,7 @@ def __handle_command(log: Log, api: AdminAPI, cmd: str) -> None:
|
||||
log.info("Service has been added")
|
||||
|
||||
case "del_service":
|
||||
api.del_service(self.log.input("Serivce name"))
|
||||
api.del_service(log.input("Serivce name"))
|
||||
log.info("Service has been deleted")
|
||||
|
||||
case "check_services":
|
||||
@ -229,11 +233,11 @@ def __handle_command(log: Log, api: AdminAPI, cmd: str) -> None:
|
||||
news["content"] = {}
|
||||
|
||||
data["id"] = log.input("News ID")
|
||||
for l in api.languages:
|
||||
data["title"][l] = log.input("News title (%s)" % l)
|
||||
for lang in api.languages:
|
||||
data["title"][lang] = log.input("News title (%s)" % lang)
|
||||
data["author"] = log.input("News author")
|
||||
for l in api.languages:
|
||||
data["content"][l] = log.input("News content (%s)" % l)
|
||||
for lang in api.languages:
|
||||
data["content"][lang] = log.input("News content (%s)" % lang)
|
||||
|
||||
api.add_news(data)
|
||||
log.info("News has been added")
|
||||
@ -245,12 +249,13 @@ def __handle_command(log: Log, api: AdminAPI, cmd: str) -> None:
|
||||
case "logs":
|
||||
logs = api.logs()
|
||||
|
||||
if None == logs["result"] or len(logs["result"]) == 0:
|
||||
if logs["result"] is None or len(logs["result"]) == 0:
|
||||
return log.info("No available logs")
|
||||
|
||||
for l in logs["result"]:
|
||||
for log in logs["result"]:
|
||||
log.info(
|
||||
"Time: %s | Action: %s" % (__format_time(l["time"]), l["action"])
|
||||
"Time: %s | Action: %s"
|
||||
% (__format_time(log["time"]), log["action"])
|
||||
)
|
||||
|
||||
|
||||
@ -283,7 +288,7 @@ def __handle_command_with_file(log: Log, api: AdminAPI, cmd: str, file: str) ->
|
||||
case "logs":
|
||||
logs = api.logs()
|
||||
|
||||
if None == logs["result"] or len(logs["result"]) == 0:
|
||||
if logs["result"] is None or len(logs["result"]) == 0:
|
||||
return log.info("No available logs")
|
||||
|
||||
__dump_json_file(logs["result"], file)
|
||||
@ -306,7 +311,7 @@ if __name__ == "__main__":
|
||||
|
||||
url = getenv(API_URL_ENV)
|
||||
|
||||
if url == None:
|
||||
if url is None:
|
||||
log.error(
|
||||
"Please specify the API URL using %s environment variable" % API_URL_ENV
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ func (ml *Multilang) Supports(lang string) bool {
|
||||
ml_ref := reflect.ValueOf(ml).Elem()
|
||||
|
||||
for i := 0; i < reflect.Indirect(ml_ref).NumField(); i++ {
|
||||
if name := reflect.Indirect(ml_ref).Field(i).Type().Name(); strings.ToLower(name) == lang {
|
||||
if name := reflect.Indirect(ml_ref).Type().Field(i).Name; strings.ToLower(name) == lang {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ func (n *News) Scan(rows *sql.Rows) (err error) {
|
||||
}
|
||||
|
||||
func (n *News) IsValid() bool {
|
||||
return n.Author != "" && n.ID != "" && !n.Title.Empty() && !n.Content.Empty()
|
||||
return n.Time != 0 && n.Author != "" && n.ID != "" && !n.Title.Empty() && !n.Content.Empty()
|
||||
}
|
||||
|
||||
func (db *Type) NewsNext(n *News) bool {
|
||||
|
@ -2,7 +2,11 @@ module github.com/ngn13/website/api
|
||||
|
||||
go 1.21.3
|
||||
|
||||
require github.com/gofiber/fiber/v2 v2.52.5
|
||||
require (
|
||||
github.com/gofiber/fiber/v2 v2.52.5
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/russross/blackfriday/v2 v2.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
@ -11,9 +15,7 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
|
@ -138,6 +138,8 @@ func PUT_AddNews(c *fiber.Ctx) error {
|
||||
return util.ErrBadJSON(c)
|
||||
}
|
||||
|
||||
news.Time = uint64(time.Now().Unix())
|
||||
|
||||
if !news.IsValid() {
|
||||
return util.ErrBadReq(c)
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/ngn13/website/api/config"
|
||||
@ -9,10 +11,29 @@ import (
|
||||
"github.com/ngn13/website/api/util"
|
||||
)
|
||||
|
||||
// feed_entry is a temporary struct used to pass the news to the news.xml
|
||||
type feed_entry struct {
|
||||
Title string
|
||||
Author string
|
||||
Time time.Time
|
||||
RFC3339 string
|
||||
Content string
|
||||
}
|
||||
|
||||
// convert UNIX timestamp to RFC3339 (format used by atom feeds)
|
||||
func (e *feed_entry) From(news *database.News, lang string) {
|
||||
e.Title = news.Title.Get(lang)
|
||||
e.Author = news.Author
|
||||
e.Time = time.Unix(int64(news.Time), 0)
|
||||
e.RFC3339 = e.Time.Format(time.RFC3339)
|
||||
e.Content = news.Content.Get(lang)
|
||||
}
|
||||
|
||||
func GET_News(c *fiber.Ctx) error {
|
||||
var (
|
||||
news []database.News
|
||||
n database.News
|
||||
entries []feed_entry
|
||||
news database.News
|
||||
indx uint64
|
||||
feed []byte
|
||||
err error
|
||||
)
|
||||
@ -27,17 +48,25 @@ func GET_News(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
lang = strings.ToLower(lang)
|
||||
indx = 0
|
||||
|
||||
for db.NewsNext(&n) {
|
||||
if n.Supports(lang) {
|
||||
news = append(news, n)
|
||||
for db.NewsNext(&news) {
|
||||
if news.Supports(lang) {
|
||||
entries = append(entries, feed_entry{})
|
||||
entries[indx].From(&news, lang)
|
||||
indx++
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
return entries[i].Time.Before(entries[j].Time)
|
||||
})
|
||||
|
||||
if feed, err = util.Render("views/news.xml", fiber.Map{
|
||||
"frontend": frontend,
|
||||
"updated": time.Now().Format(time.RFC3339),
|
||||
"entries": entries,
|
||||
"lang": lang,
|
||||
"news": news,
|
||||
}); err != nil {
|
||||
return util.ErrInternal(c, err)
|
||||
}
|
||||
|
@ -1,6 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>{{.frontend.Host}} news</title>
|
||||
<updated>2025-01-02T20:46:24Z</updated>
|
||||
<subtitle>News and updates about my self-hosted services and projects</subtitle>
|
||||
<link href="{{.frontend.String}}/news"></link>
|
||||
<updated>{{.updated}}</updated>
|
||||
<subtitle>News and updates about my projects and self-hosted services</subtitle>
|
||||
<link href="{{.frontend.JoinPath "/news"}}"></link>
|
||||
{{ range .entries }}
|
||||
<entry>
|
||||
<title>{{.Title}}</title>
|
||||
<updated>{{.RFC3339}}</updated>
|
||||
<author>
|
||||
<name>{{.Author}}</name>
|
||||
</author>
|
||||
<content>{{.Content}}</content>
|
||||
</entry>
|
||||
{{ end }}
|
||||
</feed>
|
||||
|
9
app/.prettierrc
Normal file
9
app/.prettierrc
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
29
app/package-lock.json
generated
29
app/package-lock.json
generated
@ -17,6 +17,8 @@
|
||||
"@sveltejs/adapter-node": "^5.2.11",
|
||||
"@sveltejs/kit": "^2.15.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.3",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.2",
|
||||
"svelte": "^5.16.0",
|
||||
"vite": "^5.4.11"
|
||||
}
|
||||
@ -1330,6 +1332,33 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
|
||||
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-svelte": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.2.tgz",
|
||||
"integrity": "sha512-kRPjH8wSj2iu+dO+XaUv4vD8qr5mdDmlak3IT/7AOgGIMRG86z/EHOLauFcClKEnOUf4A4nOA7sre5KrJD4Raw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"prettier": "^3.0.0",
|
||||
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.9",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.9.tgz",
|
||||
|
@ -5,13 +5,17 @@
|
||||
"scripts": {
|
||||
"dev": "VITE_API_URL_DEV=http://127.0.0.1:7001 vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview --host"
|
||||
"preview": "vite preview --host",
|
||||
"lint": "prettier --check .",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.3.1",
|
||||
"@sveltejs/adapter-node": "^5.2.11",
|
||||
"@sveltejs/kit": "^2.15.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.3",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.2",
|
||||
"svelte": "^5.16.0",
|
||||
"vite": "^5.4.11"
|
||||
},
|
||||
|
@ -1,9 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=1024">
|
||||
<link rel="icon" href="data:;base64,=">
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<link rel="icon" href="data:;base64,=" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
|
@ -1,15 +1,18 @@
|
||||
<script>
|
||||
export let title
|
||||
export let title;
|
||||
|
||||
let current = ""
|
||||
let i = 0
|
||||
let current = "";
|
||||
let i = 0;
|
||||
|
||||
while (title.length > i) {
|
||||
let c = title[i]
|
||||
setTimeout(()=>{
|
||||
current += c
|
||||
}, 100*(i+1))
|
||||
i += 1
|
||||
let c = title[i];
|
||||
setTimeout(
|
||||
() => {
|
||||
current += c;
|
||||
},
|
||||
100 * (i + 1)
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -38,7 +41,15 @@
|
||||
padding: 25px;
|
||||
border-radius: 7px 7px 0px 0px;
|
||||
font-size: 20px;
|
||||
font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace;
|
||||
font-family:
|
||||
Consolas,
|
||||
Monaco,
|
||||
Lucida Console,
|
||||
Liberation Mono,
|
||||
DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono,
|
||||
Courier New,
|
||||
monospace;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,24 @@
|
||||
<script>
|
||||
export let title
|
||||
export let url
|
||||
let audio
|
||||
export let title;
|
||||
export let url;
|
||||
let audio;
|
||||
|
||||
let current = ""
|
||||
let i = 0
|
||||
let current = "";
|
||||
let i = 0;
|
||||
|
||||
while (title.length > i) {
|
||||
let c = title[i]
|
||||
setTimeout(()=>{
|
||||
current += c
|
||||
}, 100*(i+1))
|
||||
i += 1
|
||||
let c = title[i];
|
||||
setTimeout(
|
||||
() => {
|
||||
current += c;
|
||||
},
|
||||
100 * (i + 1)
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
function epicSound() {
|
||||
audio.play()
|
||||
audio.play();
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -40,7 +43,7 @@ a {
|
||||
box-shadow: var(--box-shadow);
|
||||
border-radius: var(--radius);
|
||||
cursor: pointer;
|
||||
transition: .4s;
|
||||
transition: 0.4s;
|
||||
text-decoration: none;
|
||||
border: solid 1px var(--border-color);
|
||||
}
|
||||
@ -55,7 +58,15 @@ a:hover > .title {
|
||||
padding: 25px;
|
||||
border-radius: 7px 7px 0px 0px;
|
||||
font-size: 20px;
|
||||
font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace;
|
||||
font-family:
|
||||
Consolas,
|
||||
Monaco,
|
||||
Lucida Console,
|
||||
Liberation Mono,
|
||||
DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono,
|
||||
Courier New,
|
||||
monospace;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
export let subtitle = ""
|
||||
export let subtitle = "";
|
||||
</script>
|
||||
|
||||
<header>
|
||||
@ -11,8 +11,7 @@ export let subtitle = ""
|
||||
|
||||
<style>
|
||||
header {
|
||||
background:
|
||||
linear-gradient(rgba(11, 11, 11, 0.808), rgba(1, 1, 1, 0.96)),
|
||||
background: linear-gradient(rgba(11, 11, 11, 0.808), rgba(1, 1, 1, 0.96)),
|
||||
url("https://files.ngn.tf/banner.png");
|
||||
background-size: 50%;
|
||||
width: 100%;
|
||||
|
@ -1,33 +1,30 @@
|
||||
<script>
|
||||
import { color } from "$lib/util.js";
|
||||
import NavbarLink from "./navbar_link.svelte";
|
||||
</script>
|
||||
|
||||
<nav>
|
||||
<div>
|
||||
<h3>[ngn.tf]</h3>
|
||||
</div>
|
||||
<nav style="border-bottom: solid 2px var(--{color()});">
|
||||
<h3 style="color: var(--{color()})">[ngn.tf]</h3>
|
||||
|
||||
<div>
|
||||
<NavbarLink link="/">home</NavbarLink>
|
||||
<NavbarLink link="/news">news</NavbarLink>
|
||||
<NavbarLink link="/services">services</NavbarLink>
|
||||
<NavbarLink link="/blog">blog</NavbarLink>
|
||||
<!-- <NavbarLink link="/donate">donate</NavbarLink> -->
|
||||
<NavbarLink link="https://stats.ngn.tf">status</NavbarLink>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
background: var(--dark-one);
|
||||
padding: 20px 26px 22px 20px;
|
||||
padding: 20px 30px 20px 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: solid 1.5px black;
|
||||
animation-name: borderAnimation;
|
||||
/*animation-name: borderAnimation;
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-iteration-count: infinite;*/
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
|
||||
@ -41,11 +38,6 @@ div {
|
||||
|
||||
h3 {
|
||||
font-weight: 900;
|
||||
font-size: 25px;
|
||||
color: red;
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
font-size: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -1,29 +1,21 @@
|
||||
<script>
|
||||
import { page } from "$app/stores"
|
||||
export let link
|
||||
export let type
|
||||
let audio
|
||||
|
||||
function epicSound() {
|
||||
audio.play()
|
||||
}
|
||||
import { color, click } from "$lib/util.js";
|
||||
export let link;
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<audio bind:this={audio} preload="auto">
|
||||
<source src="/click.wav" type="audio/mpeg" />
|
||||
</audio>
|
||||
{#if type==="icon"}
|
||||
<a class="icon" data-sveltekit-preload-data on:click={epicSound} href="{link}"><slot></slot></a>
|
||||
{:else}
|
||||
<a data-sveltekit-preload-data on:click={epicSound} href="{link}"><slot></slot></a>
|
||||
{/if}
|
||||
</div>
|
||||
<a
|
||||
style="text-decoration-color: var(--{color()})"
|
||||
data-sveltekit-preload-data
|
||||
on:click={click}
|
||||
href={link}
|
||||
>
|
||||
<slot></slot>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
a {
|
||||
font-weight: 700;
|
||||
font-size: 22px;
|
||||
font-size: 20px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
@ -32,16 +24,5 @@ a {
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
|
||||
animation-name: underlineAnimation;
|
||||
animation-duration: 5s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.icon:hover {
|
||||
text-decoration: none;
|
||||
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
|
||||
animation-name: colorAnimation;
|
||||
animation-duration: 5s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,17 +1,17 @@
|
||||
<script>
|
||||
export let desc
|
||||
export let url
|
||||
export let desc;
|
||||
export let url;
|
||||
|
||||
let icon = "<i class='nf nf-md-clipboard_multiple'></i>"
|
||||
let audio
|
||||
let icon = "<i class='nf nf-md-clipboard_multiple'></i>";
|
||||
let audio;
|
||||
|
||||
function copy() {
|
||||
audio.play()
|
||||
navigator.clipboard.writeText(url)
|
||||
icon = "<i class='nf nf-md-clipboard_check'></i>"
|
||||
audio.play();
|
||||
navigator.clipboard.writeText(url);
|
||||
icon = "<i class='nf nf-md-clipboard_check'></i>";
|
||||
setTimeout(() => {
|
||||
icon = "<i class='nf nf-md-clipboard_multiple'></i>"
|
||||
}, 500)
|
||||
icon = "<i class='nf nf-md-clipboard_multiple'></i>";
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<button on:click={copy}>{@html icon}</button>
|
||||
<a href="{url}"><i class="nf nf-oct-link_external"></i></a>
|
||||
<a href={url}><i class="nf nf-oct-link_external"></i></a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@ -42,7 +42,7 @@ main {
|
||||
align-items: center;
|
||||
color: white;
|
||||
gap: 100px;
|
||||
transition: .4s;
|
||||
transition: 0.4s;
|
||||
flex-grow: 1;
|
||||
flex: 1 1 0px;
|
||||
}
|
||||
@ -59,7 +59,8 @@ div p {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
a, button {
|
||||
a,
|
||||
button {
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
text-decoration: none;
|
||||
@ -70,7 +71,8 @@ a, button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a:hover, button:hover{
|
||||
a:hover,
|
||||
button:hover {
|
||||
animation-name: colorAnimation;
|
||||
animation-duration: 5s;
|
||||
animation-iteration-count: infinite;
|
||||
|
16
app/src/lib/util.js
Normal file
16
app/src/lib/util.js
Normal file
@ -0,0 +1,16 @@
|
||||
function click() {
|
||||
let audio = new Audio("/click.wav");
|
||||
audio.play();
|
||||
}
|
||||
|
||||
let colors_pos = -1;
|
||||
const colors = ["yellow", "cyan", "green", "pinkish", "red", "blue"];
|
||||
|
||||
function color() {
|
||||
if (colors_pos < 0) colors_pos = Math.floor(Math.random() * colors.length);
|
||||
else if (colors_pos >= colors.length) colors_pos = 0;
|
||||
|
||||
return colors[colors_pos];
|
||||
}
|
||||
|
||||
export { click, color };
|
@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { goto } from "$app/navigation"
|
||||
import { onMount } from "svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
|
||||
onMount(() => {
|
||||
goto("/")
|
||||
})
|
||||
goto("/");
|
||||
});
|
||||
</script>
|
||||
|
@ -9,8 +9,18 @@
|
||||
<meta content="Homepage of my personal website" property="og:description" />
|
||||
<meta content="https://ngn.tf" property="og:url" />
|
||||
<meta content="#000000" data-react-helmet="true" name="theme-color" />
|
||||
<link rel="alternate" type="application/atom+xml" href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.atom'}" title="Atom Feed">
|
||||
<link rel="alternate" type="application/rss+xml" href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.rss'}" title="RSS Feed">
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/atom+xml"
|
||||
href={import.meta.env.VITE_API_URL_DEV + "/blog/feed.atom"}
|
||||
title="Atom Feed"
|
||||
/>
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/rss+xml"
|
||||
href={import.meta.env.VITE_API_URL_DEV + "/blog/feed.rss"}
|
||||
title="RSS Feed"
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<Header>
|
||||
@ -23,7 +33,7 @@
|
||||
<Card title="whoami">
|
||||
<div class="whoami-box">
|
||||
<div class="whoami-pic">
|
||||
<img alt="My profile" src="https://files.ngn.tf/pplow.png">
|
||||
<img alt="My profile" src="https://files.ngn.tf/pplow.png" />
|
||||
<a href="https://keyoxide.org/F9E70878C2FB389AEC2BA34CA3654DF5AD9F641D">
|
||||
<c><i class="nf nf-oct-key"></i> Keyoxide</c>
|
||||
</a>
|
||||
@ -34,7 +44,9 @@
|
||||
<li>🇹🇷 I'm a high school student from Turkey</li>
|
||||
<li>🖥️ I'm interested in cyber security and programming.</li>
|
||||
<li>❤️ I love and support Free/Libre and Open Source Software (FLOSS)</li>
|
||||
<li>🐧 My GNU/Linux distribution of choice is Artix, however I am currently running Arch</li>
|
||||
<li>
|
||||
🐧 My GNU/Linux distribution of choice is Artix, however I am currently running Arch
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -49,14 +61,17 @@
|
||||
<li><c>👥</c> contributing stuff that I like</li>
|
||||
<li><c>🚩</c> solving CTFs</li>
|
||||
<li><c>🖥️</c> customizing my desktop</li>
|
||||
<li><c>📑</c> posting random stuff on my blog, you should definitely check it out btw (it's very active)</li>
|
||||
<li>
|
||||
<c>📑</c> posting random stuff on my blog, you should definitely check it out btw (it's very
|
||||
active)
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
|
||||
<Card title="wall">
|
||||
Here are some links if you want to get in contact with me, I highly
|
||||
prefer email and I usually respond to emails in 1 or 2 days, just make
|
||||
sure to check your spam folder (turns out running a TOR relay gets your IP into multiple blacklists)
|
||||
Here are some links if you want to get in contact with me, I highly prefer email and I usually
|
||||
respond to emails in 1 or 2 days, just make sure to check your spam folder (turns out running
|
||||
a TOR relay gets your IP into multiple blacklists)
|
||||
<ul>
|
||||
<li>
|
||||
<c><i class="nf nf-cod-github"></i></c>
|
||||
@ -124,7 +139,9 @@ main{
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
|
||||
box-shadow: rgba(50, 50, 93, 1) 0px 30px 60px -12px inset, rgba(0, 0, 0, 1) 0px 18px 36px -18px inset;
|
||||
box-shadow:
|
||||
rgba(50, 50, 93, 1) 0px 30px 60px -12px inset,
|
||||
rgba(0, 0, 0, 1) 0px 18px 36px -18px inset;
|
||||
}
|
||||
|
||||
ul {
|
||||
|
@ -1,9 +1,9 @@
|
||||
export async function load({ fetch }) {
|
||||
const api = import.meta.env.VITE_API_URL_DEV
|
||||
const res = await fetch(api+"/blog/sum")
|
||||
const data = await res.json()
|
||||
const api = import.meta.env.VITE_API_URL_DEV;
|
||||
const res = await fetch(api + "/blog/sum");
|
||||
const data = await res.json();
|
||||
|
||||
return {
|
||||
posts: data["result"]
|
||||
}
|
||||
posts: data["result"],
|
||||
};
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
import Header from "../../lib/header.svelte";
|
||||
import CardLink from "../../lib/card_link.svelte";
|
||||
|
||||
export let data
|
||||
let posts = data.posts
|
||||
export let data;
|
||||
let posts = data.posts;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@ -12,8 +12,18 @@
|
||||
<meta content="View my blog posts" property="og:description" />
|
||||
<meta content="https://ngn.tf" property="og:url" />
|
||||
<meta content="#000000" data-react-helmet="true" name="theme-color" />
|
||||
<link rel="alternate" type="application/atom+xml" href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.atom'}" title="Atom Feed">
|
||||
<link rel="alternate" type="application/rss+xml" href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.rss'}" title="RSS Feed">
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/atom+xml"
|
||||
href={import.meta.env.VITE_API_URL_DEV + "/blog/feed.atom"}
|
||||
title="Atom Feed"
|
||||
/>
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/rss+xml"
|
||||
href={import.meta.env.VITE_API_URL_DEV + "/blog/feed.rss"}
|
||||
title="RSS Feed"
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<Header>
|
||||
@ -22,21 +32,24 @@
|
||||
|
||||
<main>
|
||||
<div class="feed-list">
|
||||
<a href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.rss'}">
|
||||
<c><i class="nf nf-fa-rss_square"></i></c> <p>RSS</p>
|
||||
<a href={import.meta.env.VITE_API_URL_DEV + "/blog/feed.rss"}>
|
||||
<c><i class="nf nf-fa-rss_square"></i></c>
|
||||
<p>RSS</p>
|
||||
</a>
|
||||
<a href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.atom'}">
|
||||
<c><i class="nf nf-fae-atom"></i></c> <p>Atom</p>
|
||||
<a href={import.meta.env.VITE_API_URL_DEV + "/blog/feed.atom"}>
|
||||
<c><i class="nf nf-fae-atom"></i></c>
|
||||
<p>Atom</p>
|
||||
</a>
|
||||
<a href="{import.meta.env.VITE_API_URL_DEV+'/blog/feed.json'}">
|
||||
<c><i class="nf nf-seti-json"></i></c> <p>JSON</p>
|
||||
<a href={import.meta.env.VITE_API_URL_DEV + "/blog/feed.json"}>
|
||||
<c><i class="nf nf-seti-json"></i></c>
|
||||
<p>JSON</p>
|
||||
</a>
|
||||
</div>
|
||||
<div class="post-list">
|
||||
{#each posts as post}
|
||||
<CardLink url="/blog/{post.id}" title="{post.title}">
|
||||
<CardLink url="/blog/{post.id}" title={post.title}>
|
||||
<p>{post.author} | {post.date}</p>
|
||||
<br>
|
||||
<br />
|
||||
{post.content}...
|
||||
</CardLink>
|
||||
{/each}
|
||||
@ -86,7 +99,7 @@ p {
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
|
||||
transition: .2s;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.feed-list a:hover {
|
||||
|
@ -1,14 +1,14 @@
|
||||
export async function load({ fetch, params }) {
|
||||
const id = params.id
|
||||
const api = import.meta.env.VITE_API_URL_DEV
|
||||
const res = await fetch(api+"/blog/get?id="+id)
|
||||
const data = await res.json()
|
||||
const id = params.id;
|
||||
const api = import.meta.env.VITE_API_URL_DEV;
|
||||
const res = await fetch(api + "/blog/get?id=" + id);
|
||||
const data = await res.json();
|
||||
|
||||
if (data["error"] != "") {
|
||||
return {
|
||||
error: data["error"]
|
||||
}
|
||||
error: data["error"],
|
||||
};
|
||||
}
|
||||
|
||||
return data["result"]
|
||||
return data["result"];
|
||||
}
|
||||
|
@ -1,94 +1,85 @@
|
||||
<script>
|
||||
import Header from "../../../lib/header.svelte"
|
||||
import { goto } from "$app/navigation"
|
||||
import { onMount } from "svelte"
|
||||
import DOMPurify from "dompurify"
|
||||
import { marked } from "marked"
|
||||
import Header from "../../../lib/header.svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { onMount } from "svelte";
|
||||
import DOMPurify from "dompurify";
|
||||
import { marked } from "marked";
|
||||
|
||||
export let data
|
||||
let sanitized
|
||||
const api = import.meta.env.VITE_API_URL_DEV
|
||||
export let data;
|
||||
let sanitized;
|
||||
const api = import.meta.env.VITE_API_URL_DEV;
|
||||
|
||||
let upvote_status = "inactive"
|
||||
let downvote_status = "inactive"
|
||||
let voted = false
|
||||
let audio
|
||||
let upvote_status = "inactive";
|
||||
let downvote_status = "inactive";
|
||||
let voted = false;
|
||||
let audio;
|
||||
|
||||
async function get_status() {
|
||||
const res = await fetch(api+"/blog/vote/get?id="+data.id)
|
||||
const json = await res.json()
|
||||
const res = await fetch(api + "/blog/vote/get?id=" + data.id);
|
||||
const json = await res.json();
|
||||
|
||||
if (json["error"] != "") {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (json["result"] == "upvote") {
|
||||
upvote_status = "active"
|
||||
downvote_status = "inactive"
|
||||
}
|
||||
else {
|
||||
downvote_status = "active"
|
||||
upvote_status = "inactive"
|
||||
upvote_status = "active";
|
||||
downvote_status = "inactive";
|
||||
} else {
|
||||
downvote_status = "active";
|
||||
upvote_status = "inactive";
|
||||
}
|
||||
|
||||
voted = true
|
||||
voted = true;
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (data.title == undefined)
|
||||
goto("/blog")
|
||||
if (data.title == undefined) goto("/blog");
|
||||
|
||||
sanitized = DOMPurify.sanitize(
|
||||
marked.parse(data.content, { breaks: true }),
|
||||
{
|
||||
sanitized = DOMPurify.sanitize(marked.parse(data.content, { breaks: true }), {
|
||||
ADD_TAGS: ["iframe"],
|
||||
ADD_ATTR: ["allow", "allowfullscreen", "frameborder", "scrolling"]
|
||||
}
|
||||
)
|
||||
ADD_ATTR: ["allow", "allowfullscreen", "frameborder", "scrolling"],
|
||||
});
|
||||
|
||||
await get_status()
|
||||
})
|
||||
await get_status();
|
||||
});
|
||||
|
||||
async function upvote() {
|
||||
audio.play()
|
||||
const res = await fetch(api+"/blog/vote/set?id="+data.id+"&to=upvote")
|
||||
const json = await res.json()
|
||||
audio.play();
|
||||
const res = await fetch(api + "/blog/vote/set?id=" + data.id + "&to=upvote");
|
||||
const json = await res.json();
|
||||
|
||||
if (json["error"] != "") {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (voted) {
|
||||
data.vote += 2
|
||||
data.vote += 2;
|
||||
} else {
|
||||
voted = true;
|
||||
data.vote += 1;
|
||||
}
|
||||
|
||||
else {
|
||||
voted = true
|
||||
data.vote += 1
|
||||
}
|
||||
|
||||
await get_status()
|
||||
await get_status();
|
||||
}
|
||||
|
||||
async function downvote() {
|
||||
audio.play()
|
||||
const res = await fetch(api+"/blog/vote/set?id="+data.id+"&to=downvote")
|
||||
const json = await res.json()
|
||||
audio.play();
|
||||
const res = await fetch(api + "/blog/vote/set?id=" + data.id + "&to=downvote");
|
||||
const json = await res.json();
|
||||
|
||||
if (json["error"] != "") {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (voted) {
|
||||
data.vote -= 2
|
||||
data.vote -= 2;
|
||||
} else {
|
||||
voted = true;
|
||||
data.vote -= 1;
|
||||
}
|
||||
|
||||
else {
|
||||
voted = true
|
||||
data.vote -= 1
|
||||
}
|
||||
|
||||
await get_status()
|
||||
await get_status();
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -98,7 +89,7 @@
|
||||
<meta content="{data.content.substring(0, 100)}..." property="og:description" />
|
||||
<meta content="https://ngn.tf" property="og:url" />
|
||||
<meta content="#000000" data-react-helmet="true" name="theme-color" />
|
||||
<link href="/markdown.css" rel="stylesheet">
|
||||
<link href="/markdown.css" rel="stylesheet" />
|
||||
</svelte:head>
|
||||
|
||||
<Header subtitle="{data.author} | {data.date}">
|
||||
@ -113,17 +104,26 @@
|
||||
{@html sanitized}
|
||||
</div>
|
||||
<div class="votes">
|
||||
<button on:click={async ()=>{upvote()}} class="{upvote_status}">
|
||||
<button
|
||||
on:click={async () => {
|
||||
upvote();
|
||||
}}
|
||||
class={upvote_status}
|
||||
>
|
||||
<i class="nf nf-md-arrow_up_bold"></i>
|
||||
</button>
|
||||
<p>{data.vote}</p>
|
||||
<button on:click={async ()=>{downvote()}} class="{downvote_status}">
|
||||
<button
|
||||
on:click={async () => {
|
||||
downvote();
|
||||
}}
|
||||
class={downvote_status}
|
||||
>
|
||||
<i class="nf nf-md-arrow_down_bold"></i>
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
<style>
|
||||
main {
|
||||
padding: 50px 10% 50px 10%;
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
<main>
|
||||
<Card title="bash donate.sh">
|
||||
I work on free/libre and open source software and offer free services. General hosting
|
||||
and stuff costs around 550₺ (~$17) per month, so feel free to donate in order to help me keep
|
||||
everything up and running!
|
||||
I work on free/libre and open source software and offer free services. General hosting and stuff
|
||||
costs around 550₺ (~$17) per month, so feel free to donate in order to help me keep everything
|
||||
up and running!
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -39,8 +39,8 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
Also huge thanks to all of you who has donated so far, even if it's a small amount, I highly
|
||||
appreciate it. Thank you!
|
||||
Also huge thanks to all of you who has donated so far, even if it's a small amount, I highly appreciate
|
||||
it. Thank you!
|
||||
</Card>
|
||||
</main>
|
||||
|
||||
@ -62,13 +62,15 @@ table {
|
||||
box-shadow: var(--box-shadow);
|
||||
}
|
||||
|
||||
|
||||
tr,th,td{
|
||||
tr,
|
||||
th,
|
||||
td {
|
||||
color: white;
|
||||
background: var(--dark-two);
|
||||
}
|
||||
|
||||
td,th{
|
||||
td,
|
||||
th {
|
||||
border: solid 1px var(--dark-fife);
|
||||
padding: 16px;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
export async function load({ fetch }) {
|
||||
const api = import.meta.env.VITE_API_URL_DEV
|
||||
const res = await fetch(api+"/services/all")
|
||||
const data = await res.json()
|
||||
const api = import.meta.env.VITE_API_URL_DEV;
|
||||
const res = await fetch(api + "/services/all");
|
||||
const data = await res.json();
|
||||
|
||||
if (data["error"] != "") {
|
||||
return {
|
||||
error: data["error"]
|
||||
}
|
||||
error: data["error"],
|
||||
};
|
||||
}
|
||||
|
||||
// Some really bad code to convert
|
||||
@ -17,27 +17,27 @@ export async function load({ fetch }) {
|
||||
// [[service1, service2], [service4, service5], [service4...]...]
|
||||
// so i can render it in the UI easily
|
||||
|
||||
let all = data["result"]
|
||||
let counter = 0
|
||||
let currentlist = []
|
||||
let services = []
|
||||
let all = data["result"];
|
||||
let counter = 0;
|
||||
let currentlist = [];
|
||||
let services = [];
|
||||
|
||||
for (let i = 0; i < all.length; i++) {
|
||||
currentlist.push(all[i])
|
||||
counter += 1
|
||||
currentlist.push(all[i]);
|
||||
counter += 1;
|
||||
|
||||
if (i == all.length - 1 && counter != 2) {
|
||||
services.push(currentlist)
|
||||
services.push(currentlist);
|
||||
}
|
||||
|
||||
if (counter == 2) {
|
||||
services.push(currentlist)
|
||||
currentlist = []
|
||||
counter = 0
|
||||
services.push(currentlist);
|
||||
currentlist = [];
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
services
|
||||
}
|
||||
services,
|
||||
};
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
import Service from "../../lib/service.svelte";
|
||||
import Card from "../../lib/card.svelte";
|
||||
|
||||
export let data
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@ -20,7 +20,7 @@
|
||||
{#each data.services as services_list}
|
||||
<div class="flexrow">
|
||||
{#each services_list as service}
|
||||
<Service url="{service.url}" desc="{service.desc}">{service.name}</Service>
|
||||
<Service url={service.url} desc={service.desc}>{service.name}</Service>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
@ -31,28 +31,29 @@
|
||||
Here some details for all the services I offer:
|
||||
<ul>
|
||||
<li>
|
||||
<c><i class="nf nf-cod-account"></i> Registration:</c> All the services are offered for free, and all of them
|
||||
are accessiable to public. And registrations are open for the all services that support account registrations.
|
||||
<c><i class="nf nf-cod-account"></i> Registration:</c> All the services are offered for free,
|
||||
and all of them are accessiable to public. And registrations are open for the all services that
|
||||
support account registrations.
|
||||
</li>
|
||||
<li>
|
||||
<c><i class="nf nf-fa-eye_slash"></i> Privacy:</c> To protect user privacy, all the web proxy logs are cleared regularly.
|
||||
I also do not use any kind of CDN, and provide SSL encrypted connection for all the services. You can also connect all the
|
||||
services over TOR, as I do not block any traffic from TOR.
|
||||
<c><i class="nf nf-fa-eye_slash"></i> Privacy:</c> To protect user privacy, all the web proxy
|
||||
logs are cleared regularly. I also do not use any kind of CDN, and provide SSL encrypted connection
|
||||
for all the services. You can also connect all the services over TOR, as I do not block any traffic
|
||||
from TOR.
|
||||
</li>
|
||||
<li>
|
||||
<c><i class="nf nf-oct-graph"></i> Uptime:</c> Some services get restarted regularly, also sometimes I have
|
||||
issues with the hosting, so I cannot provide or guarantee %100 uptime for any of the services. I also cannot guarantee
|
||||
the that there won't be any data loss. I do take any regular backups, but your data may be lost in case of something
|
||||
like a SSD failure.
|
||||
<c><i class="nf nf-oct-graph"></i> Uptime:</c> Some services get restarted regularly, also sometimes
|
||||
I have issues with the hosting, so I cannot provide or guarantee %100 uptime for any of the services.
|
||||
I also cannot guarantee the that there won't be any data loss. I do take any regular backups,
|
||||
but your data may be lost in case of something like a SSD failure.
|
||||
</li>
|
||||
<li>
|
||||
<c><i class="nf nf-md-speedometer"></i> Speed:</c> All the services are located in Turkey, and avaliable
|
||||
over an 400 Mbit/s interface. If you are close to Turkey you should have a fairly good experience.
|
||||
If you are not, then you should probably use another provider for the service.
|
||||
<c><i class="nf nf-md-speedometer"></i> Speed:</c> All the services are located in Turkey, and
|
||||
avaliable over an 400 Mbit/s interface. If you are close to Turkey you should have a fairly good
|
||||
experience. If you are not, then you should probably use another provider for the service.
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
|
||||
</main>
|
||||
|
||||
<style>
|
||||
|
79
app/static/animations.css
Normal file
79
app/static/animations.css
Normal file
@ -0,0 +1,79 @@
|
||||
@keyframes colorAnimation {
|
||||
100%,
|
||||
0% {
|
||||
color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes borderAnimation {
|
||||
100%,
|
||||
0% {
|
||||
border-bottom-color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
border-bottom-color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
border-bottom-color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
border-bottom-color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
border-bottom-color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
border-bottom-color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
border-bottom-color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
border-bottom-color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
border-bottom-color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
border-bottom-color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
border-bottom-color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
border-bottom-color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
@ -1,13 +1,22 @@
|
||||
@import "./animations.css";
|
||||
@import "./font.css";
|
||||
|
||||
:root {
|
||||
--white: white;
|
||||
--dark-one: black;
|
||||
--white: #ffffff;
|
||||
--yellow: #d3b910;
|
||||
--cyan: #0dd2e8;
|
||||
--green: #06e00a;
|
||||
--pinkish: #d506e0;
|
||||
--red: #e8180d;
|
||||
--blue: #0536fc;
|
||||
|
||||
--dark-one: #000000;
|
||||
--dark-two: #050505;
|
||||
--dark-three: #121212;
|
||||
--dark-four: #101010;
|
||||
--dark-fife: #3a3b3c;
|
||||
--dark-six: #C0C0C0;
|
||||
--dark-six: #c0c0c0;
|
||||
|
||||
--radius: 8px;
|
||||
/*
|
||||
old shadow animation
|
||||
@ -53,252 +62,7 @@ body {
|
||||
background: #282828;
|
||||
}
|
||||
|
||||
@keyframes colorAnimation {
|
||||
100%,
|
||||
0% {
|
||||
color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes borderAnimation {
|
||||
100%,
|
||||
0% {
|
||||
border-bottom-color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
border-bottom-color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
border-bottom-color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
border-bottom-color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
border-bottom-color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
border-bottom-color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
border-bottom-color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
border-bottom-color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
border-bottom-color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
border-bottom-color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
border-bottom-color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
border-bottom-color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fullBorderAnimation {
|
||||
100%,
|
||||
0% {
|
||||
border-color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
border-color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
border-color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
border-color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
border-color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
border-color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
border-color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
border-color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
border-color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
border-color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
border-color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
border-color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gayShadowAnimation {
|
||||
100%,
|
||||
0% {
|
||||
box-shadow: rgba(255, 0, 0, 0.07) 0px 1px 2px,
|
||||
rgba(255, 0, 0, 0.07) 0px 2px 4px, rgba(255, 0, 0, 0.07) 0px 4px 8px,
|
||||
rgba(255, 0, 0, 0.07) 0px 8px 16px, rgba(255, 0, 0, 0.07) 0px 16px 32px,
|
||||
rgba(255, 0, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
8% {
|
||||
box-shadow: rgba(255, 127, 0, 0.07) 0px 1px 2px,
|
||||
rgba(255, 127, 0, 0.07) 0px 2px 4px, rgba(255, 127, 0, 0.07) 0px 4px 8px,
|
||||
rgba(255, 127, 0, 0.07) 0px 8px 16px,
|
||||
rgba(255, 127, 0, 0.07) 0px 16px 32px,
|
||||
rgba(255, 127, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
16% {
|
||||
box-shadow: rgba(255, 255, 0, 0.07) 0px 1px 2px,
|
||||
rgba(255, 255, 0, 0.07) 0px 2px 4px, rgba(255, 255, 0, 0.07) 0px 4px 8px,
|
||||
rgba(255, 255, 0, 0.07) 0px 8px 16px,
|
||||
rgba(255, 255, 0, 0.07) 0px 16px 32px,
|
||||
rgba(255, 255, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
25% {
|
||||
box-shadow: rgba(127, 255, 0, 0.07) 0px 1px 2px,
|
||||
rgba(127, 255, 0, 0.07) 0px 2px 4px, rgba(127, 255, 0, 0.07) 0px 4px 8px,
|
||||
rgba(127, 255, 0, 0.07) 0px 8px 16px,
|
||||
rgba(127, 255, 0, 0.07) 0px 16px 32px,
|
||||
rgba(127, 255, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
33% {
|
||||
box-shadow: rgba(0, 255, 0, 0.07) 0px 1px 2px,
|
||||
rgba(0, 255, 0, 0.07) 0px 2px 4px, rgba(0, 255, 0, 0.07) 0px 4px 8px,
|
||||
rgba(0, 255, 0, 0.07) 0px 8px 16px, rgba(0, 255, 0, 0.07) 0px 16px 32px,
|
||||
rgba(0, 255, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
41% {
|
||||
box-shadow: rgba(0, 255, 127, 0.07) 0px 1px 2px,
|
||||
rgba(0, 255, 127, 0.07) 0px 2px 4px, rgba(0, 255, 127, 0.07) 0px 4px 8px,
|
||||
rgba(0, 255, 127, 0.07) 0px 8px 16px,
|
||||
rgba(0, 255, 127, 0.07) 0px 16px 32px,
|
||||
rgba(0, 255, 127, 0.07) 0px 32px 64px;
|
||||
}
|
||||
50% {
|
||||
box-shadow: rgba(0, 255, 255, 0.07) 0px 1px 2px,
|
||||
rgba(0, 255, 255, 0.07) 0px 2px 4px, rgba(0, 255, 255, 0.07) 0px 4px 8px,
|
||||
rgba(0, 255, 255, 0.07) 0px 8px 16px,
|
||||
rgba(0, 255, 255, 0.07) 0px 16px 32px,
|
||||
rgba(0, 255, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
58% {
|
||||
box-shadow: rgba(0, 127, 255, 0.07) 0px 1px 2px,
|
||||
rgba(0, 127, 255, 0.07) 0px 2px 4px, rgba(0, 127, 255, 0.07) 0px 4px 8px,
|
||||
rgba(0, 127, 255, 0.07) 0px 8px 16px,
|
||||
rgba(0, 127, 255, 0.07) 0px 16px 32px,
|
||||
rgba(0, 127, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
66% {
|
||||
box-shadow: rgba(0, 0, 255, 0.07) 0px 1px 2px,
|
||||
rgba(0, 0, 255, 0.07) 0px 2px 4px, rgba(0, 0, 255, 0.07) 0px 4px 8px,
|
||||
rgba(0, 0, 255, 0.07) 0px 8px 16px, rgba(0, 0, 255, 0.07) 0px 16px 32px,
|
||||
rgba(0, 0, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
75% {
|
||||
box-shadow: rgba(127, 0, 255, 0.07) 0px 1px 2px,
|
||||
rgba(127, 0, 255, 0.07) 0px 2px 4px, rgba(127, 0, 255, 0.07) 0px 4px 8px,
|
||||
rgba(127, 0, 255, 0.07) 0px 8px 16px,
|
||||
rgba(127, 0, 255, 0.07) 0px 16px 32px,
|
||||
rgba(127, 0, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
83% {
|
||||
box-shadow: rgba(255, 0, 255, 0.07) 0px 1px 2px,
|
||||
rgba(255, 0, 255, 0.07) 0px 2px 4px, rgba(255, 0, 255, 0.07) 0px 4px 8px,
|
||||
rgba(255, 0, 255, 0.07) 0px 8px 16px,
|
||||
rgba(255, 0, 255, 0.07) 0px 16px 32px,
|
||||
rgba(255, 0, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
91% {
|
||||
box-shadow: rgba(255, 0, 127, 0.07) 0px 1px 2px,
|
||||
rgba(255, 0, 127, 0.07) 0px 2px 4px, rgba(255, 0, 127, 0.07) 0px 4px 8px,
|
||||
rgba(255, 0, 127, 0.07) 0px 8px 16px,
|
||||
rgba(255, 0, 127, 0.07) 0px 16px 32px,
|
||||
rgba(255, 0, 127, 0.07) 0px 32px 64px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes underlineAnimation {
|
||||
100%,
|
||||
0% {
|
||||
text-decoration-color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
text-decoration-color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
text-decoration-color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
text-decoration-color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
text-decoration-color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
text-decoration-color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
text-decoration-color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
text-decoration-color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
text-decoration-color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
text-decoration-color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
text-decoration-color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
text-decoration-color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
.c, c {
|
||||
.glitch {
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
|
@ -5,7 +5,8 @@
|
||||
margin: 0;
|
||||
color: #c9d1d9;
|
||||
background-color: #000;
|
||||
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial,
|
||||
sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
@ -38,7 +39,7 @@
|
||||
.markdown-body h6:hover .anchor .octicon-link:before {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
content: ' ';
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
background-color: currentColor;
|
||||
-webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
|
||||
@ -83,9 +84,9 @@
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
margin: .67em 0;
|
||||
margin: 0.67em 0;
|
||||
font-weight: 600;
|
||||
padding-bottom: .3em;
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 2em;
|
||||
border-bottom: 1px solid #21262d;
|
||||
}
|
||||
@ -139,7 +140,7 @@
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
border-bottom: 1px solid #21262d;
|
||||
height: .25em;
|
||||
height: 0.25em;
|
||||
padding: 0;
|
||||
margin: 24px 0;
|
||||
background-color: #30363d;
|
||||
@ -155,31 +156,31 @@
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.markdown-body [type=button],
|
||||
.markdown-body [type=reset],
|
||||
.markdown-body [type=submit] {
|
||||
.markdown-body [type="button"],
|
||||
.markdown-body [type="reset"],
|
||||
.markdown-body [type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
.markdown-body [type=checkbox],
|
||||
.markdown-body [type=radio] {
|
||||
.markdown-body [type="checkbox"],
|
||||
.markdown-body [type="radio"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-body [type=number]::-webkit-inner-spin-button,
|
||||
.markdown-body [type=number]::-webkit-outer-spin-button {
|
||||
.markdown-body [type="number"]::-webkit-inner-spin-button,
|
||||
.markdown-body [type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.markdown-body [type=search]::-webkit-search-cancel-button,
|
||||
.markdown-body [type=search]::-webkit-search-decoration {
|
||||
.markdown-body [type="search"]::-webkit-search-cancel-button,
|
||||
.markdown-body [type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.markdown-body ::-webkit-input-placeholder {
|
||||
color: inherit;
|
||||
opacity: .54;
|
||||
opacity: 0.54;
|
||||
}
|
||||
|
||||
.markdown-body ::-webkit-file-upload-button {
|
||||
@ -230,25 +231,25 @@
|
||||
}
|
||||
|
||||
.markdown-body a:focus,
|
||||
.markdown-body [role=button]:focus,
|
||||
.markdown-body input[type=radio]:focus,
|
||||
.markdown-body input[type=checkbox]:focus {
|
||||
.markdown-body [role="button"]:focus,
|
||||
.markdown-body input[type="radio"]:focus,
|
||||
.markdown-body input[type="checkbox"]:focus {
|
||||
outline: 2px solid #58a6ff;
|
||||
outline-offset: -2px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.markdown-body a:focus:not(:focus-visible),
|
||||
.markdown-body [role=button]:focus:not(:focus-visible),
|
||||
.markdown-body input[type=radio]:focus:not(:focus-visible),
|
||||
.markdown-body input[type=checkbox]:focus:not(:focus-visible) {
|
||||
.markdown-body [role="button"]:focus:not(:focus-visible),
|
||||
.markdown-body input[type="radio"]:focus:not(:focus-visible),
|
||||
.markdown-body input[type="checkbox"]:focus:not(:focus-visible) {
|
||||
outline: solid 1px transparent;
|
||||
}
|
||||
|
||||
.markdown-body a:focus-visible,
|
||||
.markdown-body [role=button]:focus-visible,
|
||||
.markdown-body input[type=radio]:focus-visible,
|
||||
.markdown-body input[type=checkbox]:focus-visible {
|
||||
.markdown-body [role="button"]:focus-visible,
|
||||
.markdown-body input[type="radio"]:focus-visible,
|
||||
.markdown-body input[type="checkbox"]:focus-visible {
|
||||
outline: 2px solid #58a6ff;
|
||||
outline-offset: -2px;
|
||||
box-shadow: none;
|
||||
@ -256,17 +257,24 @@
|
||||
|
||||
.markdown-body a:not([class]):focus,
|
||||
.markdown-body a:not([class]):focus-visible,
|
||||
.markdown-body input[type=radio]:focus,
|
||||
.markdown-body input[type=radio]:focus-visible,
|
||||
.markdown-body input[type=checkbox]:focus,
|
||||
.markdown-body input[type=checkbox]:focus-visible {
|
||||
.markdown-body input[type="radio"]:focus,
|
||||
.markdown-body input[type="radio"]:focus-visible,
|
||||
.markdown-body input[type="checkbox"]:focus,
|
||||
.markdown-body input[type="checkbox"]:focus-visible {
|
||||
outline-offset: 0;
|
||||
}
|
||||
|
||||
.markdown-body kbd {
|
||||
display: inline-block;
|
||||
padding: 3px 5px;
|
||||
font: 11px ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
|
||||
font:
|
||||
11px ui-monospace,
|
||||
SFMono-Regular,
|
||||
SF Mono,
|
||||
Menlo,
|
||||
Consolas,
|
||||
Liberation Mono,
|
||||
monospace;
|
||||
line-height: 10px;
|
||||
color: #c9d1d9;
|
||||
vertical-align: middle;
|
||||
@ -291,7 +299,7 @@
|
||||
|
||||
.markdown-body h2 {
|
||||
font-weight: 600;
|
||||
padding-bottom: .3em;
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 1.5em;
|
||||
border-bottom: 1px solid #21262d;
|
||||
}
|
||||
@ -308,12 +316,12 @@
|
||||
|
||||
.markdown-body h5 {
|
||||
font-weight: 600;
|
||||
font-size: .875em;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.markdown-body h6 {
|
||||
font-weight: 600;
|
||||
font-size: .85em;
|
||||
font-size: 0.85em;
|
||||
color: #8b949e;
|
||||
}
|
||||
|
||||
@ -326,7 +334,7 @@
|
||||
margin: 0;
|
||||
padding: 0 1em;
|
||||
color: #8b949e;
|
||||
border-left: .25em solid #30363d;
|
||||
border-left: 0.25em solid #30363d;
|
||||
}
|
||||
|
||||
.markdown-body ul,
|
||||
@ -355,14 +363,28 @@
|
||||
.markdown-body tt,
|
||||
.markdown-body code,
|
||||
.markdown-body samp {
|
||||
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
|
||||
font-family:
|
||||
ui-monospace,
|
||||
SFMono-Regular,
|
||||
SF Mono,
|
||||
Menlo,
|
||||
Consolas,
|
||||
Liberation Mono,
|
||||
monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown-body pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
|
||||
font-family:
|
||||
ui-monospace,
|
||||
SFMono-Regular,
|
||||
SF Mono,
|
||||
Menlo,
|
||||
Consolas,
|
||||
Liberation Mono,
|
||||
monospace;
|
||||
font-size: 12px;
|
||||
word-wrap: normal;
|
||||
}
|
||||
@ -481,7 +503,7 @@
|
||||
.markdown-body h5 code,
|
||||
.markdown-body h6 tt,
|
||||
.markdown-body h6 code {
|
||||
padding: 0 .2em;
|
||||
padding: 0 0.2em;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
@ -515,19 +537,19 @@
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.markdown-body ol[type=a] {
|
||||
.markdown-body ol[type="a"] {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
.markdown-body ol[type=A] {
|
||||
.markdown-body ol[type="A"] {
|
||||
list-style-type: upper-alpha;
|
||||
}
|
||||
|
||||
.markdown-body ol[type=i] {
|
||||
.markdown-body ol[type="i"] {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
|
||||
.markdown-body ol[type=I] {
|
||||
.markdown-body ol[type="I"] {
|
||||
list-style-type: upper-roman;
|
||||
}
|
||||
|
||||
@ -552,7 +574,7 @@
|
||||
}
|
||||
|
||||
.markdown-body li + li {
|
||||
margin-top: .25em;
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
.markdown-body dl {
|
||||
@ -595,11 +617,11 @@
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.markdown-body img[align=right] {
|
||||
.markdown-body img[align="right"] {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.markdown-body img[align=left] {
|
||||
.markdown-body img[align="left"] {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
@ -699,7 +721,7 @@
|
||||
|
||||
.markdown-body code,
|
||||
.markdown-body tt {
|
||||
padding: .2em .4em;
|
||||
padding: 0.2em 0.4em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
white-space: break-spaces;
|
||||
@ -997,12 +1019,12 @@
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item-checkbox {
|
||||
margin: 0 .2em .25em -1.4em;
|
||||
margin: 0 0.2em 0.25em -1.4em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.markdown-body .contains-task-list:dir(rtl) .task-list-item-checkbox {
|
||||
margin: 0 -1.6em .25em .2em;
|
||||
margin: 0 -1.6em 0.25em 0.2em;
|
||||
}
|
||||
|
||||
.markdown-body .contains-task-list {
|
||||
|
@ -1,14 +1,14 @@
|
||||
//import adapter from '@sveltejs/adapter-auto';
|
||||
import adapter from '@sveltejs/adapter-node';
|
||||
import adapter from "@sveltejs/adapter-node";
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
adapter: adapter()
|
||||
adapter: adapter(),
|
||||
},
|
||||
onwarn: (warning, handler) => {
|
||||
if (warning.code === "a11y-click-events-have-key-events") return
|
||||
handler(warning)
|
||||
if (warning.code === "a11y-click-events-have-key-events") return;
|
||||
handler(warning);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import { sveltekit } from "@sveltejs/kit/vite";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()]
|
||||
plugins: [sveltekit()],
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user