fixing indentations and adding to gitignore

This commit is contained in:
Mike Eberlein 2026-05-10 19:07:08 -04:00
parent f41a059b8d
commit 5882be39d7
13 changed files with 171 additions and 47 deletions

14
.gitignore vendored
View File

@ -10,3 +10,17 @@
# Python
__pycache__/
*.pyc
# LibreOffice lock files (e.g. .~lock.MikeEberlein_Resume.docx#)
.~lock.*#
# Linux temp / editor files
*~
.*.swp
.*.swo
*.bak
*.tmp
.fuse_hidden*
.nfs*
.directory
.Trash-*

View File

@ -47,8 +47,8 @@ $(TEX): $(YAML) render_tex.py
python3 render_tex.py --level=short --output=$(TEX)
$(PDF): $(TEX)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX)
lualatex -interaction=nonstopmode -halt-on-error $(TEX)
lualatex -interaction=nonstopmode -halt-on-error $(TEX)
$(ODT): $(YAML) render_odt.py
python3 render_odt.py --level=short --output=$(ODT)
@ -61,8 +61,8 @@ $(TEX_D): $(YAML) render_tex.py
python3 render_tex.py --level=full --output=$(TEX_D)
$(PDF_D): $(TEX_D)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX_D)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX_D)
lualatex -interaction=nonstopmode -halt-on-error $(TEX_D)
lualatex -interaction=nonstopmode -halt-on-error $(TEX_D)
$(ODT_D): $(YAML) render_odt.py
python3 render_odt.py --level=full --output=$(ODT_D)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,18 +1,35 @@
% Mike Eberlein — single-page resume (generated from resume.yaml).
% Build: pdflatex MikeEberlein_Resume.tex (run twice for stable layout)
% Build: lualatex MikeEberlein_Resume.tex (run twice for stable layout)
% Do not edit by hand — re-run `python3 render_tex.py` after changing resume.yaml.
%
% Fonts: Roboto via the roboto LaTeX package (texlive-fonts-extra). The official
% Google Roboto font repo (with OFL license) is also bundled at ./fonts/ —
% individual weights live in ./fonts/static/, variable fonts at ./fonts/.
% Fonts: Roboto, loaded directly from ./fonts/static/ via fontspec. Requires
% lualatex (or xelatex). This makes the build self-contained — no dependency
% on TeX Live's bundled `roboto` package.
\documentclass[letterpaper,10pt]{extarticle}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[sfdefault]{roboto}
\usepackage{fontspec}
\setmainfont{Roboto}[
Path = fonts/static/,
Extension = .ttf,
UprightFont = *-Regular,
ItalicFont = *-Italic,
BoldFont = *-Bold,
BoldItalicFont = *-BoldItalic,
Ligatures = NoCommon, % keep fi/fl as two letters so PDF text search / ATS works
]
\newfontfamily\RobotoLight{Roboto}[
Path=fonts/static/, Extension=.ttf,
UprightFont=*-Light, ItalicFont=*-LightItalic,
Ligatures=NoCommon,
]
\newfontfamily\RobotoMedium{Roboto}[
Path=fonts/static/, Extension=.ttf,
UprightFont=*-Medium, BoldFont=*-Bold,
Ligatures=NoCommon,
]
\usepackage{microtype}
\DisableLigatures{encoding = *, family = *} % keep fi/fl as two letters so PDF text search / ATS works
\usepackage[letterpaper,margin=0.5in,top=0.35in,bottom=0.3in]{geometry}
\usepackage[dvipsnames]{xcolor}
\usepackage{titlesec}
@ -21,9 +38,6 @@
\usepackage{ragged2e}
\usepackage{parskip}
\newcommand{\RobotoLight}{\fontseries{l}\selectfont}
\newcommand{\RobotoMedium}{\fontseries{m}\selectfont}
\definecolor{accent}{HTML}{1F3864}
\definecolor{body}{HTML}{222222}
\definecolor{muted}{HTML}{555555}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,18 +1,35 @@
% Mike Eberlein — single-page resume (generated from resume.yaml).
% Build: pdflatex MikeEberlein_Resume.tex (run twice for stable layout)
% Build: lualatex MikeEberlein_Resume.tex (run twice for stable layout)
% Do not edit by hand — re-run `python3 render_tex.py` after changing resume.yaml.
%
% Fonts: Roboto via the roboto LaTeX package (texlive-fonts-extra). The official
% Google Roboto font repo (with OFL license) is also bundled at ./fonts/ —
% individual weights live in ./fonts/static/, variable fonts at ./fonts/.
% Fonts: Roboto, loaded directly from ./fonts/static/ via fontspec. Requires
% lualatex (or xelatex). This makes the build self-contained — no dependency
% on TeX Live's bundled `roboto` package.
\documentclass[letterpaper,10pt]{extarticle}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[sfdefault]{roboto}
\usepackage{fontspec}
\setmainfont{Roboto}[
Path = fonts/static/,
Extension = .ttf,
UprightFont = *-Regular,
ItalicFont = *-Italic,
BoldFont = *-Bold,
BoldItalicFont = *-BoldItalic,
Ligatures = NoCommon, % keep fi/fl as two letters so PDF text search / ATS works
]
\newfontfamily\RobotoLight{Roboto}[
Path=fonts/static/, Extension=.ttf,
UprightFont=*-Light, ItalicFont=*-LightItalic,
Ligatures=NoCommon,
]
\newfontfamily\RobotoMedium{Roboto}[
Path=fonts/static/, Extension=.ttf,
UprightFont=*-Medium, BoldFont=*-Bold,
Ligatures=NoCommon,
]
\usepackage{microtype}
\DisableLigatures{encoding = *, family = *} % keep fi/fl as two letters so PDF text search / ATS works
\usepackage[letterpaper,margin=0.5in,top=0.35in,bottom=0.3in]{geometry}
\usepackage[dvipsnames]{xcolor}
\usepackage{titlesec}
@ -21,9 +38,6 @@
\usepackage{ragged2e}
\usepackage{parskip}
\newcommand{\RobotoLight}{\fontseries{l}\selectfont}
\newcommand{\RobotoMedium}{\fontseries{m}\selectfont}
\definecolor{accent}{HTML}{1F3864}
\definecolor{body}{HTML}{222222}
\definecolor{muted}{HTML}{555555}

View File

@ -21,7 +21,7 @@ Two flavors are produced from the same YAML:
| `MikeEberlein_Resume.odt` | Built from YAML via `render_odt.py`. |
| `MikeEberlein_Resume.docx` | Built from `.odt` via LibreOffice. |
| `Makefile` | Build orchestration. |
| `fonts/` | Official Google Roboto font repo. Variable fonts at the top level; individual weights under `fonts/static/`. License in `fonts/OFL.txt`. |
| `fonts/` | Official Google Roboto font repo. Variable fonts at the top level; individual weights under `fonts/static/`. License in `fonts/OFL.txt`. **Used by both build paths**: lualatex loads from `fonts/static/`; the ODT renderer embeds these `.ttf` files inside the ODT zip. |
## Build
@ -46,11 +46,13 @@ python3 render_odt.py --level=short --output=foo.odt
Required system packages (Debian/Ubuntu):
```bash
sudo apt install texlive-latex-recommended texlive-latex-extra texlive-fonts-extra
sudo apt install texlive-latex-recommended texlive-latex-extra texlive-luatex
sudo apt install libreoffice # for the .docx output
sudo apt install python3-yaml # for the renderers (usually pre-installed)
```
The PDF build uses **lualatex** with `fontspec`, loading Roboto directly from `fonts/static/`. No dependency on TeX Live's `roboto` package or any system-installed Roboto. The ODT/DOCX outputs embed the Roboto faces inside the document zip, so the resume looks correct even on a machine with no Roboto installed.
## Editing
Open `resume.yaml`. The schema:

View File

@ -26,12 +26,32 @@ DEFAULT_OUT = {
MIMETYPE = "application/vnd.oasis.opendocument.text"
MANIFEST = '''<?xml version="1.0" encoding="UTF-8"?>
# Roboto faces to embed in the zip, sourced from fonts/static/.
# Each tuple: (filename in Fonts/, weight attr, style attr).
EMBEDDED_FONTS = [
("Roboto-Regular.ttf", "normal", "normal"),
("Roboto-Italic.ttf", "normal", "italic"),
("Roboto-Bold.ttf", "bold", "normal"),
("Roboto-BoldItalic.ttf", "bold", "italic"),
("Roboto-Light.ttf", "300", "normal"),
("Roboto-LightItalic.ttf", "300", "italic"),
("Roboto-Medium.ttf", "500", "normal"),
]
FONTS_SRC_DIR = os.path.join(HERE, "fonts", "static")
def _font_manifest_entries():
rows = []
for name, _w, _s in EMBEDDED_FONTS:
rows.append(f' <manifest:file-entry manifest:full-path="Fonts/{name}" manifest:media-type="application/x-font-ttf"/>')
return "\n".join(rows)
MANIFEST = f'''<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.3">
<manifest:file-entry manifest:full-path="/" manifest:version="1.3" manifest:media-type="application/vnd.oasis.opendocument.text"/>
<manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>
<manifest:file-entry manifest:full-path="styles.xml" manifest:media-type="text/xml"/>
<manifest:file-entry manifest:full-path="meta.xml" manifest:media-type="text/xml"/>
{_font_manifest_entries()}
</manifest:manifest>
'''
@ -41,19 +61,50 @@ META = '''<?xml version="1.0" encoding="UTF-8"?>
</office:document-meta>
'''
STYLES = '''<?xml version="1.0" encoding="UTF-8"?>
def _font_face_uris(filter_family):
"""Emit <svg:font-face-uri> children for one logical family ('roboto' | 'light')."""
rows = []
for name, weight, style in EMBEDDED_FONTS:
# The 'Roboto Light' family only carries the Light faces; the main
# 'Roboto' family carries everything else (including Medium).
is_light = name.startswith("Roboto-Light")
if filter_family == "light" and not is_light:
continue
if filter_family == "roboto" and is_light:
continue
rows.append(
f' <svg:font-face-uri xlink:href="Fonts/{name}" xlink:type="simple" '
f'loext:font-style="{style}" loext:font-weight="{weight}">'
f'<svg:font-face-format svg:string="application/x-font-ttf"/>'
f'</svg:font-face-uri>'
)
return "\n".join(rows)
FONT_FACE_DECLS = f'''<office:font-face-decls>
<style:font-face style:name="Roboto" svg:font-family="Roboto" style:font-family-generic="swiss" style:font-pitch="variable">
<svg:font-face-src>
{_font_face_uris("roboto")}
</svg:font-face-src>
</style:font-face>
<style:font-face style:name="Roboto Light" svg:font-family="&apos;Roboto Light&apos;" style:font-family-generic="swiss" style:font-pitch="variable">
<svg:font-face-src>
{_font_face_uris("light")}
</svg:font-face-src>
</style:font-face>
</office:font-face-decls>'''
STYLES = f'''<?xml version="1.0" encoding="UTF-8"?>
<office:document-styles
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
office:version="1.3">
<office:font-face-decls>
<style:font-face style:name="Roboto" svg:font-family="Roboto"/>
<style:font-face style:name="Roboto Light" svg:font-family="&apos;Roboto Light&apos;"/>
</office:font-face-decls>
{FONT_FACE_DECLS}
<office:styles>
<style:default-style style:family="paragraph">
<style:paragraph-properties fo:hyphenate="false"/>
@ -94,7 +145,7 @@ STYLES = '''<?xml version="1.0" encoding="UTF-8"?>
<style:style style:name="Bullet" style:family="paragraph" style:parent-style-name="Standard" style:list-style-name="L1">
<style:paragraph-properties fo:margin-left="0.18in" fo:text-indent="-0.13in"/>
</style:style>
<style:style style:name="SubBullet" style:family="paragraph" style:parent-style-name="Standard" style:list-style-name="L1">
<style:style style:name="SubBullet" style:family="paragraph" style:parent-style-name="Standard" style:list-style-name="L2">
<style:paragraph-properties fo:margin-left="0.4in" fo:text-indent="-0.13in"/>
<style:text-properties fo:font-size="9pt" fo:color="#555555"/>
</style:style>
@ -108,6 +159,13 @@ STYLES = '''<?xml version="1.0" encoding="UTF-8"?>
</style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
<text:list-style style:name="L2">
<text:list-level-style-bullet text:level="1" text:bullet-char="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4in" fo:text-indent="-0.13in" fo:margin-left="0.4in"/>
</style:list-level-properties>
</text:list-level-style-bullet>
</text:list-style>
</office:styles>
<office:automatic-styles>
<style:page-layout style:name="PL1">
@ -170,7 +228,8 @@ def i(text):
TAB = '<text:tab/>'
def bullet(text, style="Bullet"):
return (f'<text:list text:style-name="L1"><text:list-item>'
list_style = "L2" if style == "SubBullet" else "L1"
return (f'<text:list text:style-name="{list_style}"><text:list-item>'
f'<text:p text:style-name="{style}">{xesc(text)}</text:p>'
f'</text:list-item></text:list>')
@ -235,6 +294,13 @@ def main():
z.writestr("meta.xml", META)
z.writestr("styles.xml", STYLES)
z.writestr("content.xml", content)
# Embed the Roboto faces inside the document for portability.
for name, _w, _s in EMBEDDED_FONTS:
src = os.path.join(FONTS_SRC_DIR, name)
if not os.path.exists(src):
raise SystemExit(f"font missing: {src}")
with open(src, "rb") as f:
z.writestr(f"Fonts/{name}", f.read())
print(f"wrote {out_path} (level={args.level})")
if __name__ == "__main__":

View File

@ -21,20 +21,37 @@ DEFAULT_OUT = {
}
PREAMBLE = r"""% Mike Eberlein — single-page resume (generated from resume.yaml).
% Build: pdflatex MikeEberlein_Resume.tex (run twice for stable layout)
% Build: lualatex MikeEberlein_Resume.tex (run twice for stable layout)
% Do not edit by hand re-run `python3 render_tex.py` after changing resume.yaml.
%
% Fonts: Roboto via the roboto LaTeX package (texlive-fonts-extra). The official
% Google Roboto font repo (with OFL license) is also bundled at ./fonts/
% individual weights live in ./fonts/static/, variable fonts at ./fonts/.
% Fonts: Roboto, loaded directly from ./fonts/static/ via fontspec. Requires
% lualatex (or xelatex). This makes the build self-contained no dependency
% on TeX Live's bundled `roboto` package.
\documentclass[letterpaper,10pt]{extarticle}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[sfdefault]{roboto}
\usepackage{fontspec}
\setmainfont{Roboto}[
Path = fonts/static/,
Extension = .ttf,
UprightFont = *-Regular,
ItalicFont = *-Italic,
BoldFont = *-Bold,
BoldItalicFont = *-BoldItalic,
Ligatures = NoCommon, % keep fi/fl as two letters so PDF text search / ATS works
]
\newfontfamily\RobotoLight{Roboto}[
Path=fonts/static/, Extension=.ttf,
UprightFont=*-Light, ItalicFont=*-LightItalic,
Ligatures=NoCommon,
]
\newfontfamily\RobotoMedium{Roboto}[
Path=fonts/static/, Extension=.ttf,
UprightFont=*-Medium, BoldFont=*-Bold,
Ligatures=NoCommon,
]
\usepackage{microtype}
\DisableLigatures{encoding = *, family = *} % keep fi/fl as two letters so PDF text search / ATS works
\usepackage[letterpaper,margin=0.5in,top=0.35in,bottom=0.3in]{geometry}
\usepackage[dvipsnames]{xcolor}
\usepackage{titlesec}
@ -43,9 +60,6 @@ PREAMBLE = r"""% Mike Eberlein — single-page resume (generated from resume.yam
\usepackage{ragged2e}
\usepackage{parskip}
\newcommand{\RobotoLight}{\fontseries{l}\selectfont}
\newcommand{\RobotoMedium}{\fontseries{m}\selectfont}
\definecolor{accent}{HTML}{1F3864}
\definecolor{body}{HTML}{222222}
\definecolor{muted}{HTML}{555555}