Remove Jekyll; Add new workflow scripts

This commit is contained in:
Erick Ruiz de Chavez 2025-01-07 08:38:30 -05:00
parent 0ddd43ef24
commit 0bd550b561
27 changed files with 168 additions and 434 deletions

6
.gitignore vendored
View file

@ -1,6 +1,2 @@
.sass-cache
.jekyll-cache
.jekyll-metadata
vendor
_site
.venv
_capsule

View file

@ -2,7 +2,9 @@ FROM alpine:latest
WORKDIR /app
COPY requirements.txt .
RUN apk add python3 py3-pip lowdown \
RUN apk update \
&& apk add python3 py3-pip lowdown \
&& python3 -m pip install -r requirements.txt --break-system-packages
COPY generate_capsule.py .
ENTRYPOINT [ "python3", "generate_capsule.py" ]
COPY *.py ./
ENTRYPOINT [ "python3" ]
CMD [ "_generate.py" ]

View file

@ -1,9 +0,0 @@
FROM ruby:3.3
EXPOSE 4000
WORKDIR /app
COPY Gemfile .
RUN gem install bundler && bundle install
ENTRYPOINT [ "bundle", "exec", "jekyll" ]
CMD [ "serve", "-H", "0.0.0.0", "--force_polling", "--livereload", "--drafts" ]

View file

@ -1,9 +0,0 @@
source "https://rubygems.org"
gem "jekyll", "~> 4.3.4"
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12"
gem "jekyll-compose", "~> 0.12.0"
gem "jekyll-commonmark"
end

View file

@ -1,84 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
bigdecimal (3.1.9)
colorator (1.1.0)
commonmarker (0.23.11)
concurrent-ruby (1.3.4)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
eventmachine (1.2.7)
ffi (1.17.0-x86_64-linux-gnu)
forwardable-extended (2.6.0)
google-protobuf (4.29.2-x86_64-linux)
bigdecimal
rake (>= 13)
http_parser.rb (0.8.0)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
jekyll (4.3.4)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 1.0)
jekyll-sass-converter (>= 2.0, < 4.0)
jekyll-watch (~> 2.0)
kramdown (~> 2.3, >= 2.3.1)
kramdown-parser-gfm (~> 1.0)
liquid (~> 4.0)
mercenary (>= 0.3.6, < 0.5)
pathutil (~> 0.9)
rouge (>= 3.0, < 5.0)
safe_yaml (~> 1.0)
terminal-table (>= 1.8, < 4.0)
webrick (~> 1.7)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-compose (0.12.0)
jekyll (>= 3.7, < 5.0)
jekyll-feed (0.17.0)
jekyll (>= 3.7, < 5.0)
jekyll-sass-converter (3.0.0)
sass-embedded (~> 1.54)
jekyll-watch (2.2.1)
listen (~> 3.0)
kramdown (2.5.1)
rexml (>= 3.3.9)
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.4.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (6.0.1)
rake (13.2.1)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rexml (3.4.0)
rouge (4.5.1)
safe_yaml (1.0.5)
sass-embedded (1.83.0-x86_64-linux-gnu)
google-protobuf (~> 4.28)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
unicode-display_width (2.6.0)
webrick (1.9.1)
PLATFORMS
x86_64-linux-gnu
DEPENDENCIES
jekyll (~> 4.3.4)
jekyll-commonmark
jekyll-compose (~> 0.12.0)
jekyll-feed (~> 0.12)
BUNDLED WITH
2.6.2

View file

@ -1,39 +1,21 @@
args :=
env := development
default: clean start
start:
docker compose up -d
rebuild:
docker compose up -d --build
stop:
docker compose down
default: clean generate
clean:
\rm -rf .jekyll-cache .saas-cache _site _capsule
docker compose down -v
\rm -rf _capsule
logs:
docker compose logs --follow --since 1m
build: build-jekyll build-gemini
build-gemini:
docker compose run --rm gemini
build-jekyll:
docker compose run --rm jekyll build
install:
docker compose run --rm --entrypoint bash jekyll -c bundle add ${args}
generate:
docker compose run --rm -e GEMINI_ENV=${env} gemini
draft:
docker compose run --rm jekyll draft ${args}
docker compose run --rm -e GEMINI_ENV=${env} gemini _draft.py
publish:
docker compose run --rm jekyll publish ${args}
docker compose run --rm -e GEMINI_ENV=${env} gemini _publish.py
unpublish:
docker compose run --rm jekyll unpublish ${args}
docker compose run --rm -e GEMINI_ENV=${env} gemini _unpublish.py
build:
docker compose build --no-cache

View file

@ -1,19 +0,0 @@
title: Erick Ruiz de Chavez
author: Erick Ruiz de Chavez
url: https://erickruizdechavez.com
exclude:
- Dockerfile*
- compose.yaml
- Makefile
- generate_capsule.py
- requirements.txt
jekyll_compose:
default_front_matter:
drafts:
layout: article
posts:
layout: article
markdown: CommonMark

13
_draft.py Normal file
View file

@ -0,0 +1,13 @@
from slugify import slugify
title = input("Enter draft's title: ")
slug = slugify(title)
body = f"""
---
title: {title}
---
"""
with open(f"_drafts/{slug}.gmi", mode="w", encoding="utf8") as file:
file.write(body)

View file

@ -1,7 +1,6 @@
---
layout: article
title: Live Long and Prosper with These Tools
links: inline
title: Live Long and Prosper with These Tools
---
I'm not entirely sure why, but I love trying out and testing productivity tools—especially those geared toward programming. Over the years, I've explored and used a wide variety of tools, and these are the ones I can't live without. Below, I've listed them in alphabetical order. For each, I'll include a brief description and explain why it stands out to me. When time and inspiration allow, I plan to write dedicated articles diving deeper into each tool. I'll also do my best to keep this list updated as I discover new favorites or stop using the current ones.
@ -77,4 +76,4 @@ To help you understand the labels I've used, here's a quick guide to the emojis
## Honorary Mentions
- Keyboard Maestro (💻,1⃣,🌐)
- Keyboard Maestro (💻,1⃣,🌐)

View file

@ -20,10 +20,12 @@ with open("_includes/links.gmi", mode="r", encoding="utf8") as file:
links_body = file.read()
articles = glob.glob("_posts/*.md")
articles.sort()
if os.getenv("GEMINI_ENV") != "production":
articles += glob.glob("_drafts/*.md")
today = datetime.today().strftime("%Y-%m-%d")
today = datetime.today().strftime("%F")
year = datetime.today().strftime("%Y")
articles_list = []
@ -38,8 +40,9 @@ for article in articles:
links = fm.get("links", "end")
result = subprocess.run(
["lowdown", "-tgemini", f"--gemini-link-{links}", article],
["lowdown", "-tgemini", f"--gemini-link-{links}", "--out-no-smarty", article],
capture_output=True,
check=True,
text=True,
)
article_content = result.stdout
@ -66,7 +69,10 @@ for article in articles:
articles_list.sort(reverse=True)
result = subprocess.run(
["lowdown", "-tgemini", "index.md"], capture_output=True, text=True
["lowdown", "-tgemini", "index.md"],
capture_output=True,
check=True,
text=True,
)
home_content = result.stdout

View file

@ -1,3 +0,0 @@
<footer class="site_footer">
&copy; {{ "now" | date: "%Y" }} {{ site.author }}
</footer>

View file

@ -1,7 +0,0 @@
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="{{ "/assets/styles.css" | relative_url }}">
<title>{{ site.title }}</title>
</head>

View file

@ -1,22 +0,0 @@
<header class="site_header">
<img
class="panda"
src="{{ 'assets/panda.webp' | relative_url }}"
alt="Generated Image of an anthropomorphic Panda wearing a sweater and jeans, sitting on a couch, using a laptop."
/>
<nav class="site_links">
{%- if page.url != "/" -%}
<a class="site_links__link" href="{{ "/" | relative_url }}">🏡 Front Page</a>
{%- endif -%}
<a class="site_links__link" href="https://linkedin.com/in/erickruizdechavez" rel="me noreferrer" target="_blank">
💼 LinkedIn
</a>
<a class="site_links__link" href="https://github.com/eruizdechavez" rel="me noreferrer" target="_blank">
🐙 GitHub
</a>
<a class="site_links__link" href="https://erick.social/@erick" rel="me noreferrer" target="_blank">
🗣 Fediverse
</a>
</nav>
</header>

View file

@ -1,5 +1,6 @@
%%header%%
=> index.gmi Front page
=> / Front page
## %%title%%
%%body%%
%%links%%

View file

@ -1,14 +0,0 @@
---
layout: default
---
<div class="article">
<h2 class="article__title">
{{ page.title | escape }}
</h2>
<time class="article__published">
{{ page.date | date: "%Y-%m-%d" }}
</time>
<div class="article__content">
{{ content }}
</div>
</div>

View file

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: "en" }}">
{%- include head.html -%}
<body>
{%- include header.html -%}
<main>
{{ content }}
</main>
{%- include footer.html -%}
</body>
</html>

View file

@ -1,21 +0,0 @@
---
layout: default
---
<div class="home">
{{ content }}
{%- if site.posts.size > 0 -%}
<section class="articles">
<h2 class="articles__heading">Articles</h2>
<ul class="articles__list">
{%- for post in site.posts -%}
<li class="articles__article">
<a href="{{ post.url | relative_url }}">
{{ post.date | date: "%Y-%m-%d" }} - {{ post.title | escape }}
</a>
</li>
{%- endfor -%}
</ul>
</section>
{%- endif -%}
</div>

View file

@ -1,5 +1,4 @@
---
layout: article
title: 'Regenerating My Blog: A Fresh Start'
date: 2024-12-22 00:45 +0000
---

View file

@ -1,8 +1,8 @@
---
layout: article
title: 'Energy Shields at Minimum: Automating Laptop Power Mode'
date: 2024-12-29 12:35 +0000
---
I love automation—not just home automation but anything that simplifies my life. For example, I use a Shortcut on my iPhone that automatically turns on Low Power Mode when the battery drops below a certain percentage.
This morning, while working on my laptop, I realized that macOS allows Low Power Mode to be set to "always on" when on battery power, but it doesn't provide an option like "only when the battery level is below X%." Naturally, I decided to create a script to achieve the same functionality on my laptop that I already enjoy on my phone.

62
_publish.py Normal file
View file

@ -0,0 +1,62 @@
import glob
import os
import sys
from datetime import UTC, datetime
import frontmatter
articles = glob.glob("_drafts/*.md")
articles.sort()
titles = []
if len(articles) == 0:
print("No drafts found")
sys.exit(1)
for article in articles:
fm = frontmatter.load(article)
titles.append(fm.get("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 = frontmatter.load(article)
fm.metadata["date"] = frontmatter_date
with open(
article.replace("_drafts/", f"_posts/{file_date}-"),
mode="w",
encoding="utf8",
) as file:
file.write(frontmatter.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}")

View file

@ -1,61 +0,0 @@
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

View file

@ -1,105 +0,0 @@
@use "pygments_default";
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
@media screen and (min-width: 801px) {
body {
align-items: center;
}
}
html, body {
width: 100%;
height: 100%;
margin: auto;
}
body {
font-family: sans-serif;
max-width: 800px;
display: flex;
flex-direction: column;
}
h1 {
font-size: 1.3rem;
}
h2 {
font-size: 1.2rem;
}
h3 {
font-size: 1.1rem;
}
h4,h5,h6 {
font-size: 1rem;
}
main {
padding: 20px;
opacity: .8;
line-height: 1.5rem;
}
a {
text-decoration: none;
}
.site_header {
padding-top: 40px;
display: flex;
flex-direction: column;
align-items: center;
}
.panda {
width: 200px;
height: 200px;
border-radius: 100px;
}
.site_links {
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: 40px 0;
&__link {
display: block;
padding: 0 20px;
opacity: .8;
}
}
.site_footer {
padding: 40px 20px;
opacity: .3;
}
.articles {
opacity: .8;
padding-top: 40px;
}
.article {
&__back {
font-size: .9rem;
}
&__published {
font-style: italic;
font-size: .9rem;
opacity: .6;
}
}

59
_unpublish.py Normal file
View file

@ -0,0 +1,59 @@
import glob
import os
import sys
from datetime import datetime
import frontmatter
articles = glob.glob("_posts/*.md")
articles.sort(reverse=True)
titles = []
if len(articles) == 0:
print("No articles found")
sys.exit(1)
for article in articles:
fm = frontmatter.load(article)
titles.append(fm.get("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 = frontmatter.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(frontmatter.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}")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -1,3 +0,0 @@
---
---
@use "main";

View file

@ -1,20 +1,5 @@
services:
jekyll:
build:
context: .
dockerfile: Dockerfile.jekyll
platform: linux/amd64
ports:
- 4000:4000
- 35729:35729
volumes:
- .:/app
gemini:
build:
context: .
dockerfile: Dockerfile.gemini
platform: linux/amd64
build: .
volumes:
- .:/app

View file

@ -1,5 +1,7 @@
packaging==24.2
pyparsing==3.1.4
python-frontmatter==1.1.0
python-slugify==8.0.4
PyYAML==6.0.2
setuptools==70.3.0
text-unidecode==1.3