jekyll-theme-resume 1.3.0

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.
Files changed (123) hide show
  1. checksums.yaml +7 -0
  2. data/403.html +6 -0
  3. data/404.html +6 -0
  4. data/500.html +6 -0
  5. data/CHANGELOG.md +498 -0
  6. data/CODE_OF_CONDUCT.md +92 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +184 -0
  9. data/SECURITY.md +30 -0
  10. data/_config.sample.yml +329 -0
  11. data/_data/locales/ar.yml +85 -0
  12. data/_data/locales/de.yml +86 -0
  13. data/_data/locales/en.yml +84 -0
  14. data/_data/locales/es.yml +86 -0
  15. data/_data/locales/fr.yml +86 -0
  16. data/_data/locales/ur.yml +86 -0
  17. data/_data/social_networks.yml +83 -0
  18. data/_includes/analytics-body.html +12 -0
  19. data/_includes/analytics-head.html +36 -0
  20. data/_includes/avatar.html +84 -0
  21. data/_includes/dark-mode-toggle.html +202 -0
  22. data/_includes/data-loader.html +42 -0
  23. data/_includes/date-formatter.html +63 -0
  24. data/_includes/grouped-item-list.html +53 -0
  25. data/_includes/hreflang.html +58 -0
  26. data/_includes/language-switcher.html +72 -0
  27. data/_includes/print-social-links.html +23 -0
  28. data/_includes/resume-section.html +547 -0
  29. data/_includes/safe-url.html +21 -0
  30. data/_includes/shared-head.html +51 -0
  31. data/_includes/social-links.html +54 -0
  32. data/_includes/vendors/svg-icons/ATTRIBUTION.md +34 -0
  33. data/_includes/vendors/svg-icons/dev.svg +3 -0
  34. data/_includes/vendors/svg-icons/dribbble-symbol.svg +3 -0
  35. data/_includes/vendors/svg-icons/envelope.svg +4 -0
  36. data/_includes/vendors/svg-icons/facebook.svg +3 -0
  37. data/_includes/vendors/svg-icons/flickr.svg +4 -0
  38. data/_includes/vendors/svg-icons/github.svg +3 -0
  39. data/_includes/vendors/svg-icons/globe-1.svg +3 -0
  40. data/_includes/vendors/svg-icons/instagram.svg +4 -0
  41. data/_includes/vendors/svg-icons/linkedin.svg +3 -0
  42. data/_includes/vendors/svg-icons/medium.svg +3 -0
  43. data/_includes/vendors/svg-icons/phone.svg +13 -0
  44. data/_includes/vendors/svg-icons/pinterest.svg +3 -0
  45. data/_includes/vendors/svg-icons/postcard.svg +14 -0
  46. data/_includes/vendors/svg-icons/telegram.svg +3 -0
  47. data/_includes/vendors/svg-icons/whatsapp.svg +3 -0
  48. data/_includes/vendors/svg-icons/x.svg +3 -0
  49. data/_includes/vendors/svg-icons/youtube.svg +3 -0
  50. data/_layouts/default.html +65 -0
  51. data/_layouts/error.html +138 -0
  52. data/_layouts/profile.html +123 -0
  53. data/_layouts/resume.html +238 -0
  54. data/_plugins/error_pages_generator.rb +71 -0
  55. data/_plugins/json_resume_generator.rb +79 -0
  56. data/_plugins/resume_pages_generator.rb +71 -0
  57. data/_plugins/resume_validator.rb +40 -0
  58. data/_sass/_all-pages.scss +335 -0
  59. data/_sass/_base.scss +130 -0
  60. data/_sass/_dark-mode.scss +387 -0
  61. data/_sass/_layout.scss +116 -0
  62. data/_sass/_mixins.scss +136 -0
  63. data/_sass/_normalize.scss +379 -0
  64. data/_sass/_profile-page.scss +60 -0
  65. data/_sass/_resume-ltr.scss +436 -0
  66. data/_sass/_resume-rtl.scss +91 -0
  67. data/_sass/_variables.scss +45 -0
  68. data/assets/css/cv-ltr.scss +31 -0
  69. data/assets/css/cv-rtl.scss +36 -0
  70. data/assets/css/main.scss +8 -0
  71. data/assets/css/profile.scss +9 -0
  72. data/assets/favicon/resume/about.txt +6 -0
  73. data/assets/favicon/resume/android-chrome-192x192.png +0 -0
  74. data/assets/favicon/resume/android-chrome-512x512.png +0 -0
  75. data/assets/favicon/resume/apple-touch-icon.png +0 -0
  76. data/assets/favicon/resume/favicon-16x16.png +0 -0
  77. data/assets/favicon/resume/favicon-32x32.png +0 -0
  78. data/assets/favicon/resume/favicon.ico +0 -0
  79. data/assets/favicon/resume/site.webmanifest +1 -0
  80. data/bin/validate-resume +89 -0
  81. data/bin/verify +27 -0
  82. data/docs/README.md +89 -0
  83. data/docs/explanation/accessibility-decisions.md +27 -0
  84. data/docs/explanation/architecture.md +44 -0
  85. data/docs/explanation/dark-mode-approach.md +25 -0
  86. data/docs/explanation/data-driven-model.md +25 -0
  87. data/docs/explanation/multilingual-and-rtl-design.md +40 -0
  88. data/docs/how-to/add-a-language.md +57 -0
  89. data/docs/how-to/add-a-section.md +35 -0
  90. data/docs/how-to/add-a-social-platform.md +32 -0
  91. data/docs/how-to/add-a-test.md +34 -0
  92. data/docs/how-to/create-a-custom-layout.md +64 -0
  93. data/docs/how-to/enable-dark-mode.md +43 -0
  94. data/docs/how-to/link-translations-with-hreflang.md +25 -0
  95. data/docs/how-to/migrate-v0.9-to-v1.0.md +46 -0
  96. data/docs/how-to/override-locale-strings.md +51 -0
  97. data/docs/how-to/override-sass-partials.md +26 -0
  98. data/docs/how-to/proof-built-html.md +22 -0
  99. data/docs/how-to/publish-json-resume.md +38 -0
  100. data/docs/how-to/show-language-proficiency-in-header.md +13 -0
  101. data/docs/how-to/switch-resume-versions.md +42 -0
  102. data/docs/how-to/troubleshoot-builds.md +39 -0
  103. data/docs/how-to/validate-in-ci.md +38 -0
  104. data/docs/how-to/verify-accessibility.md +28 -0
  105. data/docs/reference/accessibility-coverage.md +39 -0
  106. data/docs/reference/config.md +378 -0
  107. data/docs/reference/data-schemas.md +529 -0
  108. data/docs/reference/glossary.md +39 -0
  109. data/docs/reference/includes.md +197 -0
  110. data/docs/reference/json-resume-fields.md +148 -0
  111. data/docs/reference/layouts.md +144 -0
  112. data/docs/reference/locale-keys.md +76 -0
  113. data/docs/reference/repository-map.md +83 -0
  114. data/docs/reference/sass-tokens.md +279 -0
  115. data/docs/reference/testing-suites.md +62 -0
  116. data/docs/reference/validator-cli.md +203 -0
  117. data/docs/tutorials/getting-started.md +173 -0
  118. data/lib/jekyll-theme-resume/json_resume_exporter.rb +334 -0
  119. data/lib/jekyll-theme-resume/resume_validator.rb +853 -0
  120. data/lib/jekyll-theme-resume/schemas/LICENSE.md +21 -0
  121. data/lib/jekyll-theme-resume/schemas/json_resume_v1.0.0.json +500 -0
  122. data/lib/jekyll-theme-resume.rb +21 -0
  123. metadata +371 -0
@@ -0,0 +1,43 @@
1
+ # Enable dark mode
2
+
3
+ *Audience: site owners and theme developers*
4
+
5
+ Show the dark mode toggle site-wide or on individual pages. For why the design works this way, see [dark mode approach](../explanation/dark-mode-approach.md); for the `dark_mode` option values, see the [config reference](../reference/config.md).
6
+
7
+ ## Show the toggle on every page
8
+
9
+ 1. In `_config.yml`, set:
10
+ ```yaml
11
+ dark_mode: enabled # or true
12
+ ```
13
+ 2. Restart `bundle exec jekyll serve`; changes to `_config.yml` are not picked up while it runs.
14
+ 3. Open any page. A round button appears fixed in the top-right corner of the window.
15
+
16
+ The default, `dark_mode: auto`, shows no toggle: the page follows the visitor's system setting. Any value other than `enabled` or `true` also means no toggle.
17
+
18
+ ## Show or hide the toggle on one page
19
+
20
+ Set `dark_mode` in the page's front matter. It overrides the site setting for that page:
21
+
22
+ ```yaml
23
+ ---
24
+ layout: default
25
+ dark_mode: true # show the toggle on this page; false hides it on this page
26
+ ---
27
+ ```
28
+
29
+ ## Add the toggle to a custom layout
30
+
31
+ The theme's own layouts already include the toggle. In a layout of your own, add `{% include dark-mode-toggle.html %}` inside `<body>`, and make sure `<head>` contains `{% include shared-head.html %}`. That include holds the script that applies a saved choice before the page paints, so visitors do not see a flash of the wrong theme.
32
+
33
+ ## Check that it works
34
+
35
+ 1. Click the button. The page switches to the opposite of your system's current setting: dark if your system is light, light if your system is dark.
36
+ 2. Reload the page. The choice is kept. The browser stores it in `localStorage` under the key `color-scheme`, with the value `dark` or `light`.
37
+ 3. Click the button again. The saved choice is cleared and the page follows your system setting again.
38
+ 4. To clear a saved choice by hand, delete the `color-scheme` entry in your browser's developer tools (the storage or application tab).
39
+ 5. Print the page, or open the print preview. The toggle is hidden and the page prints black on white.
40
+
41
+ ## Limits
42
+
43
+ Hiding the toggle does not force a light palette. A visitor whose system prefers dark still gets the dark palette, and a choice saved earlier still applies. The reasons are in [Dark mode approach](../explanation/dark-mode-approach.md).
@@ -0,0 +1,25 @@
1
+ # Link translations with hreflang
2
+
3
+ *Audience: site owners*
4
+
5
+ Make the language switcher and the `hreflang` tags connect the translations of a page.
6
+
7
+ Give every translation of a page the same `t_id`:
8
+
9
+ ```yaml
10
+ ---
11
+ layout: resume
12
+ lang: en
13
+ permalink: /en/cv/
14
+ t_id: resume
15
+ ---
16
+ ```
17
+
18
+ ```yaml
19
+ ---
20
+ layout: resume
21
+ lang: ar
22
+ permalink: /ar/cv/
23
+ t_id: resume
24
+ ---
25
+ ```
@@ -0,0 +1,46 @@
1
+ # Migrate from v0.9 to v1.0
2
+
3
+ *Audience: site owners*
4
+
5
+ Upgrade a site built on v0.9.0 to v1.0.0. v1.0.0 is a hard break: no aliases, shims, or fallback keys remain for the names below. Replace each one in your site.
6
+
7
+ ## 1. Replace removed names
8
+
9
+ | Removed (v0.9.0) | Replacement (v1.0.0) |
10
+ |---|---|
11
+ | `layout: resume-en` / `layout: resume-ar` | `layout: resume` + `lang: <code>` |
12
+ | `_includes/resume-section-en.html` / `-ar.html` | `_includes/resume-section.html` |
13
+ | `_includes/resume-head-en.html` / `-ar.html` | Head logic inside `_layouts/resume.html` |
14
+ | `_includes/ar-date.html` | `_includes/date-formatter.html` |
15
+ | `_data/ar/months.yml` | `months:` in `_data/locales/ar.yml` |
16
+ | `_data/error_pages.yml` | `error_pages:` in each `_data/locales/<lang>.yml` |
17
+ | `assets/css/cv.css` / `cv-ar.css` | `assets/css/cv-ltr.css` / `cv-rtl.css` |
18
+ | `active_resume_path_en` / `_ar` | `languages.<lang>.data_path` |
19
+ | `resume_en_url` / `resume_ar_url` | `languages.<lang>.url` |
20
+ | `resume_header_intro_en` / `_ar` | `languages.<lang>.header_intro` |
21
+ | `name` / `name_ar` | `languages.<lang>.name` |
22
+ | `resume_title` / `resume_title_ar` | `languages.<lang>.resume_title` |
23
+ | `contact_info.address` / `address_ar` | `languages.<lang>.address` |
24
+ | `avatar_alt_en` / `avatar_alt_ar` / `avatar_alt` | `languages.<lang>.avatar_alt` |
25
+ | `site.avatar` | `site.avatar_url` |
26
+ | `analytics.ga` | `analytics.gtag` or `analytics.gtm` |
27
+ | `resume_section.recognition` (singular) | `resume_section.recognitions` |
28
+ | `required_ruby_version >= 3.0.0` | `>= 3.3.0` |
29
+ | A plain `gem "jekyll-theme-resume"` line (no longer enough on its own) | Put the line inside `group :jekyll_plugins do ... end`, or list the theme under `plugins:` in `_config.yml`, to load its generators and validator |
30
+
31
+ ## 2. Apply the additional removals
32
+
33
+ - `languages.<lang>.name` is a plain string (`"Jane Doe"`), not the old `first` / `middle` / `last` hash.
34
+ - The site-level `lang` and `dir` keys no longer affect any layout; direction comes from the locale file and language from `page.lang` or `default_lang`.
35
+ - `font_ar_url` is gone. Override `font_url` in your site's `_data/locales/ar.yml` instead.
36
+ - Error page front matter overrides (`title_en`, `desc_en`, `title_ar`, `desc_ar`) are gone. Override `error_pages` in a site locale file instead.
37
+ - Build-time validation is now on by default. Set `validate_resume: false` to opt out (see [validator CLI reference](../reference/validator-cli.md)).
38
+
39
+ ## 3. Validate and build
40
+
41
+ Run `bundle exec validate-resume _data` and `bundle exec jekyll build`.
42
+
43
+ Watch for two silent failures:
44
+
45
+ - A leftover `layout: resume-en` page only logs a Jekyll "layout does not exist" warning and renders unstyled.
46
+ - A page whose `lang` has no `languages:` entry renders without a name, title, or resume data.
@@ -0,0 +1,51 @@
1
+ # Override locale strings
2
+
3
+ *Audience: site owners*
4
+
5
+ Change UI text, fonts, error-page copy, or accepted "present" words for a language from your consuming site, without forking the theme. The six locale files ship inside the theme gem. Jekyll reads theme data first and then deep-merges the site's `_data/` over it; the site wins. For design background, see [multilingual and RTL design](../explanation/multilingual-and-rtl-design.md).
6
+
7
+ ## Change a few strings
8
+
9
+ 1. Create `_data/locales/<lang>.yml` in your site containing only the keys to change. Nested keys merge one by one, so this file changes one heading and leaves every other Spanish string intact:
10
+ ```yaml
11
+ # consuming site: _data/locales/es.yml
12
+ ui:
13
+ section_titles:
14
+ experience: "Trayectoria"
15
+ ```
16
+
17
+ ## Replace a whole locale
18
+
19
+ 1. Copy the theme file into your site's `_data/locales/` and edit it. No fork or gem release is needed.
20
+
21
+ ## Add a new language
22
+
23
+ 1. Create a complete `_data/locales/<lang>.yml`. There is no theme file to merge with, so every key must be present.
24
+
25
+ The validator checks the merged result: see [Overriding theme locales](../reference/locale-keys.md#overriding-theme-locales).
26
+
27
+ Arrays are replaced whole, never merged. Overriding `months` or `present_values` requires the complete list; a one-item `months` array leaves the other eleven months blank.
28
+
29
+ ## Change a language's font
30
+
31
+ Fonts are locale data, not config, so no SCSS edit is needed for the CV pages. The profile page uses its own font stack, set in `_sass/_profile-page.scss`; see [Override Sass partials](override-sass-partials.md).
32
+
33
+ 1. Override `font_family` and `font_url` in your site's `_data/locales/<lang>.yml`:
34
+ ```yaml
35
+ # consuming site: _data/locales/ar.yml
36
+ font_family: "'Tajawal', sans-serif"
37
+ font_url: "https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700&display=swap"
38
+ ```
39
+
40
+ ## Change error-page copy
41
+
42
+ 1. Override `error_pages` in your site's `_data/locales/<lang>.yml`. The structure is in the [data schemas reference](../reference/data-schemas.md).
43
+
44
+ ## Accept more "present" words
45
+
46
+ 1. Override `present_values` in the site's `_data/locales/<lang>.yml`. Arrays are replaced whole, so list every word you want, including the theme's:
47
+ ```yaml
48
+ # consuming site: _data/locales/es.yml
49
+ present_values: ["present", "actualidad", "actualmente", "presente", "hoy"]
50
+ ```
51
+ 2. If you change `ui.present`, also keep that label in `present_values`; see [Present values](../reference/locale-keys.md#present-values) for why.
@@ -0,0 +1,26 @@
1
+ # Override Sass partials
2
+
3
+ *Audience: site owners*
4
+
5
+ Change theme styles from a consuming site without forking the gem. Jekyll prioritizes files in the consuming site's directory over gem theme assets, so a file in your site's `_sass/` folder with the same name as a theme partial replaces it. The partials are listed in the [Sass reference](../reference/sass-tokens.md).
6
+
7
+ ## Replace a partial
8
+
9
+ 1. Find the theme's copy: `bundle info --path jekyll-theme-resume` prints the gem's folder; the partials are in its `_sass/` folder.
10
+ 2. Copy the complete partial into your site's `_sass/` folder under the same name (for example `_sass/_dark-mode.scss`).
11
+ 3. Edit your copy and rebuild. A same-path file replaces the whole theme partial, so keep every definition the other partials depend on.
12
+
13
+ `@use "variables" with (...)` does not work as a shortcut. The partials read only `$white` and `$text_color` from `_variables.scss`, and neither is declared with `!default`, so configuring variables changes nothing. Edit a copied partial instead.
14
+
15
+ ## Change the accent color
16
+
17
+ The accent color is a CSS custom property, defined once per color scheme in `_sass/_dark-mode.scss`. Copy that partial as described above and change `--accent-color` and `--accent-hover` in each of the four blocks that define them:
18
+
19
+ 1. `:root`: the light defaults.
20
+ 2. `:root:not([data-color-scheme="light"]):not([data-theme="light"])` inside `@media (prefers-color-scheme: dark)`: the dark palette that follows the visitor's system preference.
21
+ 3. `:root[data-color-scheme="dark"]` and its aliases: the dark palette when a visitor pins dark mode.
22
+ 4. `:root[data-color-scheme="light"]` and its aliases: the light palette when a visitor pins light mode.
23
+
24
+ `--accent-hover-color` and `--social-hover-color` follow `--accent-hover`, so leave them alone. Printed pages reset every color to black and white, so the accent color does not print. Pick a dark-scheme color with enough contrast against the dark background; see [Accessibility decisions](../explanation/accessibility-decisions.md).
25
+
26
+ To change a language's font, do not edit SCSS; see [Override locale strings](override-locale-strings.md).
@@ -0,0 +1,22 @@
1
+ # Proof the built HTML and lint the Ruby
2
+
3
+ *Audience: theme developers*
4
+
5
+ Check a built site for dead links and missing assets, and run Ruby static analysis. To validate resume data instead, see [Validate resume data in CI](validate-in-ci.md).
6
+
7
+ Two development-only Rake tasks complement the data validator. Their gems are development dependencies and are never installed for theme consumers, so run these commands from a clone of the theme repository. To proof a consuming site, build the site first, then run the task from the theme clone and point it at the site's `_site` folder.
8
+
9
+ ```bash
10
+ # Dead internal links, broken #anchors, missing images/favicons, hreflang/canonical targets.
11
+ bundle exec jekyll build --source demo --destination _site
12
+ bundle exec rake proof # proofs ./_site
13
+
14
+ # Proof a consuming site (config auto-detected next to its _site/, or passed explicitly):
15
+ bundle exec rake "proof[../my-site/_site]"
16
+ bundle exec rake "proof[../my-site/_site,../my-site/_config.yml]"
17
+
18
+ # Ruby static analysis (lib/, _plugins/, bin/validate-resume, bin/check-data-keys, test/, Rakefile):
19
+ bundle exec rake rubocop
20
+ ```
21
+
22
+ What the proofer checks and its exemptions are described in [Testing suites](../reference/testing-suites.md#built-html-proofing-semantics).
@@ -0,0 +1,38 @@
1
+ # Publish the JSON Resume export
2
+
3
+ *Audience: site owners*
4
+
5
+ Serve the localized JSON Resume documents the theme generates, and make sure hosts and CV pages expose them correctly. Field mappings are in the [JSON Resume fields reference](../reference/json-resume-fields.md).
6
+
7
+ The routes the theme generates (`/<lang>/resume.json` for every language, plus `/resume.json` from the default language) are described in the [JSON Resume export reference](../reference/json-resume-fields.md).
8
+
9
+ ## 1. Check the discovery links on CV pages
10
+
11
+ Build the site and open `/en/resume.json` (for example `http://localhost:4000/en/resume.json` while serving locally). Which contact details appear depends on what the CV shows: see [Visibility and privacy](../reference/json-resume-fields.md#visibility-and-privacy), and [Contact fields by privacy setting](../reference/json-resume-fields.md#contact-fields-by-privacy-setting) for a field-by-field table. To keep address, phone and email out of the JSON while the CV still shows them, set `json_resume.privacy.export_contact_info: false`; every `social_links` entry except WhatsApp is still exported. Entries in `references.yml` are exported exactly as written, so publish only what each referee agreed to make public.
12
+
13
+ CV pages advertise only successfully generated localized exports:
14
+
15
+ ```html
16
+ <link rel="alternate" type="application/json" href="/en/resume.json" hreflang="en">
17
+ ```
18
+
19
+ The exporter records successful routes for the shared head include. Profile and error pages do not advertise exports.
20
+
21
+ ## 2. Serve the files as JSON
22
+
23
+ Jekyll emits `.json` files; the web host must serve them with `Content-Type: application/json`. This plugin cannot set HTTP headers on a static host.
24
+
25
+ ## 3. Optionally enrich skills
26
+
27
+ Add `level_label` and `keywords` to a `skills.yml` entry:
28
+
29
+ ```yaml
30
+ # A skills.yml entry; translate content in each language's data folder.
31
+ - skill: Web development
32
+ active: true
33
+ level: 4
34
+ level_label: Advanced
35
+ keywords:
36
+ - Ruby
37
+ - Jekyll
38
+ ```
@@ -0,0 +1,13 @@
1
+ # Show language proficiency in the header
2
+
3
+ *Audience: site owners*
4
+
5
+ Show a one-line summary of the languages you speak in the resume header, instead of a full Languages section.
6
+
7
+ 1. In `_config.yml`, set `resume_section.lang_header: true` and `display_header_contact_info: true`. The line sits inside the header contact block, so it does not appear without the second setting.
8
+ 2. In each language's `languages.yml`, give every language you want shown `active: true` and a `descrp_short` value (for example `descrp_short: "Native"`).
9
+ 3. Rebuild. The header shows `Language (descrp_short)` entries joined by the locale's list separator, and the standalone Languages section is hidden.
10
+
11
+ To show a full Languages section instead, set `resume_section.lang_header: false` and `resume_section.languages: true`.
12
+
13
+ The fields of `languages.yml` are in the [data schemas reference](../reference/data-schemas.md).
@@ -0,0 +1,42 @@
1
+ # Switch resume versions
2
+
3
+ *Audience: site owners*
4
+
5
+ Load a different set of resume data (for example a dated or role-specific version) for a language, without touching the data you already have.
6
+
7
+ ## Steps
8
+
9
+ 1. Put each version in its own folder under `_data/`, holding the same files as any language folder (`header.yml`, `experience.yml`, and the rest). For example:
10
+ ```text
11
+ _data/
12
+ en/ # your everyday English data
13
+ 2025-06/
14
+ PM/ # a June 2025 product-management version
15
+ Eng/ # an engineering version
16
+ ```
17
+ Folder names can contain hyphens and digits. They cannot contain a dot, because a dot separates the levels of the path in the next step.
18
+ 2. Point the language's `data_path` at the folder in `_config.yml`, separating nested folders with dots:
19
+ ```yaml
20
+ languages:
21
+ en:
22
+ data_path: "2025-06.PM" # reads _data/2025-06/PM/*.yml
23
+ ```
24
+ Only that language changes. Every other language keeps its own `data_path`.
25
+ 3. Stop the server and run `bundle exec jekyll serve` again. Changes to `_config.yml` are not picked up while the server is running.
26
+ 4. Validate the data: `bundle exec validate-resume _data`. It should print `VALIDATION SUCCESSFUL`.
27
+ 5. Open the language's CV page (for example `/en/cv/`) and confirm it shows the content of the version you chose.
28
+
29
+ To go back, set `data_path` to the original folder and restart.
30
+
31
+ ## If it does not work
32
+
33
+ - **`Data directory '.../_data/2025-06/NOPE' for language 'en' does not exist.`** The path has a typo or the folder is missing. Check each segment of the path against the folder names.
34
+ - **The page still shows the old content.** You did not restart after editing `_config.yml`.
35
+ - **The validator reports a file that exists for one language but not another.** Every language's data folder should hold the same files, so copy the missing file into the version folder.
36
+
37
+ ## Variations
38
+
39
+ - `data_path: ""` reads the files placed directly in `_data/`.
40
+ - To use a different version for each language, give each language its own `data_path`.
41
+
42
+ How the path is resolved is described in [Dynamic Data Resolution](../reference/layouts.md#dynamic-data-resolution).
@@ -0,0 +1,39 @@
1
+ # Troubleshoot builds
2
+
3
+ *Audience: site owners and theme developers*
4
+
5
+ Find the symptom you see, then work through its checks.
6
+
7
+ ## A section is not rendering on my resume
8
+
9
+ 1. `resume_section.<name>: true` is set.
10
+ 2. The name is listed in `resume_section_order`.
11
+ 3. The language's data folder (`_data/<data_path>/`) contains `<name>.yml` and its items have `active: true`.
12
+ 4. For recognitions, use the plural key `recognitions`.
13
+ 5. For the languages section, `lang_header` must not be `true`.
14
+
15
+ ## `Missing <language> counterpart: _data/ar/xyz.yml (exists in _data/en/)`
16
+
17
+ A section file exists in the reference language and not in another (or the reverse). The message names the language by its locale `ui.language_name`. Create the missing file, or delete the extra one.
18
+
19
+ ## `Locale es: Missing key(s) vs. 'en' locale: ...`
20
+
21
+ The merged `es` locale lacks keys the reference has. For a shipped language this means a site override replaced a parent hash with a non-hash value; for a site-only language, add the listed keys.
22
+
23
+ ## `No locale found for 'it'` / `Data directory '_data/it' for language 'it' does not exist.`
24
+
25
+ A language is declared in `languages:` (or `--languages`) but has no locale file or data folder. Add both, or remove the entry.
26
+
27
+ ## `languages.it has no 'data_path'`
28
+
29
+ Every `languages.<lang>` entry needs `data_path`. Use `""` to point at the data root.
30
+
31
+ ## `Date range error: end date (2022-01-31) is before start date (2023-01-01).`
32
+
33
+ Swap or correct the dates.
34
+
35
+ ## `url '...' must begin with http:// or https://`
36
+
37
+ An error, not a warning. Add the scheme, for example `https://github.com/user`.
38
+
39
+ See the [validator CLI reference](../reference/validator-cli.md) for all checks and options.
@@ -0,0 +1,38 @@
1
+ # Validate resume data in CI
2
+
3
+ *Audience: site owners and theme developers*
4
+
5
+ Gate builds on resume data validation and run the checks in GitHub Actions. To proof the built HTML instead, see [Proof the built HTML](proof-built-html.md). Options are listed in the [validator CLI reference](../reference/validator-cli.md).
6
+
7
+ ## Configure build-time validation
8
+
9
+ How build-time validation behaves is described in [Jekyll Build-Time Validation](../reference/validator-cli.md#5-jekyll-build-time-validation). To opt out or gate the build on findings, set these options in `_config.yml`:
10
+
11
+ ```yaml
12
+ # _config.yml
13
+ validate_resume: false # opt out entirely
14
+ validate_resume_strict: true # abort the build when there are errors
15
+ validate_resume_fail_on_warnings: true # with strict: also abort on warnings
16
+ ```
17
+
18
+ ## Run the validator in GitHub Actions
19
+
20
+ How this repository's own workflows run the validator and the template key checker: [Continuous integration](../reference/testing-suites.md#continuous-integration).
21
+
22
+ A consuming site can run the same check on every push:
23
+
24
+ ```yaml
25
+ # .github/workflows/validate.yml
26
+ name: Validate Resume Data
27
+ on: [push, pull_request]
28
+ jobs:
29
+ validate:
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@v7
33
+ - uses: ruby/setup-ruby@v1
34
+ with:
35
+ ruby-version: '3.4'
36
+ bundler-cache: true
37
+ - run: bundle exec validate-resume _data --fail-on-warnings
38
+ ```
@@ -0,0 +1,28 @@
1
+ # Verify accessibility
2
+
3
+ *Audience: site owners and theme developers*
4
+
5
+ Run the automated checks, then complete the manual checks before claiming conformance. Coverage details are in the [accessibility coverage reference](../reference/accessibility-coverage.md).
6
+
7
+ ## Run the automated checks
8
+
9
+ From a clone of the theme repository (these are development tasks, not part of the installed gem):
10
+
11
+ ```bash
12
+ git submodule update --init --recursive
13
+ bundle exec jekyll build --source demo --destination _site
14
+ bundle exec rake
15
+ bundle exec rake "proof[_site,demo/_config.yml]"
16
+ ```
17
+
18
+ What the automated checks cover and exclude: [accessibility coverage](../reference/accessibility-coverage.md).
19
+
20
+ ## Complete the manual checklist
21
+
22
+ Before claiming conformance for a deployed site:
23
+
24
+ 1. Check keyboard access, skip-link focus, focus visibility, and disclosure/toggle operation on profile, CV, and error pages.
25
+ 2. Inspect accessible names and reading order with a screen reader, including the extra profile email link.
26
+ 3. Test every configured locale, including Arabic and Urdu, in both light and dark modes at narrow widths and increased zoom.
27
+ 4. Measure contrast in actual rendered states and test print output for clipping and reading order.
28
+ 5. Run an accessibility scanner and manually review its results; record browser, assistive technology, date, and remaining failures.
@@ -0,0 +1,39 @@
1
+ # Accessibility coverage
2
+
3
+ *Audience: site owners and theme developers*
4
+
5
+ Reference for the accessibility features the theme implements and what its automated checks cover. The reasoning and limits are in [accessibility decisions](../explanation/accessibility-decisions.md); the verification steps are in [verify accessibility](../how-to/verify-accessibility.md).
6
+
7
+ ## Semantic Structure and Keyboard Navigation
8
+
9
+ - Resume, default, and profile layouts have a skip link to `<main id="main-content" role="main" tabindex="-1">`. Error pages inherit the default layout.
10
+ - `_sass/_base.scss` owns `.sr-only`, skip-link styles, and `:focus-visible` outlines. The skip link becomes visible on focus.
11
+ - The focus-ring and `.sr-only` rules are in [WCAG 2.2 Accessibility & High-Contrast Standards](sass-tokens.md#wcag-22-accessibility--high-contrast-standards).
12
+ - `_includes/language-switcher.html` uses native `<details>`/`<summary>` and a labelled `<nav>`. Enter/Space toggles the disclosure.
13
+
14
+ Known limits of the header, switcher and toggle behavior are in [accessibility decisions](../explanation/accessibility-decisions.md#structure-and-keyboard-navigation).
15
+
16
+ ## Labels and Locale Support
17
+
18
+ - Every social icon link has an accessible name (`aria-label`, `title`, hidden text) in the page's language, from `ui.social_labels`. The profile page's extra email icon is labelled the same way. The avatar uses locale-specific alt text from configuration. These are checked in [`test/test_rendered_site.rb`](../../test/test_rendered_site.rb).
19
+ - Direction and UI strings come from six shipped locales; fonts per locale are listed in [locale keys](locale-keys.md), and the `dir="ltr"` isolation of Latin contact details is described in [multilingual and RTL design](../explanation/multilingual-and-rtl-design.md).
20
+ - Error pages initially render the default language. Their script can change the error block and Home button based on a leading URL language prefix. The outer page and switcher remain in the server-rendered language; see [layouts.md](layouts.md#4-errorhtml-multilingual-http-error-suite).
21
+
22
+ ## Color Contrast
23
+
24
+ The following ratios are calculated from the current colors in `_sass/_dark-mode.scss`, rounded to two decimals. They describe these specific pairs, not all rendered states.
25
+
26
+ | Foreground / background | Approximate ratio | Implication |
27
+ |---|---:|---|
28
+ | `#333333` / `#ffffff` | 12.63:1 | Main light-mode text has strong contrast. |
29
+ | `#e0e0e0` / `#121212` | 14.19:1 | Main dark-mode text has strong contrast. |
30
+ | `#999999` / `#ffffff` | 2.85:1 | Current light-mode muted/footer text is below the normal-text AA threshold. |
31
+ | `#888888` / `#121212` | 5.28:1 | Current dark-mode muted text clears the normal-text AA threshold. |
32
+
33
+ Caveats for states not in this table are in [accessibility decisions](../explanation/accessibility-decisions.md#color-contrast).
34
+
35
+ ## Verification
36
+
37
+ Commands to run the checks and the manual pre-conformance checklist are in [verify accessibility](../how-to/verify-accessibility.md).
38
+
39
+ The automated checks cover data, selected template/control behavior, Ruby quality, and internal HTML links/assets. They do not perform a full accessibility audit.