Creates a new Makefile target that converts all RST blog posts to plain text format using pandoc, enabling use of blog content as training data for machine learning applications.
209 lines
10 KiB
Makefile
209 lines
10 KiB
Makefile
.PHONY: html help clean regenerate serve devserver publish pygments jsonresume jsonresume-themes jsonresume-pdf rst2md llms jsonfeed jsonblog plaintext formats training-data
|
|
|
|
BASEDIR=$(CURDIR)
|
|
INPUTDIR=$(BASEDIR)/content
|
|
OUTPUTDIR=$(BASEDIR)/output
|
|
CONFFILE=$(BASEDIR)/pelicanconf.py
|
|
PUBLISHCONF=$(BASEDIR)/publishconf.py
|
|
|
|
help:
|
|
@echo 'Makefile for a pelican Web site '
|
|
@echo ' '
|
|
@echo 'Usage: '
|
|
@echo ' make venv setup virtual environment '
|
|
@echo ' make resume (re)generate the resume PDF '
|
|
@echo ' make jsonresume copy JSONResume to output '
|
|
@echo ' make jsonresume-themes install 30 jsonresume themes '
|
|
@echo ' make jsonresume-pdf generate PDFs for favorite themes '
|
|
@echo ' make cover-letters (re)generate cover letter PDFs '
|
|
@echo ' make html (re)generate the web site '
|
|
@echo ' make clean remove the generated files '
|
|
@echo ' make regenerate regenerate files upon modification '
|
|
@echo ' make publish generate using production settings '
|
|
@echo ' make serve serve site at http://localhost:8000'
|
|
@echo ' make devserver serve and regenerate together '
|
|
@echo ' make pygments generate pygments stylesheets '
|
|
@echo ' make rst2md convert RST to MD in output '
|
|
@echo ' make llms generate llms.txt for AI agents '
|
|
@echo ' make jsonfeed generate JSON Feed (/feeds/all.json)'
|
|
@echo ' make jsonblog generate JSON Blog (/blog.json) '
|
|
@echo ' make plaintext generate plain text (index.txt) '
|
|
@echo ' make formats generate all agent-friendly formats'
|
|
@echo ' '
|
|
|
|
THEME_REPO_URL ?= git@github.com:russellballestrini/pelican-svbhack.git
|
|
|
|
venv:
|
|
python3 -m venv venv
|
|
venv/bin/pip install -r requirements.txt
|
|
mkdir -p pelican-themes
|
|
cd pelican-themes && git clone $(THEME_REPO_URL)
|
|
venv/bin/pelican-themes -i pelican-themes/pelican-svbhack/
|
|
|
|
resume: jsonresume
|
|
venv/bin/rst2pdf content/pages/russell.ballestrini.resume.rst --stylesheets content/pages/russell.ballestrini.resume.style -o output/uploads/russell.ballestrini.resume.pdf
|
|
@echo "Creating softlinks for various job titles..."
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf founder.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf founding.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf software.developer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf software.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf senior.software.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf staff.software.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf principal.software.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf full.stack.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf site.reliability.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf sre.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf devops.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf backend.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf platform.engineer.russell.ballestrini.resume.pdf
|
|
@cd output/uploads && ln -sf russell.ballestrini.resume.pdf infrastructure.engineer.russell.ballestrini.resume.pdf
|
|
@echo "Resume softlinks created!"
|
|
|
|
jsonresume:
|
|
@mkdir -p output/uploads
|
|
cp content/pages/russell.ballestrini.resume.json output/uploads/russell.ballestrini.resume.json
|
|
cp content/pages/unturf.resume.json output/uploads/unturf.resume.json
|
|
@echo "JSONResume files copied to output/uploads/"
|
|
|
|
# JSONResume themes - 30 tested working themes
|
|
JSONRESUME_THEMES = classy cora dark-classy-responsive elegant eloquent even kards kendall \
|
|
light-classy-responsive lucide modern modern-extended modern-plain msresume nameme one \
|
|
onepage-plus printclassy projects rnord rocketspacer sceptile simplyelegant stackoverflow \
|
|
stackoverflow-ru straightforward tan-responsive techlead timeline-fixed waterfall
|
|
|
|
RESUME_FILE ?= content/pages/russell.ballestrini.resume.json
|
|
|
|
jsonresume-themes:
|
|
@echo "Installing 30 jsonresume themes..."
|
|
npm install $(addprefix jsonresume-theme-,$(JSONRESUME_THEMES)) puppeteer --legacy-peer-deps
|
|
@echo "Done! Run: make jsonresume-pdf"
|
|
|
|
# Export JSONResume as HTML in all themes
|
|
jsonresume-all-html:
|
|
@mkdir -p output/uploads/jsonresume-themes
|
|
@echo "Generating HTML for all themes..."
|
|
@for theme in $(JSONRESUME_THEMES); do \
|
|
echo " Generating $$theme..."; \
|
|
node -e "try { \
|
|
const t = require('jsonresume-theme-$$theme'); \
|
|
const r = require('./$(RESUME_FILE)'); \
|
|
require('fs').writeFileSync('output/uploads/jsonresume-themes/russell.ballestrini.$$theme.html', t.render(r)); \
|
|
console.log(' OK'); \
|
|
} catch(e) { console.log(' Failed:', e.message.split('\n')[0]); }" 2>/dev/null || echo " Failed: $$theme"; \
|
|
done
|
|
@echo "HTML files saved to output/uploads/jsonresume-themes/"
|
|
@echo "Open in browser & print to PDF"
|
|
|
|
# Favorite JSONResume themes for PDF export
|
|
JSONRESUME_PDF_THEMES = kendall modern-plain one onepage-plus
|
|
|
|
# Generate PDFs for favorite themes using puppeteer
|
|
jsonresume-pdf: jsonresume-all-html
|
|
@mkdir -p output/uploads
|
|
@echo "Generating PDFs for favorite themes..."
|
|
@node -e " \
|
|
const puppeteer = require('puppeteer'); \
|
|
const themes = '$(JSONRESUME_PDF_THEMES)'.split(' '); \
|
|
(async () => { \
|
|
const browser = await puppeteer.launch({headless: 'new'}); \
|
|
for (const theme of themes) { \
|
|
const page = await browser.newPage(); \
|
|
await page.goto('file://$(CURDIR)/output/uploads/jsonresume-themes/russell.ballestrini.' + theme + '.html', {waitUntil: 'networkidle0'}); \
|
|
await page.pdf({path: '$(CURDIR)/output/uploads/russell.ballestrini.' + theme + '.pdf', format: 'A4'}); \
|
|
console.log(' Created: russell.ballestrini.' + theme + '.pdf'); \
|
|
await page.close(); \
|
|
} \
|
|
await browser.close(); \
|
|
})(); \
|
|
"
|
|
@echo "PDFs saved to output/uploads/"
|
|
|
|
cover-letter:
|
|
@if [ -z "$(FILE)" ]; then \
|
|
echo "Usage: make cover-letter FILE=filename-without-extension"; \
|
|
echo "Example: make cover-letter FILE=2025-11-29-runpod-principal-software-engineer-storage-systems-russell-ballestrini"; \
|
|
exit 1; \
|
|
fi
|
|
@mkdir -p output/uploads/cover-letters
|
|
@echo "Generating PDF for $(FILE)..."
|
|
@venv/bin/rst2pdf content/pages/cover-letters/$(FILE).rst --stylesheets content/pages/cover-letters/cover-letter.style -o output/uploads/cover-letters/$(FILE).pdf
|
|
@echo "PDF generated: output/uploads/cover-letters/$(FILE).pdf"
|
|
|
|
cover-letters:
|
|
@mkdir -p output/uploads/cover-letters
|
|
@for letter in content/pages/cover-letters/*.rst; do \
|
|
basename=$$(basename $$letter .rst); \
|
|
echo "Generating PDF for $$basename..."; \
|
|
venv/bin/rst2pdf $$letter --stylesheets content/pages/cover-letters/cover-letter.style -o output/uploads/cover-letters/$$basename.pdf; \
|
|
done
|
|
@echo "All cover letters generated in output/uploads/cover-letters/"
|
|
|
|
html: pygments
|
|
venv/bin/pelican content -o output -s pelicanconf.py
|
|
|
|
clean:
|
|
[ ! -d output ] || rm -rf output
|
|
|
|
regenerate:
|
|
venv/bin/pelican -r content -o output -s pelicanconf.py
|
|
|
|
serve:
|
|
venv/bin/pelican -l content -o output -s pelicanconf.py
|
|
|
|
devserver:
|
|
venv/bin/pelican -lr content -o output -s pelicanconf.py
|
|
|
|
publish:
|
|
venv/bin/pelican content -o output -s publishconf.py
|
|
|
|
pygments:
|
|
@echo "Generating pygments stylesheets..."
|
|
venv/bin/python -c "from pygments.formatters import HtmlFormatter; print(HtmlFormatter(style='monokai').get_style_defs('.highlight'))" > pelican-themes/pelican-svbhack/static/css/pygments-dark.css
|
|
venv/bin/python -c "from pygments.formatters import HtmlFormatter; print(HtmlFormatter(style='default').get_style_defs('.highlight'))" > pelican-themes/pelican-svbhack/static/css/pygments-light.css
|
|
@echo "Patching to remove hardcoded backgrounds..."
|
|
sed -i 's/.highlight { background: #272822; color: #f8f8f2 }/.highlight { color: #f8f8f2 }/' pelican-themes/pelican-svbhack/static/css/pygments-dark.css
|
|
sed -i 's/.highlight { background: #f8f8f8; }/.highlight { }/' pelican-themes/pelican-svbhack/static/css/pygments-light.css
|
|
@echo "Done! Pygments stylesheets generated and patched."
|
|
|
|
rst2md:
|
|
@echo "Converting RST to Markdown in output directory..."
|
|
venv/bin/python lib/rst2md.py $(OUTPUTDIR)
|
|
@echo "Done! Markdown files generated alongside RST sources."
|
|
|
|
llms:
|
|
@echo "Generating llms.txt for AI agents..."
|
|
venv/bin/python lib/generate_llms_txt.py $(OUTPUTDIR) $(SITEURL)
|
|
@echo "Done! llms.txt generated in output directory."
|
|
|
|
jsonfeed:
|
|
@echo "Generating JSON Feed..."
|
|
venv/bin/python lib/generate_jsonfeed.py $(OUTPUTDIR) $(SITEURL)
|
|
@echo "Done! JSON Feed generated at /feeds/all.json"
|
|
|
|
jsonblog:
|
|
@echo "Generating JSON Blog..."
|
|
venv/bin/python lib/generate_jsonblog.py $(OUTPUTDIR) $(SITEURL)
|
|
@echo "Done! JSON Blog generated at /blog.json"
|
|
|
|
plaintext:
|
|
@echo "Generating plain text versions..."
|
|
venv/bin/python lib/generate_plaintext.py $(OUTPUTDIR)
|
|
@echo "Done! Plain text files generated (index.txt)."
|
|
|
|
formats: rst2md plaintext jsonfeed jsonblog llms
|
|
@echo "All agent-friendly formats generated!"
|
|
|
|
TRAINING_DATA_OUT ?= $(BASEDIR)/russell.ballestrini.net.txt
|
|
|
|
training-data: ## Convert all RST posts to plain text for ML training
|
|
@echo "converting $(words $(wildcard $(INPUTDIR)/*.rst)) RST posts to plain text via pandoc..."
|
|
@> $(TRAINING_DATA_OUT)
|
|
@count=0; \
|
|
for rst in $(INPUTDIR)/*.rst; do \
|
|
pandoc -f rst -t plain --wrap=none "$$rst" >> $(TRAINING_DATA_OUT) 2>/dev/null; \
|
|
echo "" >> $(TRAINING_DATA_OUT); \
|
|
count=$$((count + 1)); \
|
|
done; \
|
|
echo "russell.ballestrini.net: $$count posts, $$(wc -l < $(TRAINING_DATA_OUT)) lines"
|
|
|
|
SITEURL ?= https://russell.ballestrini.net
|