diff --git a/.gitignore b/.gitignore index 5fb49ab..79dbf74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,2 @@ -.sass-cache -.jekyll-cache -.jekyll-metadata -vendor -_site +.venv _capsule diff --git a/Dockerfile.gemini b/Dockerfile similarity index 52% rename from Dockerfile.gemini rename to Dockerfile index 426d8c4..a66f14b 100644 --- a/Dockerfile.gemini +++ b/Dockerfile @@ -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" ] diff --git a/Dockerfile.jekyll b/Dockerfile.jekyll deleted file mode 100644 index 1ffcae4..0000000 --- a/Dockerfile.jekyll +++ /dev/null @@ -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" ] diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 3cc3941..0000000 --- a/Gemfile +++ /dev/null @@ -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 diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 1183025..0000000 --- a/Gemfile.lock +++ /dev/null @@ -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 diff --git a/Makefile b/Makefile index 5693257..3d96269 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/_config.yml b/_config.yml deleted file mode 100644 index fe06aa8..0000000 --- a/_config.yml +++ /dev/null @@ -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 diff --git a/_draft.py b/_draft.py new file mode 100644 index 0000000..d0cb4c8 --- /dev/null +++ b/_draft.py @@ -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) diff --git a/_drafts/live-long-and-prosper-with-these-tools.md b/_drafts/live-long-and-prosper-with-these-tools.md index 1360e09..79acca6 100644 --- a/_drafts/live-long-and-prosper-with-these-tools.md +++ b/_drafts/live-long-and-prosper-with-these-tools.md @@ -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️⃣,🌐) \ No newline at end of file diff --git a/generate_capsule.py b/_generate.py similarity index 89% rename from generate_capsule.py rename to _generate.py index 3a20158..b6a5f88 100644 --- a/generate_capsule.py +++ b/_generate.py @@ -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 diff --git a/_includes/footer.html b/_includes/footer.html deleted file mode 100644 index 1983435..0000000 --- a/_includes/footer.html +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/_includes/head.html b/_includes/head.html deleted file mode 100644 index 38ed18d..0000000 --- a/_includes/head.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - {{ site.title }} - diff --git a/_includes/header.html b/_includes/header.html deleted file mode 100644 index 09d4bbf..0000000 --- a/_includes/header.html +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/_layouts/article.gmi b/_layouts/article.gmi index 85e7f08..79cf1f8 100644 --- a/_layouts/article.gmi +++ b/_layouts/article.gmi @@ -1,5 +1,6 @@ %%header%% -=> index.gmi Front page +=> / Front page + ## %%title%% %%body%% %%links%% diff --git a/_layouts/article.html b/_layouts/article.html deleted file mode 100644 index ab0296a..0000000 --- a/_layouts/article.html +++ /dev/null @@ -1,14 +0,0 @@ ---- -layout: default ---- -
-

- {{ page.title | escape }} -

- -
- {{ content }} -
-
diff --git a/_layouts/default.html b/_layouts/default.html deleted file mode 100644 index e3d9223..0000000 --- a/_layouts/default.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - {%- include head.html -%} - - - {%- include header.html -%} - -
- {{ content }} -
- - {%- include footer.html -%} - - diff --git a/_layouts/home.html b/_layouts/home.html deleted file mode 100644 index b4c2d6b..0000000 --- a/_layouts/home.html +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: default ---- -
- {{ content }} - - {%- if site.posts.size > 0 -%} -
-

Articles

- -
- {%- endif -%} -
diff --git a/_posts/2024-12-22-regenerating-my-blog-a-fresh-start.md b/_posts/2024-12-22-regenerating-my-blog-a-fresh-start.md index 72e7ad1..1f69659 100644 --- a/_posts/2024-12-22-regenerating-my-blog-a-fresh-start.md +++ b/_posts/2024-12-22-regenerating-my-blog-a-fresh-start.md @@ -1,5 +1,4 @@ --- -layout: article title: 'Regenerating My Blog: A Fresh Start' date: 2024-12-22 00:45 +0000 --- diff --git a/_posts/2024-12-29-energy-shields-at-minimum-automating-laptop-power-mode.md b/_posts/2024-12-29-energy-shields-at-minimum-automating-laptop-power-mode.md index 0fc4b93..f9f4e67 100644 --- a/_posts/2024-12-29-energy-shields-at-minimum-automating-laptop-power-mode.md +++ b/_posts/2024-12-29-energy-shields-at-minimum-automating-laptop-power-mode.md @@ -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. diff --git a/_publish.py b/_publish.py new file mode 100644 index 0000000..d10256c --- /dev/null +++ b/_publish.py @@ -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}") diff --git a/_sass/_pygments_default.scss b/_sass/_pygments_default.scss deleted file mode 100644 index 8070f2f..0000000 --- a/_sass/_pygments_default.scss +++ /dev/null @@ -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 */ diff --git a/_sass/main.scss b/_sass/main.scss deleted file mode 100644 index 42d803a..0000000 --- a/_sass/main.scss +++ /dev/null @@ -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; - } -} diff --git a/_unpublish.py b/_unpublish.py new file mode 100644 index 0000000..8c75ce6 --- /dev/null +++ b/_unpublish.py @@ -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}") diff --git a/assets/panda.webp b/assets/panda.webp deleted file mode 100644 index ca5b8c7..0000000 Binary files a/assets/panda.webp and /dev/null differ diff --git a/assets/styles.scss b/assets/styles.scss deleted file mode 100644 index af0e868..0000000 --- a/assets/styles.scss +++ /dev/null @@ -1,3 +0,0 @@ ---- ---- -@use "main"; \ No newline at end of file diff --git a/compose.yaml b/compose.yaml index 8261a42..a9a099a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -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 diff --git a/requirements.txt b/requirements.txt index f0499e4..616e1af 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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