Replace local scripts with 💎 Stargem
This commit is contained in:
parent
636334a38c
commit
4c9402d04e
31 changed files with 386 additions and 323 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,3 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
.venv
|
.venv
|
||||||
_capsule
|
dist
|
||||||
|
|
10
Dockerfile
10
Dockerfile
|
@ -1,10 +0,0 @@
|
||||||
FROM alpine:latest
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY requirements.txt .
|
|
||||||
RUN apk update \
|
|
||||||
&& apk add python3 py3-pip lowdown \
|
|
||||||
&& python3 -m pip install -r requirements.txt --break-system-packages
|
|
||||||
COPY *.py ./
|
|
||||||
ENTRYPOINT [ "python3" ]
|
|
||||||
CMD [ "_generate.py" ]
|
|
21
Makefile
21
Makefile
|
@ -1,21 +0,0 @@
|
||||||
env := development
|
|
||||||
|
|
||||||
default: clean generate
|
|
||||||
|
|
||||||
clean:
|
|
||||||
\rm -rf _capsule __pycache__
|
|
||||||
|
|
||||||
generate:
|
|
||||||
docker compose run --rm -e GEMINI_ENV=${env} gemini
|
|
||||||
|
|
||||||
draft:
|
|
||||||
docker compose run --rm -e GEMINI_ENV=${env} gemini _draft.py
|
|
||||||
|
|
||||||
publish:
|
|
||||||
docker compose run --rm -e GEMINI_ENV=${env} gemini _publish.py
|
|
||||||
|
|
||||||
unpublish:
|
|
||||||
docker compose run --rm -e GEMINI_ENV=${env} gemini _unpublish.py
|
|
||||||
|
|
||||||
build:
|
|
||||||
docker compose build --no-cache
|
|
10
_draft.py
10
_draft.py
|
@ -1,10 +0,0 @@
|
||||||
from slugify import slugify
|
|
||||||
|
|
||||||
import _utils
|
|
||||||
|
|
||||||
title = input("Enter draft's title: ")
|
|
||||||
slug = slugify(title)
|
|
||||||
fm = _utils.loads("---\n---\n")
|
|
||||||
fm.metadata["title"] = title
|
|
||||||
with open(f"_drafts/{slug}.gmi", mode="w", encoding="utf8") as file:
|
|
||||||
file.write(_utils.dumps(fm))
|
|
74
_generate.py
74
_generate.py
|
@ -1,74 +0,0 @@
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import _utils
|
|
||||||
|
|
||||||
if not os.path.exists("_capsule"):
|
|
||||||
os.makedirs("_capsule")
|
|
||||||
|
|
||||||
with open("_layouts/home.gmi", mode="r", encoding="utf8") as file:
|
|
||||||
home_body = file.read()
|
|
||||||
with open("_layouts/article.gmi", mode="r", encoding="utf8") as file:
|
|
||||||
article_body = file.read()
|
|
||||||
with open("_includes/header.gmi", mode="r", encoding="utf8") as file:
|
|
||||||
header_body = file.read()
|
|
||||||
with open("_includes/footer.gmi", mode="r", encoding="utf8") as file:
|
|
||||||
footer_body = file.read()
|
|
||||||
with open("_includes/links.gmi", mode="r", encoding="utf8") as file:
|
|
||||||
links_body = file.read()
|
|
||||||
|
|
||||||
articles = glob.glob("_posts/*.gmi")
|
|
||||||
articles.sort()
|
|
||||||
|
|
||||||
if os.getenv("GEMINI_ENV") != "production":
|
|
||||||
articles += glob.glob("_drafts/*.gmi")
|
|
||||||
|
|
||||||
today = datetime.today().strftime("%F")
|
|
||||||
year = datetime.today().strftime("%Y")
|
|
||||||
|
|
||||||
articles_list = []
|
|
||||||
|
|
||||||
for article in articles:
|
|
||||||
gmi = article.replace("_posts/", "").replace("_drafts/", "")
|
|
||||||
|
|
||||||
fm = _utils.load(article)
|
|
||||||
article_title = fm.metadata["title"]
|
|
||||||
article_date = fm.metadata.get("date")
|
|
||||||
article_content = fm.content
|
|
||||||
|
|
||||||
if article_date is None:
|
|
||||||
article_date = today
|
|
||||||
gmi = f"{article_date}-{gmi}"
|
|
||||||
elif isinstance(article_date, str):
|
|
||||||
article_date = datetime.fromisoformat(article_date).strftime("%Y-%m-%d")
|
|
||||||
|
|
||||||
body = (
|
|
||||||
article_body.replace("%%header%%", header_body)
|
|
||||||
.replace("%%links%%", links_body)
|
|
||||||
.replace("%%title%%", f"{article_title}\n{article_date}\n")
|
|
||||||
.replace("%%body%%", article_content)
|
|
||||||
.replace("%%footer%%", footer_body)
|
|
||||||
.replace("%%year%%", year)
|
|
||||||
)
|
|
||||||
|
|
||||||
articles_list.append(f"=> {gmi} {article_date} {article_title}")
|
|
||||||
with open(f"_capsule/{gmi}", mode="w", encoding="utf8") as file:
|
|
||||||
file.write(body)
|
|
||||||
|
|
||||||
articles_list.sort(reverse=True)
|
|
||||||
|
|
||||||
fm = _utils.load("index.gmi")
|
|
||||||
home_content = fm.content
|
|
||||||
|
|
||||||
body = (
|
|
||||||
home_body.replace("%%header%%", header_body)
|
|
||||||
.replace("%%links%%", links_body)
|
|
||||||
.replace("%%body%%", home_content)
|
|
||||||
.replace("%%articles%%", "\n".join(articles_list))
|
|
||||||
.replace("%%footer%%", footer_body)
|
|
||||||
.replace("%%year%%", year)
|
|
||||||
)
|
|
||||||
|
|
||||||
with open("_capsule/index.gmi", mode="w", encoding="utf8") as file:
|
|
||||||
file.write(body)
|
|
|
@ -1 +0,0 @@
|
||||||
© %%year%% Erick Ruiz de Chavez
|
|
|
@ -1,12 +0,0 @@
|
||||||
%%header%%
|
|
||||||
|
|
||||||
=> / Front page
|
|
||||||
|
|
||||||
## %%title%%
|
|
||||||
|
|
||||||
%%body%%
|
|
||||||
|
|
||||||
%%links%%
|
|
||||||
|
|
||||||
|
|
||||||
%%footer%%
|
|
|
@ -1,11 +0,0 @@
|
||||||
%%header%%
|
|
||||||
|
|
||||||
%%body%%
|
|
||||||
|
|
||||||
## Articles
|
|
||||||
%%articles%%
|
|
||||||
|
|
||||||
%%links%%
|
|
||||||
|
|
||||||
|
|
||||||
%%footer%%
|
|
64
_publish.py
64
_publish.py
|
@ -1,64 +0,0 @@
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from datetime import UTC, datetime
|
|
||||||
|
|
||||||
import _utils
|
|
||||||
|
|
||||||
articles = glob.glob("_drafts/*.gmi")
|
|
||||||
print(articles)
|
|
||||||
articles.sort()
|
|
||||||
titles = []
|
|
||||||
|
|
||||||
if len(articles) == 0:
|
|
||||||
print("No drafts found")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
for article in articles:
|
|
||||||
fm = _utils.load(article)
|
|
||||||
titles.append(fm.metadata["title"])
|
|
||||||
|
|
||||||
print("\nAvailable drafts:\n")
|
|
||||||
|
|
||||||
for index, title in enumerate(titles):
|
|
||||||
print(f"\t[{index + 1}] {title}")
|
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
article = ""
|
|
||||||
selection = ""
|
|
||||||
index = -1
|
|
||||||
|
|
||||||
while index < 0 or index > len(articles):
|
|
||||||
try:
|
|
||||||
index = int(selection) - 1
|
|
||||||
|
|
||||||
if index == -1:
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
article = articles[index]
|
|
||||||
|
|
||||||
except (ValueError, IndexError):
|
|
||||||
selection = input("Enter a number (0 to exit): ")
|
|
||||||
|
|
||||||
now = datetime.now(UTC)
|
|
||||||
file_date = now.strftime("%F")
|
|
||||||
frontmatter_date = now.strftime("%F %H:%m %z")
|
|
||||||
|
|
||||||
|
|
||||||
fm = _utils.load(article)
|
|
||||||
fm.metadata["date"] = frontmatter_date
|
|
||||||
|
|
||||||
with open(
|
|
||||||
article.replace("_drafts/", f"_posts/{file_date}-"),
|
|
||||||
mode="w",
|
|
||||||
encoding="utf8",
|
|
||||||
) as file:
|
|
||||||
file.write(_utils.dumps(fm))
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.remove(article)
|
|
||||||
except PermissionError:
|
|
||||||
print(f"Permission denied to delete '{article}'.")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An error occurred: {e}")
|
|
|
@ -1,59 +0,0 @@
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import _utils
|
|
||||||
|
|
||||||
articles = glob.glob("_posts/*.gmi")
|
|
||||||
articles.sort(reverse=True)
|
|
||||||
titles = []
|
|
||||||
|
|
||||||
if len(articles) == 0:
|
|
||||||
print("No articles found")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
for article in articles:
|
|
||||||
fm = _utils.load(article)
|
|
||||||
titles.append(fm.metadata["title"])
|
|
||||||
|
|
||||||
print("\nAvailable articles:\n")
|
|
||||||
|
|
||||||
for index, title in enumerate(titles):
|
|
||||||
print(f"\t[{index + 1}] {title}")
|
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
article = ""
|
|
||||||
selection = ""
|
|
||||||
index = -1
|
|
||||||
|
|
||||||
while index < 0 or index > len(articles):
|
|
||||||
try:
|
|
||||||
index = int(selection) - 1
|
|
||||||
|
|
||||||
if index == -1:
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
article = articles[index]
|
|
||||||
|
|
||||||
except (ValueError, IndexError):
|
|
||||||
selection = input("Enter a number (0 to exit): ")
|
|
||||||
|
|
||||||
fm = _utils.load(article)
|
|
||||||
file_date = datetime.fromisoformat(fm.metadata["date"]).strftime("%Y-%m-%d")
|
|
||||||
del fm.metadata["date"]
|
|
||||||
|
|
||||||
with open(
|
|
||||||
article.replace(f"_posts/{file_date}-", "_drafts/"),
|
|
||||||
mode="w",
|
|
||||||
encoding="utf8",
|
|
||||||
) as file:
|
|
||||||
file.write(_utils.dumps(fm))
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.remove(article)
|
|
||||||
except PermissionError:
|
|
||||||
print(f"Permission denied to delete '{article}'.")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An error occurred: {e}")
|
|
50
_utils.py
50
_utils.py
|
@ -1,50 +0,0 @@
|
||||||
from dataclasses import dataclass, field
|
|
||||||
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Article:
|
|
||||||
metadata: dict = field(default_factory=dict)
|
|
||||||
content: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
def load(file_name) -> Article:
|
|
||||||
content = ""
|
|
||||||
with open(file=file_name, mode="r", encoding="utf8") as file:
|
|
||||||
content = file.read()
|
|
||||||
|
|
||||||
return loads(content)
|
|
||||||
|
|
||||||
|
|
||||||
def loads(content: str) -> Article:
|
|
||||||
lines = content.splitlines()
|
|
||||||
|
|
||||||
start = -1
|
|
||||||
end = -1
|
|
||||||
|
|
||||||
for index, line in enumerate(lines):
|
|
||||||
if line.startswith("---"):
|
|
||||||
if start == -1:
|
|
||||||
start = index
|
|
||||||
elif end == -1:
|
|
||||||
end = index
|
|
||||||
break
|
|
||||||
|
|
||||||
if start == -1 or end == -1:
|
|
||||||
raise ValueError("Missing frontmatter delimiters")
|
|
||||||
|
|
||||||
metadata = lines[start + 1 : end]
|
|
||||||
content = lines[end + 1 :]
|
|
||||||
|
|
||||||
metadata = yaml.safe_load("\n".join(metadata))
|
|
||||||
if not metadata:
|
|
||||||
metadata = {}
|
|
||||||
return Article(
|
|
||||||
metadata=metadata,
|
|
||||||
content="\n".join(content),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def dumps(article: Article) -> str:
|
|
||||||
return f"""---\n{yaml.dump(article.metadata)}---\n{article.content}\n"""
|
|
|
@ -1,5 +0,0 @@
|
||||||
services:
|
|
||||||
gemini:
|
|
||||||
build: .
|
|
||||||
volumes:
|
|
||||||
- .:/app
|
|
|
@ -74,4 +74,4 @@ To help you understand the labels I've used, here's a quick guide to the emojis
|
||||||
|
|
||||||
## Honorary Mentions
|
## Honorary Mentions
|
||||||
|
|
||||||
- Keyboard Maestro (💻,1️⃣,🌐)
|
- Keyboard Maestro (💻,1️⃣,🌐)
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
template: home
|
||||||
---
|
---
|
||||||
Hi 👋, I'm Erick!
|
Hi 👋, I'm Erick!
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
python-slugify==8.0.4
|
|
||||||
PyYAML==6.0.2
|
|
||||||
text-unidecode==1.3
|
|
19
static/bookmarks.gmi
Normal file
19
static/bookmarks.gmi
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Bookmarks
|
||||||
|
|
||||||
|
## Social
|
||||||
|
=> gemini://station.martinrue.com/ Station
|
||||||
|
=> gemini://bbs.geminispace.org/ BBS
|
||||||
|
|
||||||
|
## Agregators
|
||||||
|
=> gemini://warmedal.se/~antenna/ Antenna
|
||||||
|
=> gemini://skyjake.fi/~Cosmos/ Cosmos
|
||||||
|
|
||||||
|
## Capsules
|
||||||
|
=> gemini://erick.is/ Erick
|
||||||
|
=> gemini://gemi.dev/ Gemi.dev
|
||||||
|
=> gemini://skyjake.fi/ skyjake
|
||||||
|
=> gemini://cities.yesterweb.org/ Yestercities
|
||||||
|
|
||||||
|
## Gemini
|
||||||
|
=> gemini://geminiprotocol.net/ Project Gemini
|
||||||
|
=> gemini://skyjake.fi/lagrange/getting_started.gmi Getting Started
|
71
static/robots.txt
Normal file
71
static/robots.txt
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# Modified GoToSocial robots.txt
|
||||||
|
|
||||||
|
# AI scrapers and the like.
|
||||||
|
# https://github.com/ai-robots-txt/ai.robots.txt/
|
||||||
|
User-agent: AI2Bot
|
||||||
|
User-agent: Ai2Bot-Dolma
|
||||||
|
User-agent: Amazonbot
|
||||||
|
User-agent: anthropic-ai
|
||||||
|
User-agent: Applebot
|
||||||
|
User-agent: Applebot-Extended
|
||||||
|
User-agent: Bytespider
|
||||||
|
User-agent: CCBot
|
||||||
|
User-agent: ChatGPT-User
|
||||||
|
User-agent: Claude-Web
|
||||||
|
User-agent: ClaudeBot
|
||||||
|
User-agent: cohere-ai
|
||||||
|
User-agent: cohere-training-data-crawler
|
||||||
|
User-agent: Diffbot
|
||||||
|
User-agent: DuckAssistBot
|
||||||
|
User-agent: FacebookBot
|
||||||
|
User-agent: FriendlyCrawler
|
||||||
|
User-agent: Google-Extended
|
||||||
|
User-agent: GoogleOther
|
||||||
|
User-agent: GoogleOther-Image
|
||||||
|
User-agent: GoogleOther-Video
|
||||||
|
User-agent: GPTBot
|
||||||
|
User-agent: iaskspider/2.0
|
||||||
|
User-agent: ICC-Crawler
|
||||||
|
User-agent: ImagesiftBot
|
||||||
|
User-agent: img2dataset
|
||||||
|
User-agent: ISSCyberRiskCrawler
|
||||||
|
User-agent: Kangaroo Bot
|
||||||
|
User-agent: Meta-ExternalAgent
|
||||||
|
User-agent: Meta-ExternalFetcher
|
||||||
|
User-agent: OAI-SearchBot
|
||||||
|
User-agent: omgili
|
||||||
|
User-agent: omgilibot
|
||||||
|
User-agent: PanguBot
|
||||||
|
User-agent: PerplexityBot
|
||||||
|
User-agent: PetalBot
|
||||||
|
User-agent: Scrapy
|
||||||
|
User-agent: SemrushBot
|
||||||
|
User-agent: Sidetrade indexer bot
|
||||||
|
User-agent: Timpibot
|
||||||
|
User-agent: VelenPublicWebCrawler
|
||||||
|
User-agent: Webzio-Extended
|
||||||
|
User-agent: YouBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# Marketing/SEO "intelligence" data scrapers
|
||||||
|
User-agent: AwarioRssBot
|
||||||
|
User-agent: AwarioSmartBot
|
||||||
|
User-agent: DataForSeoBot
|
||||||
|
User-agent: magpie-crawler
|
||||||
|
User-agent: Meltwater
|
||||||
|
User-agent: peer39_crawler
|
||||||
|
User-agent: peer39_crawler/1.0
|
||||||
|
User-agent: PiplBot
|
||||||
|
User-agent: scoop.it
|
||||||
|
User-agent: Seekr
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# Well-known.dev crawler. Indexes stuff under /.well-known.
|
||||||
|
# https://well-known.dev/about/
|
||||||
|
User-agent: WellKnownBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# Rules for everything else.
|
||||||
|
User-agent: *
|
||||||
|
Crawl-delay: 500
|
||||||
|
|
167
static/styles.css
Normal file
167
static/styles.css
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
html {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: #444;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
background-color: #eee;
|
||||||
|
border-left: 3px solid #555;
|
||||||
|
margin: 1rem -1rem 1rem calc(-1rem - 3px);
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
margin-left: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:has(img) {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:hover,
|
||||||
|
a:active,
|
||||||
|
a:visited {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:before {
|
||||||
|
content: '⇒';
|
||||||
|
color: #999;
|
||||||
|
font-weight: bold;
|
||||||
|
position: absolute;
|
||||||
|
left: -1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 1.5rem -1rem 2rem;
|
||||||
|
background-color: #eee;
|
||||||
|
padding: 1rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 1.5px;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:nth-last-of-type(2) {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:has(a) {
|
||||||
|
margin-top: 0rem;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
details:not([open]) summary,
|
||||||
|
details:not([open]) summary a {
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
details summary a:before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dt:not(:first-child) {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
html {
|
||||||
|
background-color: #111;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:hover,
|
||||||
|
a:active {
|
||||||
|
color: #0087bd;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: #333399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
display: block;
|
||||||
|
border: 1px solid #888;
|
||||||
|
padding: 0.375rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
outline: 0;
|
||||||
|
border-color: #80bdff;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||||
|
}
|
64
static/test.gmi
Normal file
64
static/test.gmi
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# Test page
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi fermentum dolor ut diam efficitur, non pellentesque purus vulputate. Mauris imperdiet sapien at cursus ullamcorper. Donec viverra, purus a viverra varius, leo augue ullamcorper purus, vitae mattis ipsum velit at nibh. Maecenas iaculis aliquam tempor. Mauris sed convallis nunc, laoreet facilisis sem. Pellentesque ultrices, mi at euismod vehicula, turpis ante aliquet arcu, sit amet tincidunt lacus ligula non leo. Quisque fringilla faucibus quam id placerat.
|
||||||
|
|
||||||
|
=> test.svg Test SVG Image
|
||||||
|
|
||||||
|
## Mauris fermentum feugiat enim
|
||||||
|
|
||||||
|
Get maximus augue sagittis sed. Curabitur massa tellus, porttitor nec tellus in, consequat dignissim purus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam non iaculis velit. Nulla at rutrum tellus. Ut iaculis nunc ac faucibus placerat. Duis viverra dictum diam. Donec eu auctor odio. Suspendisse eget massa condimentum lorem molestie maximus.
|
||||||
|
|
||||||
|
=> / Quisque nec nisi rutrum
|
||||||
|
|
||||||
|
Facilisis sapien ac, euismod risus. Nulla faucibus, felis nec pulvinar lacinia, nunc odio ultrices magna, porttitor dictum nisi eros vitae justo. Quisque vulputate, nisi sit amet dapibus fermentum, mi leo iaculis erat, vel tristique risus mi sit amet dui.
|
||||||
|
|
||||||
|
=> https://google.com Phasellus pretium neque nec ligula egestas
|
||||||
|
|
||||||
|
Eget porttitor nibh aliquam. Nulla facilisi. Suspendisse sollicitudin quam id tortor eleifend, in bibendum metus pulvinar. Sed ut nisi at augue ultricies tincidunt. Fusce risus diam, vulputate nec fringilla sit amet, scelerisque sed enim. Aliquam eget risus vitae urna pharetra pretium.
|
||||||
|
|
||||||
|
## Aliquam rutrum commodo quam
|
||||||
|
|
||||||
|
Get commodo justo consequat a. Morbi ornare justo sit amet ultrices congue. Ut ultrices blandit tempor. Curabitur et consequat sapien, eget lobortis metus. Vivamus pretium tellus et urna molestie commodo. Aenean vitae sapien vestibulum, hendrerit nibh sed, tempus leo. Mauris eleifend justo a felis pretium sodales.
|
||||||
|
|
||||||
|
> Cras auctor justo non elementum pharetra. Nulla ullamcorper quam nec velit aliquet convallis. Suspendisse elit nisi, euismod a nulla vitae, volutpat tempor felis. Duis urna orci, dapibus sit amet urna a, convallis ornare lorem. Donec varius vitae elit ac lobortis. Curabitur id hendrerit ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut dui in turpis efficitur rhoncus. In et lacinia lectus, ac molestie odio. Curabitur ultrices felis est, nec semper ante posuere eget. In vel elit lacus.
|
||||||
|
|
||||||
|
## Nam facilisis erat ex
|
||||||
|
|
||||||
|
* Ac ultricies eros tempus a
|
||||||
|
* Phasellus fermentum lacus odio
|
||||||
|
* Ac luctus diam cursus ac
|
||||||
|
* Orci varius natoque penatibus et magnis dis parturient montes
|
||||||
|
|
||||||
|
### Ascetur ridiculus mus
|
||||||
|
|
||||||
|
Ut vitae sagittis tellus. Fusce tortor dui, interdum in risus eget, sollicitudin fringilla ligula. Duis vehicula hendrerit enim, eu fringilla nisi fermentum non. Pellentesque feugiat maximus dolor, ac pellentesque libero venenatis id. Suspendisse vestibulum justo quis magna sodales, et varius ante congue.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> import this
|
||||||
|
The Zen of Python, by Tim Peters
|
||||||
|
|
||||||
|
Beautiful is better than ugly.
|
||||||
|
Explicit is better than implicit.
|
||||||
|
Simple is better than complex.
|
||||||
|
Complex is better than complicated.
|
||||||
|
Flat is better than nested.
|
||||||
|
Sparse is better than dense.
|
||||||
|
Readability counts.
|
||||||
|
Special cases aren't special enough to break the rules.
|
||||||
|
Although practicality beats purity.
|
||||||
|
Errors should never pass silently.
|
||||||
|
Unless explicitly silenced.
|
||||||
|
In the face of ambiguity, refuse the temptation to guess.
|
||||||
|
There should be one-- and preferably only one --obvious way to do it.
|
||||||
|
Although that way may not be obvious at first unless you're Dutch.
|
||||||
|
Now is better than never.
|
||||||
|
Although never is often better than *right* now.
|
||||||
|
If the implementation is hard to explain, it's a bad idea.
|
||||||
|
If the implementation is easy to explain, it may be a good idea.
|
||||||
|
Namespaces are one honking great idea -- let's do more of those!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phasellus molestie in metus sit amet vestibulum
|
||||||
|
|
||||||
|
Nunc cursus nunc consectetur sapien aliquet eleifend. Sed facilisis ipsum iaculis egestas accumsan. Morbi congue ac lectus a sollicitudin. Pellentesque bibendum laoreet tortor quis interdum. In sed arcu odio. Pellentesque turpis orci, mattis vitae ligula nec, semper molestie tellus. Integer nunc risus, vehicula non felis eget, ultricies faucibus urna.
|
1
static/test.svg
Normal file
1
static/test.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="400" viewBox="0 0 600 400"><rect width="100%" height="100%" fill="#EEE"/><path fill="#31343C" d="m155.52 171.08-17.16 21-2 2.48q1.68-.84 3.62-1.3 1.94-.46 4.18-.46 3.28 0 6.38 1.08t5.46 3.26q2.36 2.18 3.8 5.42 1.44 3.24 1.44 7.56 0 4.04-1.48 7.58t-4.16 6.18q-2.68 2.64-6.46 4.16t-8.34 1.52q-4.64 0-8.32-1.48-3.68-1.48-6.28-4.14-2.6-2.66-3.98-6.4t-1.38-8.3q0-4.08 1.66-8.38 1.66-4.3 5.14-8.94l13.8-18.52q.72-.96 2.1-1.64 1.38-.68 3.18-.68h8.8Zm-14.92 50.4q2.36 0 4.34-.8t3.4-2.24q1.42-1.44 2.22-3.38.8-1.94.8-4.22 0-2.48-.76-4.46t-2.16-3.36q-1.4-1.38-3.36-2.1-1.96-.72-4.32-.72-2.36 0-4.28.8-1.92.8-3.28 2.22-1.36 1.42-2.12 3.36t-.76 4.18q0 2.4.66 4.38t1.96 3.38q1.3 1.4 3.22 2.18 1.92.78 4.44.78ZM208.28 200q0 7.56-1.62 13.14-1.62 5.58-4.48 9.22-2.86 3.64-6.76 5.42-3.9 1.78-8.42 1.78t-8.38-1.78q-3.86-1.78-6.7-5.42-2.84-3.64-4.44-9.22-1.6-5.58-1.6-13.14 0-7.6 1.6-13.16 1.6-5.56 4.44-9.2 2.84-3.64 6.7-5.42 3.86-1.78 8.38-1.78 4.52 0 8.42 1.78 3.9 1.78 6.76 5.42 2.86 3.64 4.48 9.2 1.62 5.56 1.62 13.16Zm-10.2 0q0-6.28-.92-10.4t-2.46-6.56q-1.54-2.44-3.54-3.42t-4.16-.98q-2.12 0-4.1.98-1.98.98-3.5 3.42t-2.42 6.56q-.9 4.12-.9 10.4t.9 10.4q.9 4.12 2.42 6.56 1.52 2.44 3.5 3.42t4.1.98q2.16 0 4.16-.98t3.54-3.42q1.54-2.44 2.46-6.56.92-4.12.92-10.4Zm56.6 0q0 7.56-1.62 13.14-1.62 5.58-4.48 9.22-2.86 3.64-6.76 5.42-3.9 1.78-8.42 1.78t-8.38-1.78q-3.86-1.78-6.7-5.42-2.84-3.64-4.44-9.22-1.6-5.58-1.6-13.14 0-7.6 1.6-13.16 1.6-5.56 4.44-9.2 2.84-3.64 6.7-5.42 3.86-1.78 8.38-1.78 4.52 0 8.42 1.78 3.9 1.78 6.76 5.42 2.86 3.64 4.48 9.2 1.62 5.56 1.62 13.16Zm-10.2 0q0-6.28-.92-10.4t-2.46-6.56q-1.54-2.44-3.54-3.42t-4.16-.98q-2.12 0-4.1.98-1.98.98-3.5 3.42t-2.42 6.56q-.9 4.12-.9 10.4t.9 10.4q.9 4.12 2.42 6.56 1.52 2.44 3.5 3.42t4.1.98q2.16 0 4.16-.98t3.54-3.42q1.54-2.44 2.46-6.56.92-4.12.92-10.4Zm73.72 15.68-5.24 5.16-13.56-13.56-13.68 13.64-5.24-5.16 13.68-13.72L281.12 189l5.2-5.2 13.04 13.04 12.96-12.96 5.28 5.2-13 13 13.6 13.6Zm34.64-8.56h17.6V188.2q0-2.68.36-5.92l-17.96 24.84Zm26.2 0h7.28v5.72q0 .8-.52 1.38-.52.58-1.48.58h-5.28v14.12h-8.6V214.8h-24.4q-1 0-1.76-.62t-.96-1.54l-1.04-5 27.4-36.6h9.36v36.08Zm53.72-7.12q0 7.56-1.62 13.14-1.62 5.58-4.48 9.22-2.86 3.64-6.76 5.42-3.9 1.78-8.42 1.78t-8.38-1.78q-3.86-1.78-6.7-5.42-2.84-3.64-4.44-9.22-1.6-5.58-1.6-13.14 0-7.6 1.6-13.16 1.6-5.56 4.44-9.2 2.84-3.64 6.7-5.42 3.86-1.78 8.38-1.78 4.52 0 8.42 1.78 3.9 1.78 6.76 5.42 2.86 3.64 4.48 9.2 1.62 5.56 1.62 13.16Zm-10.2 0q0-6.28-.92-10.4t-2.46-6.56q-1.54-2.44-3.54-3.42t-4.16-.98q-2.12 0-4.1.98-1.98.98-3.5 3.42t-2.42 6.56q-.9 4.12-.9 10.4t.9 10.4q.9 4.12 2.42 6.56 1.52 2.44 3.5 3.42t4.1.98q2.16 0 4.16-.98t3.54-3.42q1.54-2.44 2.46-6.56.92-4.12.92-10.4Zm56.6 0q0 7.56-1.62 13.14-1.62 5.58-4.48 9.22-2.86 3.64-6.76 5.42-3.9 1.78-8.42 1.78t-8.38-1.78q-3.86-1.78-6.7-5.42-2.84-3.64-4.44-9.22-1.6-5.58-1.6-13.14 0-7.6 1.6-13.16 1.6-5.56 4.44-9.2 2.84-3.64 6.7-5.42 3.86-1.78 8.38-1.78 4.52 0 8.42 1.78 3.9 1.78 6.76 5.42 2.86 3.64 4.48 9.2 1.62 5.56 1.62 13.16Zm-10.2 0q0-6.28-.92-10.4t-2.46-6.56q-1.54-2.44-3.54-3.42t-4.16-.98q-2.12 0-4.1.98-1.98.98-3.5 3.42t-2.42 6.56q-.9 4.12-.9 10.4t.9 10.4q.9 4.12 2.42 6.56 1.52 2.44 3.5 3.42t4.1.98q2.16 0 4.16-.98t3.54-3.42q1.54-2.44 2.46-6.56.92-4.12.92-10.4Z"/></svg>
|
After Width: | Height: | Size: 3.2 KiB |
|
@ -2,4 +2,7 @@
|
||||||
|
|
||||||
=> https://linkedin.com/in/erickruizdechavez LinkedIn
|
=> https://linkedin.com/in/erickruizdechavez LinkedIn
|
||||||
=> https://github.com/eruizdechavez GitHub
|
=> https://github.com/eruizdechavez GitHub
|
||||||
=> https://erick.social/@erick Fediverse
|
=> https://erick.social/@erick Fediverse
|
||||||
|
|
||||||
|
|
||||||
|
© {{ now.strftime('%Y') }} Erick Ruiz de Chavez
|
18
templates/gemlog.jinja
Normal file
18
templates/gemlog.jinja
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% include "header.jinja" %}
|
||||||
|
{{ content }}
|
||||||
|
|
||||||
|
{% if stargem.posts -%}
|
||||||
|
## Posts
|
||||||
|
{% for post in stargem.posts -%}
|
||||||
|
=> {{ post.path }} {{ post.frontmatter.date.strftime('%F') }} {{ post.frontmatter.title }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if stargem.drafts %}
|
||||||
|
## Drafts
|
||||||
|
{% for draft in stargem.drafts -%}
|
||||||
|
=> {{ draft.path }} {{ draft.frontmatter.title }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include "footer.jinja" %}
|
21
templates/home.jinja
Normal file
21
templates/home.jinja
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% include "header.jinja" %}
|
||||||
|
{{ content }}
|
||||||
|
|
||||||
|
{% if stargem.posts -%}
|
||||||
|
## Latests Posts
|
||||||
|
{% for post in stargem.posts[:5] -%}
|
||||||
|
=> {{ post.path }} {{ post.frontmatter.date.strftime('%F') }} {{ post.frontmatter.title }}
|
||||||
|
{% endfor %}
|
||||||
|
{%- if stargem.posts | length > 5 %}
|
||||||
|
=> gemlog.gmi See All Posts
|
||||||
|
{% endif -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if stargem.drafts %}
|
||||||
|
## Drafts
|
||||||
|
{% for draft in stargem.drafts -%}
|
||||||
|
=> {{ draft.path }} {{ draft.frontmatter.title }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% include "footer.jinja" %}
|
8
templates/page.jinja
Normal file
8
templates/page.jinja
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% include "header.jinja" %}
|
||||||
|
## {{ frontmatter.title }}
|
||||||
|
|
||||||
|
=> / Front page
|
||||||
|
|
||||||
|
{{ content }}
|
||||||
|
|
||||||
|
{% include "footer.jinja" %}
|
10
templates/post.jinja
Normal file
10
templates/post.jinja
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% include "header.jinja" %}
|
||||||
|
## {{ frontmatter.title }}
|
||||||
|
|
||||||
|
=> / Front page
|
||||||
|
|
||||||
|
> Published: {% if frontmatter.date %}{{ frontmatter.date.strftime('%F') }}{%else%}TBD{% endif %}
|
||||||
|
|
||||||
|
{{ content }}
|
||||||
|
|
||||||
|
{% include "footer.jinja" %}
|
Loading…
Reference in a new issue