This commit is contained in:
2026-04-17 06:16:30 +09:00
parent 1a2410488f
commit dc7472de89
20 changed files with 254 additions and 45 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}About Nercone{% endblock %} {% block title %}About Nercone{% endblock %}
{% block extra_title %}About{% endblock %} {% block title_prefix %}About{% endblock %}
{% block description %}Nerconeについて{% endblock %} {% block description %}Nerconeについて{% endblock %}
{% block content %} {% block content %}
<p class="font-small font-bold"><a href="/" class="text-no-decoration">← ホーム</a></p> <p class="font-small font-bold"><a href="/" class="text-no-decoration">← ホーム</a></p>
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}アクセスカウンタ - Nercone{% endblock %} {% block title %}アクセスカウンタ - Nercone{% endblock %}
{% block extra_title %}Access Counter{% endblock %} {% block title_suffix %}Access Counter{% endblock %}
{% block header_desc %}ただのアクセスカウンタ{% endblock %} {% block header_desc %}ただのアクセスカウンタ{% endblock %}
{% block extra_head %} {% block extra_head %}
<style> <style>
+66 -15
View File
@@ -97,7 +97,7 @@ pre {
margin-bottom: 20px; margin-bottom: 20px;
} }
.code { code {
padding: 4px; padding: 4px;
font-family: "MesloLGS Nerd Font", monospace; font-family: "MesloLGS Nerd Font", monospace;
font-optical-sizing: auto; font-optical-sizing: auto;
@@ -109,6 +109,7 @@ a {
text-decoration: underline; text-decoration: underline;
color: inherit; color: inherit;
} }
h1 { h1 {
font-weight: 400; font-weight: 400;
line-height: 8pt; line-height: 8pt;
@@ -120,6 +121,70 @@ section h2, section h3 {
line-height: 8pt; line-height: 8pt;
} }
b {
font-weight: 400;
}
i {
font-style: italic;
}
u {
text-decoration: underline;
}
s {
text-decoration: line-through;
}
.font-bold {
font-weight: 400;
}
.font-italic {
font-style: italic;
}
.text-no-decoration {
text-decoration: none;
}
.text-underline {
text-decoration: underline;
}
.text-overline {
text-decoration: overline;
}
.text-line-through {
text-decoration: line-through;
}
.font-xx-small {
font-size: xx-small;
}
.font-x-small {
font-size: x-small;
}
.font-small {
font-size: small;
}
.font-medium {
font-size: medium;
}
.font-large {
font-size: large;
}
.font-x-large {
font-size: x-large;
}
.font-xx-large {
font-size: xx-large;
}
.font-xxx-large {
font-size: xxx-large;
}
.font-smaller {
font-size: smaller;
}
.font-larger {
font-size: larger;
}
.font-inter { .font-inter {
font-family: "Inter"; font-family: "Inter";
} }
@@ -139,20 +204,6 @@ section h2, section h3 {
font-family: "MesloLGS Nerd Font"; font-family: "MesloLGS Nerd Font";
} }
.font-small {
font-size: small;
}
.font-bold {
font-weight: 400;
}
.text-no-decoration {
text-decoration: none;
}
.text-underline {
text-decoration: underline;
}
/* Colors */ /* Colors */
.text-white { .text-white {
color: #FFFFFF; color: #FFFFFF;
+66 -15
View File
@@ -111,7 +111,7 @@ pre {
margin-bottom: 20px; margin-bottom: 20px;
} }
.code { code {
padding: 4px; padding: 4px;
font-family: "MesloLGS Nerd Font", monospace; font-family: "MesloLGS Nerd Font", monospace;
font-optical-sizing: auto; font-optical-sizing: auto;
@@ -156,6 +156,7 @@ a {
text-decoration: underline; text-decoration: underline;
color: inherit; color: inherit;
} }
h1 { h1 {
font-weight: 400; font-weight: 400;
line-height: 8pt; line-height: 8pt;
@@ -167,6 +168,70 @@ section h2, section h3 {
line-height: 8pt; line-height: 8pt;
} }
b {
font-weight: 400;
}
i {
font-style: italic;
}
u {
text-decoration: underline;
}
s {
text-decoration: line-through;
}
.font-bold {
font-weight: 400;
}
.font-italic {
font-style: italic;
}
.text-no-decoration {
text-decoration: none;
}
.text-underline {
text-decoration: underline;
}
.text-overline {
text-decoration: overline;
}
.text-line-through {
text-decoration: line-through;
}
.font-xx-small {
font-size: xx-small;
}
.font-x-small {
font-size: x-small;
}
.font-small {
font-size: small;
}
.font-medium {
font-size: medium;
}
.font-large {
font-size: large;
}
.font-x-large {
font-size: x-large;
}
.font-xx-large {
font-size: xx-large;
}
.font-xxx-large {
font-size: xxx-large;
}
.font-smaller {
font-size: smaller;
}
.font-larger {
font-size: larger;
}
.font-inter { .font-inter {
font-family: "Inter"; font-family: "Inter";
} }
@@ -186,20 +251,6 @@ section h2, section h3 {
font-family: "MesloLGS Nerd Font"; font-family: "MesloLGS Nerd Font";
} }
.font-small {
font-size: small;
}
.font-bold {
font-weight: 400;
}
.text-no-decoration {
text-decoration: none;
}
.text-underline {
text-decoration: underline;
}
/* Colors */ /* Colors */
.text-white { .text-white {
color: #FFFFFF; color: #FFFFFF;
+1 -1
View File
@@ -31,7 +31,7 @@
<div id="cursor"></div> <div id="cursor"></div>
<header class="flex"> <header class="flex">
<div class="flex-1 flex"> <div class="flex-1 flex">
<a href="/" class="text-no-decoration text-white" style="gap: 8px;"><span class="font-bold">Nercone</span> {% block extra_title %}{% endblock %}</a> <a href="/" class="text-no-decoration text-white" style="gap: 8px;">{% block title_prefix %}{% endblock %} <span class="font-bold">Nercone</span> {% block title_suffix %}{% endblock %}</a>
<p class="hide show-on-medium show-on-large">{% block header_desc %}<a href="/daily-quote/" class="text-no-decoration">{{ get_daily_quote() }}</a>{% endblock %}</p> <p class="hide show-on-medium show-on-large">{% block header_desc %}<a href="/daily-quote/" class="text-no-decoration">{{ get_daily_quote() }}</a>{% endblock %}</p>
</div> </div>
<div class="flex"> <div class="flex">
+1 -1
View File
@@ -54,7 +54,7 @@
<div id="cursor"></div> <div id="cursor"></div>
<header class="flex"> <header class="flex">
<div class="flex-1 flex"> <div class="flex-1 flex">
<a href="/" class="text-no-decoration text-white" style="gap: 8px;"><span class="font-bold">Nercone</span> {% block extra_title %}{% endblock %}</a> <a href="/" class="text-no-decoration text-white" style="gap: 8px;">{% block title_prefix %}{% endblock %} <span class="font-bold">Nercone</span> {% block title_suffix %}{% endblock %}</a>
<p class="hide show-on-medium show-on-large">{% block header_desc %}<a href="/daily-quote/" class="text-no-decoration">{{ get_daily_quote() }}</a>{% endblock %}</p> <p class="hide show-on-medium show-on-large">{% block header_desc %}<a href="/daily-quote/" class="text-no-decoration">{{ get_daily_quote() }}</a>{% endblock %}</p>
</div> </div>
<div class="flex"> <div class="flex">
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}今日の迷言 - Nercone{% endblock %} {% block title %}今日の迷言 - Nercone{% endblock %}
{% block extra_title %}Daily Quote{% endblock %} {% block title_suffix %}Daily Quote{% endblock %}
{% block header_desc %}日替わり迷言集{% endblock %} {% block header_desc %}日替わり迷言集{% endblock %}
{% block extra_head %} {% block extra_head %}
<style> <style>
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}Download / Use Banner - Nercone{% endblock %} {% block title %}Download / Use Banner - Nercone{% endblock %}
{% block extra_title %}Links{% endblock %} {% block title_suffix %}Links{% endblock %}
{% block header_desc %}バナー画像は<a href="https://creativecommons.org/licenses/by/4.0/deed.ja">CC BY 4.0</a>の元で自由に使用できます。{% endblock %} {% block header_desc %}バナー画像は<a href="https://creativecommons.org/licenses/by/4.0/deed.ja">CC BY 4.0</a>の元で自由に使用できます。{% endblock %}
{% block description %}Nerconeのバナー画像をダウンロード{% endblock %} {% block description %}Nerconeのバナー画像をダウンロード{% endblock %}
{% block content %} {% block content %}
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}{{ status_code }} {{ status_code_name }} - Nercone{% endblock %} {% block title %}{{ status_code }} {{ status_code_name }} - Nercone{% endblock %}
{% block extra_title %}{{ status_code }}{% endblock %} {% block title_suffix %}{{ status_code }}{% endblock %}
{% block header_desc %}<span class="text-tx-alt">{{ joke_message }}</span>{% endblock %} {% block header_desc %}<span class="text-tx-alt">{{ joke_message }}</span>{% endblock %}
{% block content %} {% block content %}
<h1 class="font-bold">{{ status_code }} {{ status_code_name }}</h1> <h1 class="font-bold">{{ status_code }} {{ status_code_name }}</h1>
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}Links - Nercone{% endblock %} {% block title %}Links - Nercone{% endblock %}
{% block extra_title %}Links{% endblock %} {% block title_suffix %}Links{% endblock %}
{% block header_desc %}相互リンク大歓迎{% endblock %} {% block header_desc %}相互リンク大歓迎{% endblock %}
{% block description %}Nerconeのリンク集{% endblock %} {% block description %}Nerconeのリンク集{% endblock %}
{% block content %} {% block content %}
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}Projects - Nercone{% endblock %} {% block title %}Projects - Nercone{% endblock %}
{% block extra_title %}Projects{% endblock %} {% block title_suffix %}Projects{% endblock %}
{% block header_desc %}主なプロジェクトたち{% endblock %} {% block header_desc %}主なプロジェクトたち{% endblock %}
{% block description %}Nerconeの主なプロジェクトたち{% endblock %} {% block description %}Nerconeの主なプロジェクトたち{% endblock %}
{% block content %} {% block content %}
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}PGP公開鍵 - Nercone{% endblock %} {% block title %}PGP公開鍵 - Nercone{% endblock %}
{% block extra_title %}Public Key{% endblock %} {% block title_suffix %}Public Key{% endblock %}
{% block header_desc %}PGP公開鍵{% endblock %} {% block header_desc %}PGP公開鍵{% endblock %}
{% block description %}NerconeのPGP公開鍵とそのフィンガープリント{% endblock %} {% block description %}NerconeのPGP公開鍵とそのフィンガープリント{% endblock %}
{% block content %} {% block content %}
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}QRコード - Nercone{% endblock %} {% block title %}QRコード - Nercone{% endblock %}
{% block extra_title %}QR Code{% endblock %} {% block title_suffix %}QR Code{% endblock %}
{% block header_desc %}このサイトのトップページのQRコードです{% endblock %} {% block header_desc %}このサイトのトップページのQRコードです{% endblock %}
{% block extra_head %} {% block extra_head %}
<style> <style>
+2 -2
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}サーバーのバージョン - Nercone{% endblock %} {% block title %}サーバーのバージョン - Nercone{% endblock %}
{% block extra_title %}Server Version{% endblock %} {% block title_suffix %}Server Version{% endblock %}
{% block header_desc %}サーバーのバージョン{% endblock %} {% block header_desc %}サーバーのバージョン{% endblock %}
{% block extra_head %} {% block extra_head %}
<style> <style>
@@ -22,7 +22,7 @@
<p class="text-white big-text"><span class="text-tx-alt unselectable">#</span>{{ server_version }}</p> <p class="text-white big-text"><span class="text-tx-alt unselectable">#</span>{{ server_version }}</p>
<div class="block"> <div class="block">
<p>このサーバーで現在使用されているソースコードのコミットID(ハッシュ)の先頭7文字です。</p> <p>このサーバーで現在使用されているソースコードのコミットID(ハッシュ)の先頭7文字です。</p>
<p>サーバーが起動されるたびに<span class="code">git rev-parse --short HEAD</span>を使用して取得しています。</p> <p>サーバーが起動されるたびに<code>git rev-parse --short HEAD</code>を使用して取得しています。</p>
<p>詳しくは<a href="https://gitea.nercone.dev/nercone-dev/website/">このサーバーのソースコード</a></p> <p>詳しくは<a href="https://gitea.nercone.dev/nercone-dev/website/">このサーバーのソースコード</a></p>
</div> </div>
{% endblock %} {% endblock %}
+17
View File
@@ -0,0 +1,17 @@
{% extends "/base.html" %}
{% block title %}HTML Test Page - Nercone{% endblock %}
{% block description %}nercone.devのHTMLファイル処理のテストページです。{% endblock %}
{% block content %}
<h1>H1</h1>
<h2>H2</h2>
<h3>H3</h3>
<h4>H4</h4>
<h5>H5</h5>
<h6>H6</h6>
<p><b>太字</b> <i>斜体(イタリック)</i></p>
<p>インラインコード<code>markdown.code(.inline)</code>のテスト</p>
<pre>import requests<br>print(requests.get("https://nercone.dev/welcome").text)</pre>
<p><a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">リンク</a></p>
<p><b>画像:</b></p>
<img src="/assets/images/favicon.png" width="256px">
{% endblock %}
+31
View File
@@ -0,0 +1,31 @@
---
title: Markdown Test Page - Nercone
description: nercone.devのMarkdownファイル処理のテストページです。
---
# H1
## H2
### H3
#### H4
##### H5
###### H6
**太字** *斜体(イタリック)*
インラインコード`markdown.code(.inline)`のテスト
```
import requests
print(requests.get("https://nercone.dev/welcome").text)
```
[リンク](https://www.youtube.com/watch?v=dQw4w9WgXcQ)
**HTML埋め込み(`<img>`タグ):**
<img src="/assets/images/favicon.png" width="256px">
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}404 Not Found - Nercone Redirect{% endblock %} {% block title %}404 Not Found - Nercone Redirect{% endblock %}
{% block extra_title %}Redirect{% endblock %} {% block title_suffix %}Redirect{% endblock %}
{% block header_desc %}404 Not Found{% endblock %} {% block header_desc %}404 Not Found{% endblock %}
{% block description %}見つからないよ{% endblock %} {% block description %}見つからないよ{% endblock %}
{% block content %} {% block content %}
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "/base.html" %} {% extends "/base.html" %}
{% block title %}Thank you for Helping!{% endblock %} {% block title %}Thank you for Helping!{% endblock %}
{% block extra_title %}Vulnerability Reporters{% endblock %} {% block title_suffix %}Vulnerability Reporters{% endblock %}
{% block header_desc %}These people found and pointed out security vulnerabilities in my system/service.{% endblock %} {% block header_desc %}These people found and pointed out security vulnerabilities in my system/service.{% endblock %}
{% block description %}People who found and pointed out security vulnerabilities in my system/service{% endblock %} {% block description %}People who found and pointed out security vulnerabilities in my system/service{% endblock %}
{% block content %} {% block content %}
+1
View File
@@ -9,6 +9,7 @@ requires-python = ">=3.8"
dependencies = [ dependencies = [
"rjsmin", "rjsmin",
"rcssmin", "rcssmin",
"mistune",
"markitdown", "markitdown",
"beautifulsoup4", "beautifulsoup4",
"httpx", "httpx",
+58
View File
@@ -1,6 +1,8 @@
import io import io
import json import json
import yaml
import random import random
import mistune
from pathlib import Path from pathlib import Path
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from markitdown import MarkItDown from markitdown import MarkItDown
@@ -22,6 +24,11 @@ templates.env.globals["get_access_count"] = accesscounter.get
templates.env.globals["server_version"] = server_version templates.env.globals["server_version"] = server_version
templates.env.globals["onion_site_url"] = f"http://{onion_hostname}/" templates.env.globals["onion_site_url"] = f"http://{onion_hostname}/"
class CustomHTMLRenderer(mistune.HTMLRenderer):
def block_code(self, code, **attrs):
return f'<pre>{mistune.escape(code)}</pre>\n'
htmlitdown = mistune.create_markdown(renderer=CustomHTMLRenderer(escape=False))
def get_daily_quote() -> str: def get_daily_quote() -> str:
seed = str(datetime.now(timezone.utc).date()) seed = str(datetime.now(timezone.utc).date())
with Path.cwd().joinpath("public", "quotes.txt").open("r") as f: with Path.cwd().joinpath("public", "quotes.txt").open("r") as f:
@@ -104,6 +111,8 @@ async def default_response(request: Request, full_path: str) -> Response:
markdown_mode = False markdown_mode = False
if "curl" in request.headers.get("user-agent", "").lower(): if "curl" in request.headers.get("user-agent", "").lower():
markdown_mode = True markdown_mode = True
original_path = full_path
if full_path.endswith(".md"): if full_path.endswith(".md"):
markdown_mode = True markdown_mode = True
full_path = full_path[:-3] + ".html" full_path = full_path[:-3] + ".html"
@@ -151,6 +160,55 @@ async def default_response(request: Request, full_path: str) -> Response:
except TemplateNotFound: except TemplateNotFound:
continue continue
if original_path in ["", "/"]:
markdown_candidates = ["index.md"]
elif original_path.endswith(".md"):
markdown_candidates = [original_path.lstrip('/')]
else:
markdown_candidates = [f"{original_path.strip('/')}.md", f"{original_path.strip('/')}/index.md"]
for name in markdown_candidates:
try:
markdown_path = Path.cwd().joinpath("public", name)
if not markdown_path.is_relative_to(Path.cwd().joinpath("public")):
continue
with markdown_path.open("r") as f:
markdown = f.read()
if markdown_mode:
response = PlainTextResponse(markdown, status_code=200, media_type="text/markdown")
else:
if not markdown.startswith("---"):
front = {}
body = markdown
else:
end = markdown.find("\n---", 3)
if end == -1:
front = {}
body = markdown
else:
front = yaml.safe_load(markdown[3:end]) or {}
body = markdown[end+4:].lstrip("\n")
html = htmlitdown(body)
source = f'{{% extends "{"/base-light.html" if lightweight_mode else "/base.html"}" %}}\n'
for block in front:
source += f'{{% block {block} %}}{front[block]}{{% endblock %}}\n'
source += f'{{% block content %}}\n{html}\n{{% endblock %}}\n'
content = templates.env.from_string(source).render(request=request)
response = Response(content=content, status_code=200, media_type="text/html")
if lightweight_mode:
response.set_cookie("lightweight_mode", "true", samesite="lax")
elif request.cookies.get("lightweight_mode", "") == "true":
response.set_cookie("lightweight_mode", "false", samesite="lax")
accesscounter.increase()
return response
except FileNotFoundError:
continue
try: try:
path = Path.cwd().joinpath("public", "shorturls.json") path = Path.cwd().joinpath("public", "shorturls.json")
if not path.exists(): if not path.exists():