simple-resume 0.1.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simple_resume/__init__.py +132 -0
- simple_resume/core/__init__.py +47 -0
- simple_resume/core/colors.py +215 -0
- simple_resume/core/config.py +672 -0
- simple_resume/core/constants/__init__.py +207 -0
- simple_resume/core/constants/colors.py +98 -0
- simple_resume/core/constants/files.py +28 -0
- simple_resume/core/constants/layout.py +58 -0
- simple_resume/core/dependencies.py +258 -0
- simple_resume/core/effects.py +154 -0
- simple_resume/core/exceptions.py +261 -0
- simple_resume/core/file_operations.py +68 -0
- simple_resume/core/generate/__init__.py +21 -0
- simple_resume/core/generate/exceptions.py +69 -0
- simple_resume/core/generate/html.py +233 -0
- simple_resume/core/generate/pdf.py +659 -0
- simple_resume/core/generate/plan.py +131 -0
- simple_resume/core/hydration.py +55 -0
- simple_resume/core/importers/__init__.py +3 -0
- simple_resume/core/importers/json_resume.py +284 -0
- simple_resume/core/latex/__init__.py +60 -0
- simple_resume/core/latex/context.py +56 -0
- simple_resume/core/latex/conversion.py +227 -0
- simple_resume/core/latex/escaping.py +68 -0
- simple_resume/core/latex/fonts.py +93 -0
- simple_resume/core/latex/formatting.py +81 -0
- simple_resume/core/latex/sections.py +218 -0
- simple_resume/core/latex/types.py +84 -0
- simple_resume/core/markdown.py +127 -0
- simple_resume/core/models.py +102 -0
- simple_resume/core/palettes/__init__.py +38 -0
- simple_resume/core/palettes/common.py +73 -0
- simple_resume/core/palettes/data/default_palettes.json +58 -0
- simple_resume/core/palettes/exceptions.py +33 -0
- simple_resume/core/palettes/fetch_types.py +52 -0
- simple_resume/core/palettes/generators.py +137 -0
- simple_resume/core/palettes/registry.py +76 -0
- simple_resume/core/palettes/resolution.py +123 -0
- simple_resume/core/palettes/sources.py +162 -0
- simple_resume/core/paths.py +21 -0
- simple_resume/core/protocols.py +134 -0
- simple_resume/core/py.typed +0 -0
- simple_resume/core/render/__init__.py +37 -0
- simple_resume/core/render/manage.py +199 -0
- simple_resume/core/render/plan.py +405 -0
- simple_resume/core/result.py +226 -0
- simple_resume/core/resume.py +609 -0
- simple_resume/core/skills.py +60 -0
- simple_resume/core/validation.py +321 -0
- simple_resume/py.typed +0 -0
- simple_resume/shell/__init__.py +3 -0
- simple_resume/shell/assets/static/css/README.md +213 -0
- simple_resume/shell/assets/static/css/common.css +641 -0
- simple_resume/shell/assets/static/css/fonts.css +42 -0
- simple_resume/shell/assets/static/css/preview.css +82 -0
- simple_resume/shell/assets/static/css/print.css +99 -0
- simple_resume/shell/assets/static/fonts/AvenirLTStd-Book.otf +0 -0
- simple_resume/shell/assets/static/fonts/AvenirLTStd-Light.otf +0 -0
- simple_resume/shell/assets/static/fonts/AvenirLTStd-Medium.otf +0 -0
- simple_resume/shell/assets/static/fonts/AvenirLTStd-Oblique.otf +0 -0
- simple_resume/shell/assets/static/fonts/AvenirLTStd-Roman.otf +0 -0
- simple_resume/shell/assets/static/fonts/fontawesome/Font Awesome 6 Brands-Regular-400.otf +0 -0
- simple_resume/shell/assets/static/fonts/fontawesome/Font Awesome 6 Free-Solid-900.otf +0 -0
- simple_resume/shell/assets/static/images/default_profile_1.jpg +0 -0
- simple_resume/shell/assets/static/images/default_profile_2.png +0 -0
- simple_resume/shell/assets/static/schema.json +236 -0
- simple_resume/shell/assets/static/themes/README.md +208 -0
- simple_resume/shell/assets/static/themes/bold.yaml +64 -0
- simple_resume/shell/assets/static/themes/classic.yaml +64 -0
- simple_resume/shell/assets/static/themes/executive.yaml +64 -0
- simple_resume/shell/assets/static/themes/minimal.yaml +64 -0
- simple_resume/shell/assets/static/themes/modern.yaml +64 -0
- simple_resume/shell/assets/templates/html/cover.html +129 -0
- simple_resume/shell/assets/templates/html/demo.html +13 -0
- simple_resume/shell/assets/templates/html/resume_base.html +453 -0
- simple_resume/shell/assets/templates/html/resume_no_bars.html +316 -0
- simple_resume/shell/assets/templates/html/resume_with_bars.html +362 -0
- simple_resume/shell/cli/__init__.py +35 -0
- simple_resume/shell/cli/main.py +975 -0
- simple_resume/shell/cli/palette.py +75 -0
- simple_resume/shell/cli/random_palette_demo.py +407 -0
- simple_resume/shell/config.py +96 -0
- simple_resume/shell/effect_executor.py +211 -0
- simple_resume/shell/file_opener.py +308 -0
- simple_resume/shell/generate/__init__.py +37 -0
- simple_resume/shell/generate/core.py +650 -0
- simple_resume/shell/generate/lazy.py +284 -0
- simple_resume/shell/io_utils.py +199 -0
- simple_resume/shell/palettes/__init__.py +1 -0
- simple_resume/shell/palettes/fetch.py +63 -0
- simple_resume/shell/palettes/loader.py +321 -0
- simple_resume/shell/palettes/remote.py +179 -0
- simple_resume/shell/pdf_executor.py +52 -0
- simple_resume/shell/py.typed +0 -0
- simple_resume/shell/render/__init__.py +1 -0
- simple_resume/shell/render/latex.py +308 -0
- simple_resume/shell/render/operations.py +240 -0
- simple_resume/shell/resume_extensions.py +737 -0
- simple_resume/shell/runtime/__init__.py +7 -0
- simple_resume/shell/runtime/content.py +190 -0
- simple_resume/shell/runtime/generate.py +497 -0
- simple_resume/shell/runtime/lazy.py +138 -0
- simple_resume/shell/runtime/lazy_import.py +173 -0
- simple_resume/shell/service_locator.py +80 -0
- simple_resume/shell/services.py +256 -0
- simple_resume/shell/session/__init__.py +6 -0
- simple_resume/shell/session/config.py +35 -0
- simple_resume/shell/session/manage.py +386 -0
- simple_resume/shell/strategies.py +181 -0
- simple_resume/shell/themes/__init__.py +35 -0
- simple_resume/shell/themes/loader.py +230 -0
- simple_resume-0.1.9.dist-info/METADATA +201 -0
- simple_resume-0.1.9.dist-info/RECORD +116 -0
- simple_resume-0.1.9.dist-info/WHEEL +4 -0
- simple_resume-0.1.9.dist-info/entry_points.txt +5 -0
- simple_resume-0.1.9.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
{# NOTE: dynamic_font_size is now provided as a Python global function in manage.py
|
|
2
|
+
The old macro has been removed to avoid namespace collision.
|
|
3
|
+
Usage: {% set size = dynamic_font_size(text, width_mm, max_pt, min_pt) %}
|
|
4
|
+
#}
|
|
5
|
+
|
|
6
|
+
{%- macro render_sidebar_entries(entries, available_width, base_font_pt=9, min_font_pt=7) -%}
|
|
7
|
+
{%- set ns = namespace(normalized=[]) -%}
|
|
8
|
+
{%- if entries is mapping -%}
|
|
9
|
+
{%- for value in entries.values() -%}
|
|
10
|
+
{%- if value is iterable and value is not mapping and value is not string -%}
|
|
11
|
+
{%- for item in value -%}
|
|
12
|
+
{%- set item_str = item | string | trim -%}
|
|
13
|
+
{%- if item_str -%}{%- set ns.normalized = ns.normalized + [item_str] -%}{%- endif -%}
|
|
14
|
+
{%- endfor -%}
|
|
15
|
+
{%- else -%}
|
|
16
|
+
{%- set item_str = value | string | trim -%}
|
|
17
|
+
{%- if item_str -%}{%- set ns.normalized = ns.normalized + [item_str] -%}{%- endif -%}
|
|
18
|
+
{%- endif -%}
|
|
19
|
+
{%- endfor -%}
|
|
20
|
+
{%- elif entries is string -%}
|
|
21
|
+
{%- set ns.normalized = [entries] -%}
|
|
22
|
+
{%- elif entries is iterable -%}
|
|
23
|
+
{%- for value in entries -%}
|
|
24
|
+
{%- if value is iterable and value is not mapping and value is not string -%}
|
|
25
|
+
{%- for item in value -%}
|
|
26
|
+
{%- set item_str = item | string | trim -%}
|
|
27
|
+
{%- if item_str -%}{%- set ns.normalized = ns.normalized + [item_str] -%}{%- endif -%}
|
|
28
|
+
{%- endfor -%}
|
|
29
|
+
{%- else -%}
|
|
30
|
+
{%- set item_str = value | string | trim -%}
|
|
31
|
+
{%- if item_str -%}{%- set ns.normalized = ns.normalized + [item_str] -%}{%- endif -%}
|
|
32
|
+
{%- endif -%}
|
|
33
|
+
{%- endfor -%}
|
|
34
|
+
{%- else -%}
|
|
35
|
+
{%- set ns.normalized = [entries | string] -%}
|
|
36
|
+
{%- endif -%}
|
|
37
|
+
{%- set delimiter = resume_config.get("sidebar_inline_delimiter") %}
|
|
38
|
+
{%- if delimiter %}
|
|
39
|
+
{%- set clean_delimiter = delimiter.strip() %}
|
|
40
|
+
{%- if clean_delimiter %}
|
|
41
|
+
{%- set join_token = " " ~ clean_delimiter ~ " " %}
|
|
42
|
+
{%- else %}
|
|
43
|
+
{%- set join_token = " " %}
|
|
44
|
+
{%- endif %}
|
|
45
|
+
{%- set joined = ns.normalized | join(join_token) %}
|
|
46
|
+
<p>{{ joined }}</p>
|
|
47
|
+
{%- else %}
|
|
48
|
+
{%- for entry in ns.normalized %}
|
|
49
|
+
{%- set text = entry %}
|
|
50
|
+
<p class="sidebar-entry-item">
|
|
51
|
+
<span class="sidebar-entry-bullet">•</span>
|
|
52
|
+
{{ text }}
|
|
53
|
+
</p>
|
|
54
|
+
{%- endfor %}
|
|
55
|
+
{%- endif %}
|
|
56
|
+
{%- endmacro %}
|
|
57
|
+
|
|
58
|
+
{%- macro section_icon_svg(section_name) -%}
|
|
59
|
+
{%- set name_lower = section_name.lower() -%}
|
|
60
|
+
{% if 'experience' in name_lower or 'work' in name_lower or 'employment' in name_lower %}
|
|
61
|
+
{# Briefcase icon #}
|
|
62
|
+
<svg viewBox="0 0 490 490" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
63
|
+
<path d="M294.4 322.8c0 7.4-6.2 13.6-13.6 13.6h-71.6c-7.4 0-13.6-6.2-13.6-13.6v-62.2L0 174.6V490h490V175l-195.6 85.6v62.2z"/>
|
|
64
|
+
<path d="M174.3 71.2c0-27.6 22.4-50 50-50h41.4c27.3 0 49.7 22.4 49.7 50v10.1h25V67.7c0-37.3-30.3-67.7-67.3-67.7h-56c-37.3 0-67.7 30.3-67.7 67.7v13.6h25V71.2z"/>
|
|
65
|
+
<path d="M0 108.5v36.2L245.4 251.2 490 145.1v-36.6z"/>
|
|
66
|
+
</svg>
|
|
67
|
+
{% elif 'education' in name_lower or 'school' in name_lower or 'university' in name_lower %}
|
|
68
|
+
{# Graduation cap icon #}
|
|
69
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
70
|
+
<path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/>
|
|
71
|
+
</svg>
|
|
72
|
+
{% elif 'project' in name_lower %}
|
|
73
|
+
{# Projects gear icon #}
|
|
74
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
75
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.99996 2C9.44768 2 8.99996 2.44772 8.99996 3V4.58178C8.30471 4.86318 7.65844 5.23923 7.07704 5.69365L5.70573 4.90193C5.47605 4.76932 5.20309 4.73338 4.94691 4.80202C4.69073 4.87067 4.47232 5.03827 4.33971 5.26795L2.33971 8.73205C2.06357 9.21034 2.22744 9.82193 2.70573 10.0981L4.07654 10.8895C4.02603 11.2528 3.99997 11.6236 3.99997 12C3.99997 12.3764 4.02603 12.7471 4.07654 13.1105L2.70574 13.9019C2.47605 14.0345 2.30846 14.2529 2.23981 14.5091C2.17117 14.7653 2.2071 15.0382 2.33971 15.2679L4.33971 18.732C4.47232 18.9617 4.69074 19.1293 4.94692 19.198C5.2031 19.2666 5.47605 19.2307 5.70574 19.0981L7.07706 18.3063C7.65846 18.7607 8.30472 19.1368 8.99996 19.4182V21C8.99996 21.5523 9.44768 22 9.99996 22H14C14.5522 22 15 21.5523 15 21V19.4182C15.6952 19.1368 16.3415 18.7607 16.9229 18.3063L18.2942 19.0981C18.5239 19.2307 18.7968 19.2666 19.053 19.198C19.3092 19.1293 19.5276 18.9617 19.6602 18.7321L21.6602 15.268C21.7928 15.0383 21.8288 14.7653 21.7601 14.5091C21.6915 14.253 21.5239 14.0345 21.2942 13.9019L19.9234 13.1105C19.9739 12.7472 20 12.3764 20 12C20 11.6236 19.9739 11.2528 19.9234 10.8895L21.2942 10.0981C21.7725 9.82191 21.9364 9.21032 21.6602 8.73203L19.6602 5.26793C19.5276 5.03824 19.3092 4.87065 19.053 4.802C18.7968 4.73336 18.5239 4.76929 18.2942 4.9019L16.9229 5.69364C16.3415 5.23922 15.6952 4.86318 15 4.58178V3C15 2.44772 14.5522 2 14 2H9.99996ZM11 5.28986V4H13V5.28986C13 5.73228 13.2907 6.12211 13.7147 6.24831C14.6258 6.51947 15.4475 7.00198 16.1223 7.64029C16.4436 7.94424 16.9264 8.00099 17.3095 7.77984L18.4282 7.13395L19.4282 8.866L18.3109 9.51107C17.9281 9.73205 17.7358 10.1781 17.8379 10.6081C17.9437 11.0538 18 11.5197 18 12C18 12.4803 17.9437 12.9462 17.8379 13.3919C17.7358 13.8219 17.9281 14.2679 18.3109 14.4889L19.4282 15.134L18.4282 16.866L17.3094 16.2201C16.9264 15.999 16.4436 16.0557 16.1222 16.3597C15.4475 16.998 14.6258 17.4805 13.7147 17.7516C13.2907 17.8778 13 18.2677 13 18.7101V20H11V18.7101C11 18.2677 10.7092 17.8778 10.2852 17.7516C9.37409 17.4805 8.55246 16.998 7.87767 16.3597C7.55635 16.0557 7.07352 15.999 6.69048 16.2201L5.57176 16.866L4.57176 15.134L5.68905 14.4889C6.0718 14.2679 6.26409 13.8219 6.16201 13.3919C6.05621 12.9462 5.99997 12.4803 5.99997 12C5.99997 11.5197 6.0562 11.0538 6.16201 10.6081C6.26409 10.1781 6.07179 9.73207 5.68905 9.51109L4.57176 8.86603L5.57176 7.13398L6.69046 7.77986C7.07351 8.00101 7.55633 7.94425 7.87766 7.6403C8.55245 7.00199 9.37409 6.51948 10.2852 6.24831C10.7092 6.12211 11 5.73228 11 5.28986ZM9.99998 12C9.99998 10.8954 10.8954 10 12 10C13.1046 10 14 10.8954 14 12C14 13.1046 13.1046 14 12 14C10.8954 14 9.99998 13.1046 9.99998 12ZM12 8C9.79084 8 7.99998 9.79086 7.99998 12C7.99998 14.2091 9.79084 16 12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8Z" fill="{{ section_icon_color }}"/>
|
|
76
|
+
</svg>
|
|
77
|
+
{% elif 'speak' in name_lower or 'talk' in name_lower or 'presentation' in name_lower %}
|
|
78
|
+
{# Microphone icon for speaking engagements #}
|
|
79
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="none" stroke="{{ section_icon_color }}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
80
|
+
<path d="M19 10V12C19 15.866 15.866 19 12 19M5 10V12C5 15.866 8.13401 19 12 19M12 19V22M8 22H16M15 6H13M15 10H13M12 15C10.3431 15 9 13.6569 9 12V5C9 3.34315 10.3431 2 12 2C13.6569 2 15 3.34315 15 5V12C15 13.6569 13.6569 15 12 15Z"/>
|
|
81
|
+
</svg>
|
|
82
|
+
{% elif 'volunteer' in name_lower or 'service' in name_lower %}
|
|
83
|
+
{# Volunteer service icon #}
|
|
84
|
+
<svg viewBox="0 0 50 50" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
85
|
+
<path d="M46.79248 24.23a4.05389 4.05389 0 0 0-5.689-.14l-7.69872 6.84a5.25608 5.25608 0 0 1 .58993 2.43 5.39055 5.39055 0 0 1-3.4794 5.02l-6.46895 2.43a1.00694 1.00694 0 0 1-1.27975-.59.98322.98322 0 0 1 .57986-1.28l6.46895-2.43a3.38021 3.38021 0 0 0 2.77637-3.62A3.45753 3.45753 0 0 0 28.63555 30H9.99866A1.99982 1.99982 0 0 0 7.999 28H3.99966A1.99982 1.99982 0 0 0 2 30v16a1.99986 1.99986 0 0 0 1.99966 2H7.999a1.99986 1.99986 0 0 0 1.99967-2H14.048l1.24979.51A19.61328 19.61328 0 0 0 37.924 40.87l9.10846-11.01a4.20182 4.20182 0 0 0-.24094-5.63ZM12.99816 44H9.99866V32h2.9995ZM30.41809 2a8.59142 8.59142 0 0 0-5.42194 1.9082A8.59147 8.59147 0 0 0 19.5742 2a8.68822 8.68822 0 0 0-8.66651 8.68945c0 9.14258 13.03 16.85059 13.58463 17.17481a1.00289 1.00289 0 0 0 1.00765 0C26.05456 27.54 39.08461 19.832 39.08461 10.68945A8.68822 8.68822 0 0 0 30.41809 2Zm-1.772 18.6571a.98319.98319 0 0 1-.65022.2229.99554.99554 0 0 1-.65047-1.7423c3.70153-3.1709 5.74025-6.17188 5.74025-8.44825A2.68158 2.68158 0 0 0 30.41809 8a1 1 0 0 1 0-2 4.68337 4.68337 0 0 1 4.66719 4.68945c.00005 2.67865-3.50123 6.45008-6.43818 8.96765Z"/>
|
|
86
|
+
</svg>
|
|
87
|
+
{% elif 'publication' in name_lower or 'paper' in name_lower or 'journal' in name_lower %}
|
|
88
|
+
{# Publications icon #}
|
|
89
|
+
<svg viewBox="0 0 24 24" width="256" height="256" role="presentation" focusable="false" fill="none" stroke="{{ section_icon_color }}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
90
|
+
<path d="M6 6h8"/>
|
|
91
|
+
<path d="M6 10h12"/>
|
|
92
|
+
<path d="M12 14h6"/>
|
|
93
|
+
<path d="M12 18h6"/>
|
|
94
|
+
<path d="M2 21.4V2.6c0-.331.269-.6.6-.6h15.652a.6.6 0 01.424.176l3.148 3.148a.6.6 0 01.176.424V21.4a.6.6 0 01-.6.6H2.6a.6.6 0 01-.6-.6z"/>
|
|
95
|
+
<path d="M18 5.4V2.354a.354.354 0 01.354-.354c.094 0 .184.037.25.103l3.293 3.293a.354.354 0 01-.25.603H18.6a.6.6 0 01-.6-.6z" fill="{{ section_icon_color }}"/>
|
|
96
|
+
<path d="M6 18v-4h2v4H6z" fill="{{ section_icon_color }}"/>
|
|
97
|
+
</svg>
|
|
98
|
+
{% elif 'award' in name_lower or 'honor' in name_lower or 'achievement' in name_lower %}
|
|
99
|
+
{# Award/trophy icon - Simple Flat UI Design #}
|
|
100
|
+
<svg viewBox="0 0 512 512" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
101
|
+
<path d="M348.375 384.758c-12.811-25.137-32.785-44.594-56.582-54.492v-38.5l.047-9.133c-.016 0-.031 0-.047.004v-.242c-11.588 2.262-23.551 3.481-35.791 3.481-11.369 0-22.476-1.094-33.291-3.055-.752-.152-1.516-.262-2.264-.426v.043c-.08-.016-.16-.028-.24-.043v47.871c-12.209 5.078-23.393 12.695-33.137 22.293-.348.34-.705.66-1.049 1.004-1.072 1.082-2.1 2.219-3.133 3.348-.705.77-1.426 1.512-2.115 2.305-.61.703-1.184 1.442-1.78 2.156-1.07 1.289-2.14 2.574-3.168 3.918-.088.117-.17.238-.26.355-4.392 5.789-8.406 12.078-11.939 18.875h.131c-.043.082-.09.16-.131.238h233.654z"/>
|
|
102
|
+
<path d="M115.046 416v95.371l-.002.387h.002V512h281.911v-96z"/>
|
|
103
|
+
<path d="M498.331 29.387c-8.027-9.094-19.447-14.312-31.328-14.312h-47.744V0h-326.52v15.074H44.999c-11.887 0-23.306 5.218-31.336 14.312C3.906 40.442-0.305 56.43 1.775 74.465c.369 7.922 4.367 49.316 47.211 78.77 24.732 17.008 48.424 24.629 69.44 27.938 29.008 45.328 79.76 75.398 137.576 75.398 57.805 0 108.558-30.07 137.568-75.398 21.016-3.305 44.709-10.93 69.445-27.938 42.84-29.453 46.842-70.848 47.211-78.77 2.08-18.035-2.131-34.023-11.893-45.078zm-22.093 41.629-.125.852-.002 1.031c-.029 1.246-1.115 30.656-32.447 52.195-8.976 6.172-17.635 10.719-26.041 14.184-1.836.711-3.668 1.43-5.553 2.043 4.664-15.184 7.19-31.297 7.19-48.008V49.226h47.744c1.498 0 3.711.481 5.726 2.758 2.021 2.257 3.3 9.191 2.25 17.57zm-222.274 84.203-33.658 18.73c-1.422.793-3.174.688-4.49-.274-1.312-.949-1.959-2.586-1.644-4.18l7.412-37.801c.279-1.418-.193-2.883-1.254-3.863l-28.213-26.23c-1.191-1.106-1.633-2.805-1.129-4.352s1.859-2.664 3.474-2.859l38.236-4.633c1.436-.172 2.678-1.078 3.291-2.391l16.219-34.93c.687-1.477 2.162-2.422 3.795-2.422 1.625 0 3.102.945 3.787 2.422l16.22 34.93c.612 1.312 1.854 2.219 3.289 2.391l38.236 4.633c1.615.195 2.971 1.312 3.474 2.859.504 1.547.063 3.246-1.127 4.352l-28.215 26.23c-1.059.98-1.541 2.445-1.26 3.863l7.418 37.801c.313 1.594-.328 3.23-1.648 4.18-1.316.961-3.06 1.066-4.486.274l-33.664-18.73c-1.266-.699-2.805-.699-4.071 0zm-185.633-30.125c-31.326-21.539-32.41-50.949-32.438-52.016l-.006-1.035-.131-1.027c-1.043-8.379.232-15.312 3.516-19.031 2.01-2.277 4.222-2.758 5.726-2.758h47.742v44.086c0 14.246 1.928 28.02 5.357 41.192.559 2.308 1.076 4.629 1.725 6.926-10.427-1.758-20.902-6.957-31.828-14.465z"/>
|
|
104
|
+
</svg>
|
|
105
|
+
{% else %}
|
|
106
|
+
{# Default icon - document/file #}
|
|
107
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
108
|
+
<path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.89 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/>
|
|
109
|
+
</svg>
|
|
110
|
+
{% endif %}
|
|
111
|
+
{%- endmacro %}
|
|
112
|
+
|
|
113
|
+
{%- macro section_icon(section_name) -%}
|
|
114
|
+
<div class="timeline-icon">
|
|
115
|
+
<span class="icon" aria-hidden="true">
|
|
116
|
+
{{ section_icon_svg(section_name) }}
|
|
117
|
+
</span>
|
|
118
|
+
</div>
|
|
119
|
+
{%- endmacro %}
|
|
120
|
+
|
|
121
|
+
{%- macro section_icon_inline(section_name) -%}
|
|
122
|
+
<span class="icon-inline" aria-hidden="true">
|
|
123
|
+
{{ section_icon_svg(section_name) }}
|
|
124
|
+
</span>
|
|
125
|
+
{%- endmacro %}
|
|
126
|
+
|
|
127
|
+
{% macro contact_icon(kind) -%}
|
|
128
|
+
<span class="icon contact-icon" aria-hidden="true">
|
|
129
|
+
{% if kind == "address" %}
|
|
130
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
131
|
+
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
|
|
132
|
+
</svg>
|
|
133
|
+
{% elif kind == "phone" %}
|
|
134
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
135
|
+
<path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/>
|
|
136
|
+
</svg>
|
|
137
|
+
{% elif kind == "email" %}
|
|
138
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
139
|
+
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/>
|
|
140
|
+
</svg>
|
|
141
|
+
{% elif kind == "web" %}
|
|
142
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
143
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
|
144
|
+
</svg>
|
|
145
|
+
{% elif kind == "linkedin" %}
|
|
146
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
147
|
+
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/>
|
|
148
|
+
</svg>
|
|
149
|
+
{% elif kind == "github" %}
|
|
150
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
151
|
+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
152
|
+
</svg>
|
|
153
|
+
{% else %}
|
|
154
|
+
<svg viewBox="0 0 24 24" role="presentation" focusable="false" fill="{{ section_icon_color }}">
|
|
155
|
+
<circle cx="12" cy="12" r="9"/>
|
|
156
|
+
</svg>
|
|
157
|
+
{% endif %}
|
|
158
|
+
</span>
|
|
159
|
+
{%- endmacro %}
|
|
160
|
+
{# ========================================================================== #}
|
|
161
|
+
{# ICON COLOR CALCULATION WITH WCAG CONTRAST CHECKING #}
|
|
162
|
+
{# ========================================================================== #}
|
|
163
|
+
{# This section calculates the optimal icon color to ensure accessibility #}
|
|
164
|
+
{# by checking WCAG contrast ratios against the sidebar background. #}
|
|
165
|
+
{# ========================================================================== #}
|
|
166
|
+
|
|
167
|
+
{%- set sidebar_color = resume_config.get("sidebar_color", "#FFFFFF") -%}
|
|
168
|
+
{%- set sidebar_luminance = none -%}
|
|
169
|
+
{%- set sidebar_parse_error = false -%}
|
|
170
|
+
|
|
171
|
+
{# Parse sidebar background color and calculate luminance #}
|
|
172
|
+
{%- if sidebar_color and sidebar_color.startswith('#') -%}
|
|
173
|
+
{%- set hex_sidebar = sidebar_color[1:] -%}
|
|
174
|
+
{%- if hex_sidebar|length == 3 -%}
|
|
175
|
+
{%- set r_bg = (hex_sidebar[0:1] * 2) | int(base=16) -%}
|
|
176
|
+
{%- set g_bg = (hex_sidebar[1:2] * 2) | int(base=16) -%}
|
|
177
|
+
{%- set b_bg = (hex_sidebar[2:3] * 2) | int(base=16) -%}
|
|
178
|
+
{%- elif hex_sidebar|length == 6 -%}
|
|
179
|
+
{%- set r_bg = hex_sidebar[0:2] | int(base=16) -%}
|
|
180
|
+
{%- set g_bg = hex_sidebar[2:4] | int(base=16) -%}
|
|
181
|
+
{%- set b_bg = hex_sidebar[4:6] | int(base=16) -%}
|
|
182
|
+
{%- else -%}
|
|
183
|
+
{# Invalid hex format - set error flag #}
|
|
184
|
+
{%- set sidebar_parse_error = true -%}
|
|
185
|
+
{%- set r_bg = 255 -%}
|
|
186
|
+
{%- set g_bg = 255 -%}
|
|
187
|
+
{%- set b_bg = 255 -%}
|
|
188
|
+
{%- endif -%}
|
|
189
|
+
|
|
190
|
+
{# Calculate relative luminance (ITU-R BT.601) #}
|
|
191
|
+
{%- set sidebar_luminance = (0.299 * r_bg + 0.587 * g_bg + 0.114 * b_bg) / 255 -%}
|
|
192
|
+
{%- else -%}
|
|
193
|
+
{# Non-hex color - assume light background as fallback #}
|
|
194
|
+
{%- set sidebar_parse_error = true -%}
|
|
195
|
+
{%- set sidebar_luminance = 0.9 -%}
|
|
196
|
+
{%- endif -%}
|
|
197
|
+
|
|
198
|
+
{# Determine automatic high-contrast icon color based on sidebar luminance #}
|
|
199
|
+
{# Using luminance threshold of 0.5 (midpoint) to decide light vs dark icons #}
|
|
200
|
+
{%- set icon_contrast_color = none -%}
|
|
201
|
+
{%- if sidebar_luminance is not none -%}
|
|
202
|
+
{%- if sidebar_luminance < 0.5 -%}
|
|
203
|
+
{# Dark background -> use white icons #}
|
|
204
|
+
{%- set icon_contrast_color = "#FFFFFF" -%}
|
|
205
|
+
{%- else -%}
|
|
206
|
+
{# Light background -> use dark icons #}
|
|
207
|
+
{%- set icon_contrast_color = "#2c3e50" -%}
|
|
208
|
+
{%- endif -%}
|
|
209
|
+
{%- else -%}
|
|
210
|
+
{# Fallback if luminance couldn't be calculated #}
|
|
211
|
+
{%- set icon_contrast_color = "#2c3e50" -%}
|
|
212
|
+
{%- endif -%}
|
|
213
|
+
|
|
214
|
+
{# ========================================================================== #}
|
|
215
|
+
{# RESOLVE FINAL ICON COLOR WITH WCAG CONTRAST VALIDATION #}
|
|
216
|
+
{# ========================================================================== #}
|
|
217
|
+
|
|
218
|
+
{# Check if user explicitly requested a sidebar icon color #}
|
|
219
|
+
{%- set requested_sidebar_icon_color = resume_config.get("sidebar_icon_color") -%}
|
|
220
|
+
{%- set section_icon_color = requested_sidebar_icon_color if requested_sidebar_icon_color else icon_contrast_color -%}
|
|
221
|
+
|
|
222
|
+
{# Parse the requested/initial icon color and calculate its luminance #}
|
|
223
|
+
{%- set icon_luminance = none -%}
|
|
224
|
+
{%- set icon_parse_error = false -%}
|
|
225
|
+
{%- if section_icon_color and section_icon_color.startswith('#') -%}
|
|
226
|
+
{%- set hex_icon = section_icon_color[1:] -%}
|
|
227
|
+
{%- if hex_icon|length == 3 -%}
|
|
228
|
+
{%- set r_icon = (hex_icon[0:1] * 2) | int(base=16) -%}
|
|
229
|
+
{%- set g_icon = (hex_icon[1:2] * 2) | int(base=16) -%}
|
|
230
|
+
{%- set b_icon = (hex_icon[2:3] * 2) | int(base=16) -%}
|
|
231
|
+
{%- elif hex_icon|length == 6 -%}
|
|
232
|
+
{%- set r_icon = hex_icon[0:2] | int(base=16) -%}
|
|
233
|
+
{%- set g_icon = hex_icon[2:4] | int(base=16) -%}
|
|
234
|
+
{%- set b_icon = hex_icon[4:6] | int(base=16) -%}
|
|
235
|
+
{%- else -%}
|
|
236
|
+
{%- set icon_parse_error = true -%}
|
|
237
|
+
{%- set r_icon = none -%}
|
|
238
|
+
{%- set g_icon = none -%}
|
|
239
|
+
{%- set b_icon = none -%}
|
|
240
|
+
{%- endif -%}
|
|
241
|
+
{%- if r_icon is not none and g_icon is not none and b_icon is not none -%}
|
|
242
|
+
{%- set icon_luminance = (0.299 * r_icon + 0.587 * g_icon + 0.114 * b_icon) / 255 -%}
|
|
243
|
+
{%- endif -%}
|
|
244
|
+
{%- else -%}
|
|
245
|
+
{%- set icon_parse_error = true -%}
|
|
246
|
+
{%- endif -%}
|
|
247
|
+
|
|
248
|
+
{# Calculate WCAG contrast ratio and validate accessibility #}
|
|
249
|
+
{%- set contrast_ratio = none -%}
|
|
250
|
+
{%- set contrast_check_passed = false -%}
|
|
251
|
+
{%- if icon_luminance is not none and sidebar_luminance is not none -%}
|
|
252
|
+
{# WCAG contrast ratio formula: (L1 + 0.05) / (L2 + 0.05) where L1 >= L2 #}
|
|
253
|
+
{%- if icon_luminance > sidebar_luminance -%}
|
|
254
|
+
{%- set contrast_ratio = (icon_luminance + 0.05) / (sidebar_luminance + 0.05) -%}
|
|
255
|
+
{%- else -%}
|
|
256
|
+
{%- set contrast_ratio = (sidebar_luminance + 0.05) / (icon_luminance + 0.05) -%}
|
|
257
|
+
{%- endif -%}
|
|
258
|
+
|
|
259
|
+
{# WCAG AA requires 3.0:1 for large text/icons, 4.5:1 for normal text #}
|
|
260
|
+
{# Using 3.0 threshold for icons (they're similar to large text) #}
|
|
261
|
+
{%- if contrast_ratio >= 3.0 -%}
|
|
262
|
+
{%- set contrast_check_passed = true -%}
|
|
263
|
+
{%- endif -%}
|
|
264
|
+
{%- endif -%}
|
|
265
|
+
|
|
266
|
+
{# Override with high-contrast color if WCAG check failed or colors couldn't be parsed #}
|
|
267
|
+
{%- if not contrast_check_passed or icon_parse_error or sidebar_parse_error -%}
|
|
268
|
+
{%- set section_icon_color = icon_contrast_color -%}
|
|
269
|
+
{# Recalculate contrast ratio for debug output #}
|
|
270
|
+
{%- if icon_contrast_color == "#FFFFFF" -%}
|
|
271
|
+
{%- set final_icon_luminance = 1.0 -%}
|
|
272
|
+
{%- elif icon_contrast_color == "#2c3e50" -%}
|
|
273
|
+
{%- set final_icon_luminance = 0.196 -%}
|
|
274
|
+
{%- else -%}
|
|
275
|
+
{%- set final_icon_luminance = none -%}
|
|
276
|
+
{%- endif -%}
|
|
277
|
+
{%- if final_icon_luminance is not none and sidebar_luminance is not none -%}
|
|
278
|
+
{%- if final_icon_luminance > sidebar_luminance -%}
|
|
279
|
+
{%- set contrast_ratio = (final_icon_luminance + 0.05) / (sidebar_luminance + 0.05) -%}
|
|
280
|
+
{%- else -%}
|
|
281
|
+
{%- set contrast_ratio = (sidebar_luminance + 0.05) / (final_icon_luminance + 0.05) -%}
|
|
282
|
+
{%- endif -%}
|
|
283
|
+
{%- endif -%}
|
|
284
|
+
{%- endif -%}
|
|
285
|
+
|
|
286
|
+
{# ========================================================================== #}
|
|
287
|
+
{# SECTION HEADER COLOR CALCULATION #}
|
|
288
|
+
{# ========================================================================== #}
|
|
289
|
+
{# Calculate section header color based on theme color luminance. #}
|
|
290
|
+
{# Light theme colors get dark text, dark theme colors keep their color. #}
|
|
291
|
+
{# ========================================================================== #}
|
|
292
|
+
|
|
293
|
+
{%- set theme_color = resume_config.get("theme_color", "#0395DE") -%}
|
|
294
|
+
{%- set section_header_color = theme_color -%}
|
|
295
|
+
|
|
296
|
+
{%- if theme_color.startswith('#') -%}
|
|
297
|
+
{%- set hex_color = theme_color[1:] -%}
|
|
298
|
+
{%- if hex_color|length == 3 -%}
|
|
299
|
+
{%- set r = (hex_color[0:1] * 2) | int(base=16) -%}
|
|
300
|
+
{%- set g = (hex_color[1:2] * 2) | int(base=16) -%}
|
|
301
|
+
{%- set b = (hex_color[2:3] * 2) | int(base=16) -%}
|
|
302
|
+
{%- elif hex_color|length == 6 -%}
|
|
303
|
+
{%- set r = hex_color[0:2] | int(base=16) -%}
|
|
304
|
+
{%- set g = hex_color[2:4] | int(base=16) -%}
|
|
305
|
+
{%- set b = hex_color[4:6] | int(base=16) -%}
|
|
306
|
+
{%- else -%}
|
|
307
|
+
{%- set r = 0 -%}
|
|
308
|
+
{%- set g = 0 -%}
|
|
309
|
+
{%- set b = 0 -%}
|
|
310
|
+
{%- endif -%}
|
|
311
|
+
|
|
312
|
+
{%- set luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 -%}
|
|
313
|
+
{%- if luminance >= 0.5 -%}
|
|
314
|
+
{%- set section_header_color = "#2c3e50" -%}
|
|
315
|
+
{%- endif -%}
|
|
316
|
+
{%- else -%}
|
|
317
|
+
{# Fallback for non-hex colors #}
|
|
318
|
+
{%- set section_header_color = "#2c3e50" -%}
|
|
319
|
+
{%- endif -%}
|
|
320
|
+
|
|
321
|
+
<!-- DEBUG: Color Contrast Calculation Results -->
|
|
322
|
+
<!-- Sidebar: {{ sidebar_color }} (luminance: {{ "%.3f"|format(sidebar_luminance) if sidebar_luminance is not none else "PARSE_ERROR" }}) -->
|
|
323
|
+
<!-- Requested Icon: {{ requested_sidebar_icon_color if requested_sidebar_icon_color else "auto" }} -->
|
|
324
|
+
<!-- Auto Contrast: {{ icon_contrast_color }} -->
|
|
325
|
+
<!-- Final Icon: {{ section_icon_color }} (luminance: {{ "%.3f"|format(icon_luminance) if icon_luminance is not none else "N/A" }}) -->
|
|
326
|
+
<!-- Contrast Ratio: {{ "%.2f"|format(contrast_ratio) if contrast_ratio is not none else "N/A" }}:1 (WCAG AA minimum: 3.0:1) -->
|
|
327
|
+
<!-- WCAG Check: {{ "PASS" if contrast_check_passed else "FAIL - using auto contrast" }} -->
|
|
328
|
+
<!DOCTYPE html>
|
|
329
|
+
|
|
330
|
+
<html>
|
|
331
|
+
<head>
|
|
332
|
+
<!-- CSS Custom Properties from YAML config - MUST be first for WeasyPrint -->
|
|
333
|
+
<style>
|
|
334
|
+
:root {
|
|
335
|
+
/* ================================================================
|
|
336
|
+
* CSS Custom Properties - Defensive Default Values
|
|
337
|
+
* ================================================================
|
|
338
|
+
* These .get() fallbacks intentionally match the values in
|
|
339
|
+
* apply_config_defaults() (src/simple_resume/core/config.py).
|
|
340
|
+
* This redundancy is defensive programming: if Python fails to
|
|
341
|
+
* provide a config value, the template degrades gracefully.
|
|
342
|
+
* ================================================================ */
|
|
343
|
+
|
|
344
|
+
/* Colors */
|
|
345
|
+
--sidebar-color: {{ resume_config.get("sidebar_color", "#F6F6F6") }};
|
|
346
|
+
--sidebar-text-color: {{ resume_config.get("sidebar_text_color", "#000000") }};
|
|
347
|
+
--theme-color: {{ resume_config.get("theme_color", "#0395DE") }};
|
|
348
|
+
--date2-color: {{ resume_config.get("date2_color", "#616161") }};
|
|
349
|
+
--bar-background-color: {{ resume_config.get("bar_background_color", "#DFDFDF") }};
|
|
350
|
+
--frame-color: {{ resume_config.get("frame_color", "#757575") }};
|
|
351
|
+
--heading-icon-color: {{ resume_config.get("heading_icon_color", "#0395DE") }};
|
|
352
|
+
--section-icon-color: {{ section_icon_color }};
|
|
353
|
+
--section-header-color: {{ section_header_color }};
|
|
354
|
+
|
|
355
|
+
/* Page dimensions */
|
|
356
|
+
--page-width: {{ resume_config.get("page_width", 210) }}mm;
|
|
357
|
+
--page-height: {{ resume_config.get("page_height", 297) }}mm;
|
|
358
|
+
--sidebar-width: {{ resume_config.get("sidebar_width", 65) }}mm;
|
|
359
|
+
--body-width: {{ resume_config.get("page_width", 210) - resume_config.get("sidebar_width", 65) }}mm;
|
|
360
|
+
--padding: {{ resume_config.get("padding", 12) }}mm;
|
|
361
|
+
|
|
362
|
+
/* Sidebar padding */
|
|
363
|
+
--sidebar-padding-top: {{ resume_config.get("sidebar_padding_top", 0) }}mm;
|
|
364
|
+
--sidebar-padding-bottom: {{ resume_config.get("sidebar_padding_bottom", 12) }}mm;
|
|
365
|
+
--sidebar-padding-left: {{ resume_config.get("sidebar_padding_left", 10) }}mm;
|
|
366
|
+
--sidebar-padding-right: {{ resume_config.get("sidebar_padding_right", 10) }}mm;
|
|
367
|
+
|
|
368
|
+
/* Content spacing */
|
|
369
|
+
--pitch-padding-top: {{ resume_config.get("pitch_padding_top", 10) }}mm;
|
|
370
|
+
--pitch-padding-bottom: {{ resume_config.get("pitch_padding_bottom", 8) }}mm;
|
|
371
|
+
--pitch-padding-left: {{ resume_config.get("pitch_padding_left", 6) }}mm;
|
|
372
|
+
--h2-padding-left: {{ resume_config.get("h2_padding_left", 6) }}mm;
|
|
373
|
+
--h2-padding-left-full: {{ resume_config.get("h2_padding_left", 6) + 18 }}mm;
|
|
374
|
+
--h2-width: {{ resume_config.get("page_width", 210) - resume_config.get("sidebar_width", 65) - resume_config.get("h2_padding_left", 6) - 18 }}mm;
|
|
375
|
+
--h3-padding-top: {{ resume_config.get("h3_padding_top", 7) }}mm;
|
|
376
|
+
--date-container-width: {{ resume_config.get("date_container_width", 15) }}mm;
|
|
377
|
+
--description-container-padding-left: {{ resume_config.get("description_container_padding_left", 4) }}mm;
|
|
378
|
+
--skill-container-padding-top: {{ resume_config.get("skill_container_padding_top", 3) }}mm;
|
|
379
|
+
--profile-image-padding-bottom: {{ resume_config.get("profile_image_padding_bottom", 8) }}mm;
|
|
380
|
+
--profile-width: {{ resume_config.get("profile_width") or (resume_config.get("sidebar_width", 65) - resume_config.get("sidebar_padding_left", 10) - resume_config.get("sidebar_padding_right", 10)) }}mm;
|
|
381
|
+
--frame-padding: {{ resume_config.get("frame_padding", 15) }}mm;
|
|
382
|
+
|
|
383
|
+
/* Section icon styling */
|
|
384
|
+
--section-icon-circle-size: {{ resume_config.get("section_icon_circle_size", 7.8) }}mm;
|
|
385
|
+
--section-icon-circle-x-offset: {{ resume_config.get("section_icon_circle_x_offset", 0) }}mm;
|
|
386
|
+
--section-icon-design-size: {{ resume_config.get("section_icon_design_size", 3.5) }}mm;
|
|
387
|
+
--section-icon-design-x-offset: {{ resume_config.get("section_icon_design_x_offset", 0) }}mm;
|
|
388
|
+
--section-icon-design-y-offset: {{ resume_config.get("section_icon_design_y_offset", 0) }}mm;
|
|
389
|
+
--section-heading-text-margin: {{ resume_config.get("section_heading_text_margin", -6) }}mm;
|
|
390
|
+
--section-heading-marker-margin-left: -{{ (resume_config.get("h2_padding_left", 6) + 18) - (resume_config.get("date_container_width", 15) + 3) + 3 }}mm;
|
|
391
|
+
--section-heading-marker-line-height: calc(2.8mm + {{ resume_config.get("section_icon_circle_size", 7.8) }}mm);
|
|
392
|
+
|
|
393
|
+
--section-icon-design-scale: {{ resume_config.get("section_icon_design_scale", 1) }};
|
|
394
|
+
|
|
395
|
+
/* Section and entry spacing */
|
|
396
|
+
--section-heading-margin-top: {{ resume_config.get("section_heading_margin_top", 7) }}mm;
|
|
397
|
+
--section-heading-margin-bottom: {{ resume_config.get("section_heading_margin_bottom", 1) }}mm;
|
|
398
|
+
--entry-margin-bottom: {{ resume_config.get("entry_margin_bottom", 4) }}mm;
|
|
399
|
+
--tech-stack-margin-bottom: {{ resume_config.get("tech_stack_margin_bottom", 2) }}mm;
|
|
400
|
+
|
|
401
|
+
/* Font sizes */
|
|
402
|
+
--description-font-size: {{ resume_config.get("description_font_size", 8.5) }}pt;
|
|
403
|
+
--date-font-size: {{ resume_config.get("date_font_size", 9) }}pt;
|
|
404
|
+
--sidebar-font-size: {{ resume_config.get("sidebar_font_size", 8.5) }}pt;
|
|
405
|
+
|
|
406
|
+
/* Contact icon styling */
|
|
407
|
+
--contact-icon-size: {{ resume_config.get("contact_icon_size", 5) }}mm;
|
|
408
|
+
--contact-icon-margin-top: {{ resume_config.get("contact_icon_margin_top", 0.5) }}mm;
|
|
409
|
+
--contact-text-padding-left: {{ resume_config.get("contact_text_padding_left", 2) }}mm;
|
|
410
|
+
|
|
411
|
+
/* Sidebar item spacing */
|
|
412
|
+
--keyskills-item-margin-bottom: {{ resume_config.get("keyskills_item_margin_bottom", 0.5) }}mm;
|
|
413
|
+
--sidebar-skill-spacer-padding: {{ resume_config.get("sidebar_skill_spacer_padding", 0.5) }}mm;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/* Dynamic @page size for PDF rendering */
|
|
417
|
+
@page {
|
|
418
|
+
size: {{ resume_config.get("page_width", 210) }}mm {{ resume_config.get("page_height", 297) }}mm;
|
|
419
|
+
margin: 0;
|
|
420
|
+
}
|
|
421
|
+
@page resume {
|
|
422
|
+
size: {{ resume_config.get("page_width", 210) }}mm {{ resume_config.get("page_height", 297) }}mm;
|
|
423
|
+
margin: 0;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
</style>
|
|
427
|
+
|
|
428
|
+
<!-- Inlined CSS files from static/css/ -->
|
|
429
|
+
<style>
|
|
430
|
+
{% autoescape false %}
|
|
431
|
+
{% include "fonts.css" %}
|
|
432
|
+
{% include "common.css" %}
|
|
433
|
+
{% include "print.css" %}
|
|
434
|
+
{% if preview %}
|
|
435
|
+
{% include "preview.css" %}
|
|
436
|
+
{% endif %}
|
|
437
|
+
{% endautoescape %}
|
|
438
|
+
</style>
|
|
439
|
+
</head>
|
|
440
|
+
|
|
441
|
+
<body>{% if preview %}<div class="frame">{% endif %}<div class="page">
|
|
442
|
+
<div class="sidebar-container">
|
|
443
|
+
<div class="sidebar">
|
|
444
|
+
{% block sidebar %}{% endblock %}
|
|
445
|
+
</div>
|
|
446
|
+
</div>
|
|
447
|
+
|
|
448
|
+
<div class="body">
|
|
449
|
+
{% block body %}{% endblock %}
|
|
450
|
+
</div>
|
|
451
|
+
</div>{% if preview %}</div>{% endif %}
|
|
452
|
+
</body>
|
|
453
|
+
</html>
|