chore: slightly better markdown

This commit is contained in:
Dave Kerr
2025-03-10 08:42:48 +00:00
parent 8bac32a000
commit 67c135701f
6 changed files with 65 additions and 62 deletions

View File

@@ -1,24 +0,0 @@
https://mmistakes.github.io/so-simple-theme/
TODO
- heading link markdown anchor style
```
I'm going to paste two links. One is an index of blog posts, one is a specific blog post:
1. Index: https://mmistakes.github.io/so-simple-theme/
2. Specific: https://mmistakes.github.io/so-simple-theme/markup-syntax-highlighting/
We're going to take this and create a single page, with the markdown at the end of this message as the template. Requirements:
1. Simplify the top bar, sticky. Title is 'Hacker Laws', next button is 'Effective Shell [book icon]' then 'Sponsor [coffee icon]' then 'Terminal AI [brain icon]' then 'GitHub [github icon, this item right aligned]'
2. Use bootstrap and bootstrap icons so that we have a CSS starting point eg. for the grid
3. Use the social sharing icons below each 'law'
4. There is no need to link to any content pages - this is a single page
5. Below each law we need a 'back to top' button, choose 3-5 options so that I can pick the one I prefer, think about common patterns used to visually indicate 'go to top'
6. No need for disqus
7. Theme should be soft pastel colors, prefer a paper colored background perhaps very slightly yellow like parchment
8. No logo at the top, but Hacker Laws in slightly larger text with the subtitle
```

View File

@@ -0,0 +1 @@
*

View File

@@ -5,10 +5,22 @@ import shutil
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
# Read environment variables with defaults
TEMPLATE_FILE = os.getenv("TEMPLATE_FILE", "template.html") def bisect_text(content: str, bisect_line: str) -> tuple[str, str]:
MARKDOWN_FILE = os.getenv("MARKDOWN_FILE", "laws.md") lines = content.splitlines()
TEMPLATE_DIR = os.getenv("TEMPLATE_DIR", ".") # Directory where template is stored head = []
tail = []
found = False
for line in lines:
if found is False and line == bisect_line:
found = True
continue
if found:
tail.append(line)
else:
head.append(line)
return ("\n".join(head), "\n".join(tail))
def load_template(): def load_template():
@@ -17,12 +29,23 @@ def load_template():
return env.get_template(TEMPLATE_FILE) return env.get_template(TEMPLATE_FILE)
def parse_markdown(md_file): def prepare_markdown(path: str) -> str:
"""Parse a Markdown file and return structured law sections.""" """
with open(md_file, "r", encoding="utf-8") as f: Pre-process the README markdown by removing content we will not show in
md_content = f.read() the final website.
"""
sections = md_content.split("\n## ") # Split by Markdown headings # Load the markdown content.
with open(path, "r", encoding="utf-8") as f:
content = f.read()
return content
def parse_markdown(markdown_content: str):
(_, remains) = bisect_text(markdown_content, "<!-- vim-markdown-toc GFM -->")
(toc, content) = bisect_text(remains, "<!-- vim-markdown-toc -->")
sections = content.split("\n## ") # Split by Markdown headings
laws = [] laws = []
for section in sections: for section in sections:
if section.strip(): if section.strip():
@@ -32,11 +55,14 @@ def parse_markdown(md_file):
law_id = title.lower().replace(" ", "-") law_id = title.lower().replace(" ", "-")
laws.append({"title": title, "content": content, "id": law_id}) laws.append({"title": title, "content": content, "id": law_id})
return laws return (markdown.markdown(toc), laws)
def extract_static_files(html_content, output_dir): def extract_static_files(html_content, output_dir):
"""Extract linked CSS, JS, and image files and copy them to the output directory.""" """
Extract linked CSS, JS, and image files and copy them to the output
directory.
"""
soup = BeautifulSoup(html_content, "html.parser") soup = BeautifulSoup(html_content, "html.parser")
files_to_copy = [] files_to_copy = []
@@ -73,20 +99,17 @@ def extract_static_files(html_content, output_dir):
return files_to_copy return files_to_copy
def generate_site(output_dir): def generate_site(markdown_content: str, output_dir: str):
"""Generate the static HTML file from Markdown and Jinja2 template.""" """Generate the static HTML file from Markdown and Jinja2 template."""
print(f"📝 Loading template from: {TEMPLATE_DIR}/{TEMPLATE_FILE}")
print(f"📖 Loading markdown from: {MARKDOWN_FILE}")
print(f"💾 Outputting files to: {output_dir}")
template = load_template() template = load_template()
laws = parse_markdown(MARKDOWN_FILE) (toc, laws) = parse_markdown(markdown_content)
# Ensure output directory exists # Ensure output directory exists
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
# Render HTML # Render HTML
html_output = template.render(laws=laws) html_output = template.render(toc=toc, laws=laws)
# Save HTML to output directory # Save HTML to output directory
output_file = os.path.join(output_dir, "index.html") output_file = os.path.join(output_dir, "index.html")
@@ -104,4 +127,18 @@ if __name__ == "__main__":
parser.add_argument("-o", "--output-dir", default="build", help="Directory to save the generated site.") parser.add_argument("-o", "--output-dir", default="build", help="Directory to save the generated site.")
args = parser.parse_args() args = parser.parse_args()
generate_site(args.output_dir) # Read environment variables with defaults
TEMPLATE_FILE = os.getenv("TEMPLATE_FILE", "template.html")
TEMPLATE_DIR = os.getenv("TEMPLATE_DIR", ".")
template_path = f"{TEMPLATE_DIR}/{TEMPLATE_FILE}"
markdown_path = os.getenv("MARKDOWN_FILE", "laws.md")
output_dir = args.output_dir
print(f"📝 Loading template from: {template_path}")
print(f"📖 Loading markdown from: {markdown_path}")
print(f"💾 Outputting files to: {output_dir}")
# First, extract that markdown that we want to process.
markdown_content = prepare_markdown(markdown_path)
# Generate the site from the markdown.
generate_site(markdown_content, args.output_dir)

View File

@@ -29,7 +29,7 @@ serve: # 🚀 start local server
.PHONY: watch .PHONY: watch
watch: # 👀 Watch for changes... watch: # 👀 Watch for changes...
@echo "👀 Watching for changes..." @echo "👀 Watching for changes..."
watchmedo shell-command --patterns="$(MARKDOWN_FILE);*.py" --command="make build" . watchmedo shell-command --patterns="$(MARKDOWN_FILE);*.py;./src/*.*" --command="make build" .
.PHONY: clean .PHONY: clean
clean: #🧹 Clean up generated files clean: #🧹 Clean up generated files

View File

@@ -44,25 +44,10 @@
</header> </header>
<main class="container"> <main class="container">
<section id="introduction" class="law-section"> <!-- The table of contents. -->
<h2> {{ toc }}
Introduction
<a href="#introduction" class="anchor"><i class="bi bi-link-45deg"></i></a> <!-- Each of the laws. -->
</h2>
<p>There are lots of laws which people discuss when talking about development...</p>
<blockquote>“Any code of your own that you havent looked at for six or more months might as well have been written by someone else.” Eagleson's Law</blockquote>
<ul>
<li><a href="#">Law of Demeter</a></li>
<li><a href="#">Pareto Principle</a></li>
<li><a href="#">Hofstadter's Law</a></li>
</ul>
<div class="social-sharing">
<a href="#" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
<a href="#" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
<a href="#" title="Copy Link"><i class="bi bi-clipboard"></i></a>
</div>
<div class="back-to-top"><a href="#top">↑ Back to Top</a></div>
</section>
{% for law in laws %} {% for law in laws %}
<section id="{{ law.id }}" class="law-section"> <section id="{{ law.id }}" class="law-section">
<h2> <h2>

View File

@@ -31,6 +31,10 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Pages - name: Setup Pages
uses: actions/configure-pages@v5 uses: actions/configure-pages@v5
- name: Build Website
run: |
cd .github/website
make build
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@v3 uses: actions/upload-pages-artifact@v3
with: with: