From 67c135701fc5ed64f5f4113bbeca5c718a3922d8 Mon Sep 17 00:00:00 2001 From: Dave Kerr Date: Mon, 10 Mar 2025 08:42:48 +0000 Subject: [PATCH] chore: slightly better markdown --- .github/pages/ideas.md | 24 --------- .github/website/build/.gitignore | 1 + .github/website/generate.py | 73 +++++++++++++++++++++------- .github/website/makefile | 2 +- .github/website/src/index.html.jinja | 23 ++------- .github/workflows/pages.yaml | 4 ++ 6 files changed, 65 insertions(+), 62 deletions(-) delete mode 100644 .github/pages/ideas.md diff --git a/.github/pages/ideas.md b/.github/pages/ideas.md deleted file mode 100644 index d4465de..0000000 --- a/.github/pages/ideas.md +++ /dev/null @@ -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 -``` diff --git a/.github/website/build/.gitignore b/.github/website/build/.gitignore index e69de29..72e8ffc 100644 --- a/.github/website/build/.gitignore +++ b/.github/website/build/.gitignore @@ -0,0 +1 @@ +* diff --git a/.github/website/generate.py b/.github/website/generate.py index af8d369..d332812 100644 --- a/.github/website/generate.py +++ b/.github/website/generate.py @@ -5,10 +5,22 @@ import shutil from jinja2 import Environment, FileSystemLoader from bs4 import BeautifulSoup -# Read environment variables with defaults -TEMPLATE_FILE = os.getenv("TEMPLATE_FILE", "template.html") -MARKDOWN_FILE = os.getenv("MARKDOWN_FILE", "laws.md") -TEMPLATE_DIR = os.getenv("TEMPLATE_DIR", ".") # Directory where template is stored + +def bisect_text(content: str, bisect_line: str) -> tuple[str, str]: + lines = content.splitlines() + 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(): @@ -17,12 +29,23 @@ def load_template(): return env.get_template(TEMPLATE_FILE) -def parse_markdown(md_file): - """Parse a Markdown file and return structured law sections.""" - with open(md_file, "r", encoding="utf-8") as f: - md_content = f.read() +def prepare_markdown(path: str) -> str: + """ + Pre-process the README markdown by removing content we will not show in + 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, "") + (toc, content) = bisect_text(remains, "") + + sections = content.split("\n## ") # Split by Markdown headings laws = [] for section in sections: if section.strip(): @@ -32,11 +55,14 @@ def parse_markdown(md_file): law_id = title.lower().replace(" ", "-") laws.append({"title": title, "content": content, "id": law_id}) - return laws + return (markdown.markdown(toc), laws) 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") files_to_copy = [] @@ -73,20 +99,17 @@ def extract_static_files(html_content, output_dir): 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.""" - 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() - laws = parse_markdown(MARKDOWN_FILE) + (toc, laws) = parse_markdown(markdown_content) # Ensure output directory exists os.makedirs(output_dir, exist_ok=True) # Render HTML - html_output = template.render(laws=laws) + html_output = template.render(toc=toc, laws=laws) # Save HTML to output directory 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.") 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) diff --git a/.github/website/makefile b/.github/website/makefile index 2a4fe68..305b7df 100644 --- a/.github/website/makefile +++ b/.github/website/makefile @@ -29,7 +29,7 @@ serve: # πŸš€ start local server .PHONY: watch watch: # πŸ‘€ Watch 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 clean: #🧹 Clean up generated files diff --git a/.github/website/src/index.html.jinja b/.github/website/src/index.html.jinja index fc04c3d..2f39638 100644 --- a/.github/website/src/index.html.jinja +++ b/.github/website/src/index.html.jinja @@ -44,25 +44,10 @@
-
-

- Introduction - -

-

There are lots of laws which people discuss when talking about development...

-
β€œAny code of your own that you haven’t looked at for six or more months might as well have been written by someone else.” – Eagleson's Law
- - - -
+ + {{ toc }} + + {% for law in laws %}

diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml index 6b45df9..be727ca 100644 --- a/.github/workflows/pages.yaml +++ b/.github/workflows/pages.yaml @@ -31,6 +31,10 @@ jobs: uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v5 + - name: Build Website + run: | + cd .github/website + make build - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: