bilingual-jekyll-resume-theme 0.8.0 → 1.0.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.

Potentially problematic release.


This version of bilingual-jekyll-resume-theme might be problematic. Click here for more details.

Files changed (161) hide show
  1. checksums.yaml +4 -4
  2. data/403.html +1 -1
  3. data/404.html +1 -1
  4. data/500.html +1 -1
  5. data/CHANGELOG.md +126 -2
  6. data/README.md +71 -37
  7. data/_data/locales/ar.yml +87 -0
  8. data/_data/locales/de.yml +88 -0
  9. data/_data/locales/en.yml +86 -0
  10. data/_data/locales/es.yml +88 -0
  11. data/_data/locales/fr.yml +88 -0
  12. data/_data/locales/ur.yml +88 -0
  13. data/_includes/analytics-head.html +11 -22
  14. data/_includes/avatar.html +35 -15
  15. data/_includes/dark-mode-toggle.html +56 -31
  16. data/_includes/data-loader.html +42 -0
  17. data/_includes/date-formatter.html +50 -0
  18. data/_includes/grouped-item-list.html +53 -0
  19. data/_includes/hreflang.html +15 -2
  20. data/_includes/language-switcher.html +61 -0
  21. data/_includes/main-head.html +5 -0
  22. data/_includes/print-social-links.html +29 -18
  23. data/_includes/profile-head.html +5 -0
  24. data/_includes/{resume-section-en.html → resume-section.html} +170 -256
  25. data/_includes/shared-head.html +9 -1
  26. data/_includes/social-links.html +36 -0
  27. data/_includes/vendors/lineicons-v4.0/envelope.svg +1 -1
  28. data/_layouts/default.html +21 -15
  29. data/_layouts/error.html +98 -48
  30. data/_layouts/profile.html +78 -16
  31. data/_layouts/resume.html +246 -0
  32. data/_plugins/error_pages_generator.rb +29 -3
  33. data/_plugins/resume_validator.rb +40 -0
  34. data/_sass/_all-pages.scss +43 -80
  35. data/_sass/_base.scss +56 -8
  36. data/_sass/_dark-mode.scss +29 -0
  37. data/_sass/_layout.scss +83 -7
  38. data/_sass/_mixins.scss +18 -5
  39. data/_sass/_profile-page.scss +1 -90
  40. data/_sass/_resume-ltr.scss +461 -0
  41. data/_sass/_resume-rtl.scss +35 -16
  42. data/_sass/_variables.scss +12 -0
  43. data/assets/css/cv-ltr.scss +31 -0
  44. data/assets/css/cv-rtl.scss +36 -0
  45. data/assets/css/main.scss +1 -0
  46. data/assets/css/profile.scss +3 -0
  47. data/bin/check-data-keys +66 -0
  48. data/bin/validate-resume +88 -0
  49. data/docs/ACCESSIBILITY_GUIDE.md +137 -0
  50. data/docs/COMPLETED_AUDIT.md +71 -26
  51. data/docs/CONFIG_GUIDE.md +139 -319
  52. data/docs/DATA_GUIDE.md +40 -99
  53. data/docs/INCLUDES_GUIDE.md +145 -211
  54. data/docs/LAYOUTS_GUIDE.md +96 -201
  55. data/docs/MULTILINGUAL_GUIDE.md +169 -0
  56. data/docs/PROJECT_OVERVIEW.md +124 -82
  57. data/docs/SASS_GUIDE.md +68 -32
  58. data/docs/VALIDATION_GUIDE.md +264 -0
  59. data/docs/_data/_config.demo.yml +62 -0
  60. data/docs/_data/_config.sample.yml +108 -37
  61. data/docs/_data/ar/associations.yml +13 -13
  62. data/docs/_data/ar/certifications.yml +27 -34
  63. data/docs/_data/ar/courses.yml +24 -25
  64. data/docs/_data/ar/education.yml +23 -26
  65. data/docs/_data/ar/experience.yml +33 -44
  66. data/docs/_data/ar/header.yml +2 -2
  67. data/docs/_data/ar/interests.yml +4 -4
  68. data/docs/_data/ar/languages.yml +9 -9
  69. data/docs/_data/ar/links.yml +8 -8
  70. data/docs/_data/ar/projects.yml +24 -17
  71. data/docs/_data/ar/recognitions.yml +23 -15
  72. data/docs/_data/ar/skills.yml +13 -8
  73. data/docs/_data/ar/volunteering.yml +23 -34
  74. data/docs/_data/de/associations.yml +36 -0
  75. data/docs/_data/de/certifications.yml +51 -0
  76. data/docs/_data/de/courses.yml +46 -0
  77. data/docs/_data/de/education.yml +48 -0
  78. data/docs/_data/de/experience.yml +55 -0
  79. data/docs/_data/de/header.yml +7 -0
  80. data/docs/_data/de/interests.yml +15 -0
  81. data/docs/_data/de/languages.yml +29 -0
  82. data/docs/_data/de/links.yml +24 -0
  83. data/docs/_data/de/projects.yml +44 -0
  84. data/docs/_data/de/recognitions.yml +42 -0
  85. data/docs/_data/de/skills.yml +33 -0
  86. data/docs/_data/de/volunteering.yml +44 -0
  87. data/docs/_data/en/associations.yml +15 -15
  88. data/docs/_data/en/certifications.yml +27 -34
  89. data/docs/_data/en/courses.yml +24 -25
  90. data/docs/_data/en/education.yml +23 -26
  91. data/docs/_data/en/experience.yml +32 -43
  92. data/docs/_data/en/header.yml +2 -2
  93. data/docs/_data/en/interests.yml +4 -4
  94. data/docs/_data/en/languages.yml +9 -9
  95. data/docs/_data/en/links.yml +8 -8
  96. data/docs/_data/en/projects.yml +24 -17
  97. data/docs/_data/en/recognitions.yml +23 -15
  98. data/docs/_data/en/skills.yml +13 -8
  99. data/docs/_data/en/volunteering.yml +22 -33
  100. data/docs/_data/es/associations.yml +36 -0
  101. data/docs/_data/es/certifications.yml +51 -0
  102. data/docs/_data/es/courses.yml +46 -0
  103. data/docs/_data/es/education.yml +48 -0
  104. data/docs/_data/es/experience.yml +55 -0
  105. data/docs/_data/es/header.yml +7 -0
  106. data/docs/_data/es/interests.yml +15 -0
  107. data/docs/_data/es/languages.yml +29 -0
  108. data/docs/_data/es/links.yml +24 -0
  109. data/docs/_data/es/projects.yml +44 -0
  110. data/docs/_data/es/recognitions.yml +42 -0
  111. data/docs/_data/es/skills.yml +33 -0
  112. data/docs/_data/es/volunteering.yml +44 -0
  113. data/docs/_data/fr/associations.yml +36 -0
  114. data/docs/_data/fr/certifications.yml +51 -0
  115. data/docs/_data/fr/courses.yml +46 -0
  116. data/docs/_data/fr/education.yml +48 -0
  117. data/docs/_data/fr/experience.yml +55 -0
  118. data/docs/_data/fr/header.yml +7 -0
  119. data/docs/_data/fr/interests.yml +15 -0
  120. data/docs/_data/fr/languages.yml +29 -0
  121. data/docs/_data/fr/links.yml +24 -0
  122. data/docs/_data/fr/projects.yml +44 -0
  123. data/docs/_data/fr/recognitions.yml +42 -0
  124. data/docs/_data/fr/skills.yml +33 -0
  125. data/docs/_data/fr/volunteering.yml +44 -0
  126. data/docs/_data/ur/associations.yml +36 -0
  127. data/docs/_data/ur/certifications.yml +51 -0
  128. data/docs/_data/ur/courses.yml +46 -0
  129. data/docs/_data/ur/education.yml +48 -0
  130. data/docs/_data/ur/experience.yml +55 -0
  131. data/docs/_data/ur/header.yml +7 -0
  132. data/docs/_data/ur/interests.yml +15 -0
  133. data/docs/_data/ur/languages.yml +29 -0
  134. data/docs/_data/ur/links.yml +24 -0
  135. data/docs/_data/ur/projects.yml +44 -0
  136. data/docs/_data/ur/recognitions.yml +42 -0
  137. data/docs/_data/ur/skills.yml +33 -0
  138. data/docs/_data/ur/volunteering.yml +44 -0
  139. data/docs/assets/images/sherlock-holmes.jpg +0 -0
  140. data/docs/demo/ar.md +5 -0
  141. data/docs/demo/de.md +5 -0
  142. data/docs/demo/en.md +5 -0
  143. data/docs/demo/es.md +5 -0
  144. data/docs/demo/fr.md +5 -0
  145. data/docs/demo/ur.md +5 -0
  146. data/lib/bilingual-jekyll-resume-theme/resume_validator.rb +752 -0
  147. data/lib/bilingual-jekyll-resume-theme/template_key_checker.rb +337 -0
  148. data/lib/bilingual-jekyll-resume-theme.rb +15 -0
  149. metadata +160 -21
  150. data/_data/ar/months.yml +0 -12
  151. data/_data/error_pages.yml +0 -33
  152. data/_includes/ar-date.html +0 -47
  153. data/_includes/resume-head-ar.html +0 -14
  154. data/_includes/resume-head-en.html +0 -8
  155. data/_includes/resume-section-ar.html +0 -564
  156. data/_layouts/resume-ar.html +0 -330
  157. data/_layouts/resume-en.html +0 -330
  158. data/_sass/_profile.scss +0 -2
  159. data/_sass/_resume.scss +0 -371
  160. data/assets/css/cv-ar.scss +0 -20
  161. data/assets/css/cv.scss +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc4ee64a555f7e1df4e80b33d565d82142dd29f56b23204ad071fa1c970e2388
4
- data.tar.gz: e7eb24a6509d3e10f7fd167fec77533483d8bb8e47b4c998ef6576e92291fc96
3
+ metadata.gz: 00d980490bbad955afa894d864e4379a65a6f39f371d97a6db9d1808785ccaed
4
+ data.tar.gz: b5c302a20cb5d88382151575fdb376b870969a4067d401da907cb2608f76ed3b
5
5
  SHA512:
6
- metadata.gz: c56b2e9e48c86c9da3d05f66767818277d4177eb0751c1b5906a0cf68299bf2f693e67e935bda825cb5137bf36c35e21a6ad14261994fb801a4e92be58788c97
7
- data.tar.gz: 359e5532bf3e557bcbfeaf2d5ac40b767768dbda6af88400b67e8163c38adc27d5fe8e6c3ddd1290685bc1199c006f16225096e2b64c06bfe04a2337f1dbefba
6
+ metadata.gz: 35046ae1202cd6e65a03d90313cb6dbf2ebecff360f4d1f4183a413b02b7b0da17df223b8066133ea90f3e44d5596dfb9ea2f6834ab981afa73d2165c53f480d
7
+ data.tar.gz: ab8eb568a6ca00d51c040c2282efdfddb2dc3a29634f706e6b7d9cf96e08f49b069ceddb9c83d11f2582a5fcea9ca2d978674521aa866c9ed14281630c196135
data/403.html CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  layout: error
3
3
  code: "403"
4
- title: "403 - Access Forbidden / الوصول محظور"
4
+ title: "403 - Access Forbidden"
5
5
  permalink: /403.html
6
6
  ---
data/404.html CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  layout: error
3
3
  code: "404"
4
- title: "404 - Page Not Found / الصفحة غير موجودة"
4
+ title: "404 - Page Not Found"
5
5
  permalink: /404.html
6
6
  ---
data/500.html CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  layout: error
3
3
  code: "500"
4
- title: "500 - Internal Server Error / خطأ داخلي في الخادم"
4
+ title: "500 - Internal Server Error"
5
5
  permalink: /500.html
6
6
  ---
data/CHANGELOG.md CHANGED
@@ -4,6 +4,128 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+ ## [1.0.0] - 2026-09-24
8
+
9
+ ### Added
10
+ * Add Feature 4.9, auto-generate CV/profile pages per language ([`8b473b7`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/8b473b731b3c5ecf58576db9b014d389c0ab06e5))
11
+
12
+ * Add check-data-keys, a static checker for template-vs-data key mismatches ([`f4fcfcd`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/f4fcfcd7f8aaf2fbec08295a8029c0c5cfcfa6fe))
13
+
14
+ * Add client-side site search blueprint ([`ac7f7ef`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/ac7f7ef20fc3123bf28e79f390416d10ee7bcc5f))
15
+
16
+ * Add public-domain sherlock holmes avatar image ([`c73945b`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/c73945bbbc283acee174f70435fb3e5a0a8ca993))
17
+
18
+ * Add locale system reference guides ([`d4ebf9c`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/d4ebf9c236cc26b69c27a4e13588f919b6dfaf16))
19
+
20
+ * Add locale, parity, and schema test coverage ([`1314632`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/131463239e0bb9446430c7d4f0a2fb0bff034921))
21
+
22
+ * Add sherlock holmes demo resume in six languages ([`5194795`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/5194795f82c8ab2b0fbae721803efb5e59a9376e))
23
+
24
+ * Add locale-agnostic resume layout ([`28239ec`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/28239ecb2a4039f91c8be94bf78bac8a92a89a1e))
25
+
26
+ * Add unified section dispatcher for all locales ([`23cfc0d`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/23cfc0df8c4ee240d9298ee6a3f36dd4e572b99f))
27
+
28
+ * Add universal date formatter for all six locales ([`1a830bd`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/1a830bd52a44266a0145fb7ece5432f32ac9570e))
29
+
30
+ * Add native email support to social links ([`064e2e0`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/064e2e0ee7f4d5dac86911ee30becf32562d8aaa))
31
+
32
+ * Add canonical locale dictionaries for six languages ([`20973be`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/20973be336c3b871f1278e8be655ed0e7e547ab5))
33
+
34
+ * Add v1.0.0 multilingual implementation plan and align roadmap ([`9b71b02`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/9b71b02312a15dd002f28e899fc6fd315b3cf58c))
35
+
36
+
37
+ ### Changed
38
+ * Make profile layout multilingual and data-driven ([`87d4c46`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/87d4c4680dfd8510c9dc9add4ef68619e9ed24f7))
39
+
40
+ * Include base styles in profile page stylesheet ([`193f96b`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/193f96b41ccbc64938f8c54f6096c86fde69201d))
41
+
42
+ * Bump documented version to v1.0.0, reconcile roadmap ([`1c77680`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/1c77680bca4b648104495860a0481622b6ddbee8))
43
+
44
+ * Localize error-page search box to the visitor's browser language ([`256dbb3`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/256dbb3a4239d60cb1848f6db53d97e1b15780b2))
45
+
46
+ * Extract shared grouped-item-list renderer ([`1b5a0a4`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/1b5a0a46d30f3fdc355d24ca05b7dca53d4870f4))
47
+
48
+ * Bump actions/checkout in the github-actions group ([`0809e9c`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/0809e9cda99a6dd18e1daa3a83cdee1b2da26501))
49
+
50
+ * Update minitest requirement from ~> 5.25 to ~> 6.0 ([`7fa8a8e`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/7fa8a8e8cc7ad5983394c72346ac3a8b6380b4cc))
51
+
52
+ * Record PR #220's live CI verification for Feature 3.2 ([`00e8fdf`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/00e8fdffd6ed9f43dd7586ff44bda74104e138af))
53
+
54
+ * Update agent guidance and roadmap for v1.0.0; retire implementation plan ([`0579aa3`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/0579aa3fb4bb27ad221b6f13430500bfcb3692de))
55
+
56
+ * Wire build/proof tooling to the locale-driven demo overlay ([`4f27143`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/4f2714381205c1133372aa3f3ec093eed10be0de))
57
+
58
+ * Import and adapt locale-aware resume data validator ([`834969a`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/834969a7c2e2fb2e263687b81ccf60500b0e4bca))
59
+
60
+ * Make every remaining EN/AR consumer locale-driven ([`faa5d7e`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/faa5d7e503ac0dfc63fa1cd781430334f61be465))
61
+
62
+ * Purge deprecated site.avatar, analytics.ga, and resume_dark_mode fallbacks ([`e565de0`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/e565de054705c01cf572893c1ec35470f6f46dc0))
63
+
64
+ * Align Arabic header contact icons icon-first ([`ed3e655`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/ed3e655c7d6a413c87f5efd164bb06e22346383e))
65
+
66
+ * Split resume stylesheet into locale-driven LTR/RTL layers ([`807b4e2`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/807b4e240ba83e98fb0b61e3657667ec3b729450))
67
+
68
+
69
+ ### Fixed
70
+ * Resolve 404 language and Home button from the requested URL ([`8616bb2`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/8616bb201a4246cd2dee0f5b862f39d08f7a635b))
71
+
72
+ * Require "date" so YAML.safe_load_file's permitted_classes resolves on Ruby 3.3 ([`ad4a1cd`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/ad4a1cde235784d7e9e8c0fbc17741d1b959541a))
73
+
74
+ * Render single-language error pages via remembered language preference ([`7105376`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/7105376c57763e98c977685c1a96c645bbb84505))
75
+
76
+ * Tighten URL/section/language checks, require education year ([`86b8212`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/86b82122925fbb8557d0e7e4bb763730605558f6))
77
+
78
+ * Use locale-driven font variable instead of undefined RTL tokens ([`2a08333`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/2a08333e35e1770adeb256a4844e071f3d360283))
79
+
80
+ * Fall back to standard contact info when live fields are partial ([`dbd5e00`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/dbd5e001b43ef6688aab7a0d25c883a72d378ee6))
81
+
82
+ * Declare minitest as a development dependency ([`3b51fd4`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/3b51fd4d2711de4c08ffb5b98e31f1e84a3b345e))
83
+
84
+ * Use lang_cfg.name for creator microdata ([`83c97d9`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/83c97d9b99974f8860c514840c3b8682ada3c8df))
85
+
86
+ * Update actions/checkout and action-gh-release versions for compatibility ([`d807bc3`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/d807bc3f36a30e64bad2b2e1ba2169c9990114d2))
87
+
88
+
89
+ ### Removed
90
+ * Remove non-functional error-page search form ([`73e1ac5`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/73e1ac5515b548a245fd8443078909a265a6dfb3))
91
+
92
+ ## [0.9.0] - 2026-09-21
93
+
94
+ ### Added
95
+ * Add accessible landmark roles, skip-links, and focus styles ([`a29c480`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/a29c48087c3933c9edb71722bbb00ea12e3c9ad4))
96
+
97
+
98
+ ### Changed
99
+ * Update active feature blueprints, issue mappings, and ignore rules ([`28dd0c3`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/28dd0c317cc869f966731c1732570b7592affb3e))
100
+
101
+ * Consolidate dynamic data loader into shared include component ([`ef5cc4f`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/ef5cc4fa1e979024a0fbc8efebef5105706aa1df))
102
+
103
+ * Consolidate profile styles with shared partials and remove redundant forwarder ([`0d1fbd0`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/0d1fbd04b427c4ee334d64558d6275ec64f71e9c))
104
+
105
+ * Simplify resume section conditions with direct Liquid blank checks ([`c9a6ada`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/c9a6ada2089b9b686d510edfffe0d196dca5f051))
106
+
107
+ * Clean up legacy mixins, remove IE zoom hacks, and eliminate dead table classes ([`2800d0a`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/2800d0ab1553ee14e59c6eaae441d4de83c5b35f))
108
+
109
+ * Encapsulate dark mode activation cascade into toggle include ([`405b493`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/405b4933ea0640951fd8a24a21151574bb0ab11a))
110
+
111
+ * Implement interactive bilingual language switcher ([`c56e50f`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/c56e50fa6f7e64a58ff7930a3bfb4a7275b7e134))
112
+
113
+ * Apply living-docs framework, add code comments, browser QA verified ([`d1535b9`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/d1535b9f22d79eab1cd7f4078c0db2d86a74f7b6))
114
+
115
+ * Update release notes for version automation ([`fc9ead1`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/fc9ead129df08b3698264b9da5a07378e1543aa3))
116
+
117
+ * Preserve bump-only releases in git-cliff template ([`ba334a5`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/ba334a54fa8d63aeea1a72ad646b2bb71ff6f0a7))
118
+
119
+ * Automate gem publishing and release workflow ([`f4bd096`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/f4bd096ae44bfc42cb14c9635a0e9803e297a0ba))
120
+
121
+
122
+ ### Fixed
123
+ * Render language header summary on a dedicated line ([`d3352dc`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/d3352dcb6833f8bc48d2d799774757a42325a711))
124
+
125
+
126
+ ### Removed
127
+ * Remove redundant Gem::Specification monkey-patch ([`a78efd6`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/a78efd68e70c0848f78bb5b25ab51f848c437c1d))
128
+
7
129
  ## [0.8.0] - 2026-09-19
8
130
 
9
131
  ### Added
@@ -73,8 +195,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
73
195
  ## [0.6.1] - 2026-08-21
74
196
 
75
197
  ### Changed
76
- * Version bump since v0.6.0 gemspec had incorrect version number and release was pushed to RubyGems incorrectly and it was yanked; re-releasing under v0.6.1.
77
-
198
+ * Version bump release with no structural code changes.
78
199
  ## [0.6.0] - 2026-08-21
79
200
 
80
201
  ### Added
@@ -229,8 +350,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
229
350
 
230
351
  * Initial commit (New Theme Template) ([`00af662`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/00af6628dfec7aefe0ef7d7083bf98c9713a5ffd))
231
352
 
353
+ [1.0.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.9.0...v1.0.0
354
+ [0.9.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.8.0...v0.9.0
232
355
  [0.8.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.7.0...v0.8.0
233
356
  [0.7.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.6.1...v0.7.0
357
+ [0.6.1]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.6.0...v0.6.1
234
358
  [0.6.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.5.2...v0.6.0
235
359
  [0.5.2]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.5.1...v0.5.2
236
360
  [0.5.1]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.5.0...v0.5.1
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # bilingual-jekyll-resume-theme
2
2
 
3
- [![Latest release](https://img.shields.io/github/v/release/kmutahar/bilingual-jekyll-resume-theme?display_name=tag)](https://github.com/kmutahar/bilingual-jekyll-resume-theme/releases) [![Gem Version](https://badge.fury.io/rb/bilingual-jekyll-resume-theme.svg?icon=si%3Arubygems)](https://badge.fury.io/rb/bilingual-jekyll-resume-theme)
3
+ [![CI Test Suite](https://github.com/kmutahar/bilingual-jekyll-resume-theme/actions/workflows/ci.yml/badge.svg)](https://github.com/kmutahar/bilingual-jekyll-resume-theme/actions/workflows/ci.yml) [![Latest release](https://img.shields.io/github/v/release/kmutahar/bilingual-jekyll-resume-theme?display_name=tag)](https://github.com/kmutahar/bilingual-jekyll-resume-theme/releases) [![Gem Version](https://badge.fury.io/rb/bilingual-jekyll-resume-theme.svg?icon=si%3Arubygems)](https://badge.fury.io/rb/bilingual-jekyll-resume-theme)
4
4
 
5
- A flexible Jekyll theme for creating clean, data-driven, bilingual (English & Arabic) resume/CV websites. Created and maintained by Khaldoon Mutahar. See the latest version on the [Releases page](https://github.com/kmutahar/bilingual-jekyll-resume-theme/releases).
5
+ A flexible Jekyll theme for clean, data-driven, multilingual resume/CV websites. Ships English, Arabic, Spanish, French, German, and Urdu; any other language is added from your site alone. Created and maintained by Khaldoon Mutahar. See the latest version on the [Releases page](https://github.com/kmutahar/bilingual-jekyll-resume-theme/releases).
6
6
  Inspired by and originally forked from [Joel Glovier’s resume template](https://github.com/jglovier/resume-template/). Joel’s version was a basic English-only theme with limited customization (e.g., no section reordering); this project has since evolved into a fully separate theme authored by Khaldoon.
7
7
 
8
8
  ## Features
9
9
 
10
- - **Bilingual support**: Separate layouts for English (`resume-en.html`) and Arabic (`resume-ar.html`) with full RTL support and Cairo typography
10
+ - **Multilingual support**: One layout (`resume.html`) renders every language, LTR or RTL, from per-language locale files (`_data/locales/<lang>.yml`) with localized UI strings, month names, and fonts (Cairo for Arabic, Noto Nastaliq Urdu for Urdu)
11
11
  - **Dark mode**: System preference detection (`prefers-color-scheme`) with optional interactive toggle, `localStorage` persistence, and zero-FOUC inline script
12
12
  - **Data-driven architecture**: All resume content stored in YAML files, supporting multiple data paths and versioning
13
13
  - **12 resume sections**: Experience, Education, Certifications, Courses, Volunteering, Projects, Skills, Recognition, Associations, Languages, Links, Interests
@@ -15,15 +15,17 @@ Inspired by and originally forked from [Joel Glovier’s resume template](https:
15
15
  - **Modern favicon suite**: High-resolution favicons (Apple touch icon, 32x32, 16x16, webmanifest) with subpath-safe URLs and `_config.yml` override support
16
16
  - **Print-friendly**: Optimized for PDF generation and printing with bidirectional text isolation (`dir="ltr"`) for URLs
17
17
  - **SEO ready**: Built-in support for multilingual SEO, standardized canonical tags via `jekyll-seo-tag`, sitemaps, and feeds
18
- - **Arabic month support**: Arabic date formatting included out of the box (`_data/ar/months.yml`)
18
+ - **Data validation**: `validate-resume` CLI and build-time checks for schemas, dates, URLs, and parity across every configured language
19
19
 
20
20
  ## Quick Start
21
21
 
22
22
  ### Installation
23
23
 
24
- 1. Add to your Jekyll site's `Gemfile`:
24
+ 1. Add to your Jekyll site's `Gemfile`, inside `group :jekyll_plugins`. A plain `gem "bilingual-jekyll-resume-theme"` line never requires the theme's `lib/bilingual-jekyll-resume-theme.rb`, so its bundled plugins (the error page generator and build-time validation) silently never run:
25
25
  ```ruby
26
- gem "bilingual-jekyll-resume-theme"
26
+ group :jekyll_plugins do
27
+ gem "bilingual-jekyll-resume-theme"
28
+ end
27
29
  ```
28
30
 
29
31
  2. Add to your `_config.yml`:
@@ -36,20 +38,20 @@ theme: bilingual-jekyll-resume-theme
36
38
  bundle install
37
39
  ```
38
40
 
41
+ > **Upgrading from v0.9.0?** v1.0.0 removes the `resume-en` / `resume-ar` layouts and every `*_en` / `*_ar` config key with no compatibility aliases. Follow the migration table in the [Multilingual Guide](docs/MULTILINGUAL_GUIDE.md#breaking-changes--migration-v090-to-v100).
42
+
39
43
  ### Basic Setup
40
44
 
41
- 1. **Copy sample configuration**: Use `docs/_data/_config.sample.yml` as a starting point for your `_config.yml`
45
+ 1. **Copy sample configuration**: Use `docs/_data/_config.sample.yml` as a starting point for your `_config.yml`. Keep a `languages.<lang>` entry for each language you publish and delete the rest.
42
46
 
43
- 2. **Copy sample data files**:
44
- - English data: Copy files from `docs/_data/en/` to your `_data/en/` directory (includes `header.yml` for the intro paragraph)
45
- - Arabic data: Copy files from `docs/_data/ar/` to your `_data/ar/` directory (includes `header.yml` for the Arabic intro paragraph)
47
+ 2. **Copy sample data files**: Copy each language folder you need from `docs/_data/` (`en`, `ar`, `es`, `fr`, `de`, `ur`) to your site's `_data/`. Each holds 13 files, including `header.yml` for the intro paragraph.
46
48
 
47
- 3. **Create resume pages**: Create pages using the `resume-en` and `resume-ar` layouts:
49
+ 3. **Create resume pages**: One page per language, all using the `resume` layout:
48
50
  ```yaml
49
51
  ---
50
- layout: resume-en
51
- permalink: /resume/en/
52
+ layout: resume
52
53
  lang: en
54
+ permalink: /en/cv/
53
55
  t_id: resume
54
56
  ---
55
57
  ```
@@ -68,6 +70,12 @@ This theme is fully documented. Choose the guide that fits your needs:
68
70
  ### 📘 [Configuration Guide](docs/CONFIG_GUIDE.md)
69
71
  Complete guide to `_config.yml` settings. Learn how to configure sections, contact info, social links, analytics, and more. **Start here for beginners.**
70
72
 
73
+ ### 🌐 [Multilingual Guide](docs/MULTILINGUAL_GUIDE.md)
74
+ Locale files, adding a language, overriding theme strings and fonts, RTL typography, and the **v0.9.0 to v1.0.0 migration table**.
75
+
76
+ ### ✅ [Validation Guide](docs/VALIDATION_GUIDE.md)
77
+ The `validate-resume` CLI, build-time validation, rules per section, and CI setup.
78
+
71
79
  ### 📊 [Data Structure Guide](docs/DATA_GUIDE.md)
72
80
  Detailed documentation of all 12 data file types (experience, education, skills, etc.) with examples. Learn how to structure your YAML files and what fields are required vs optional.
73
81
 
@@ -80,17 +88,26 @@ Understanding the theme's include system, how sections render, and how to add ne
80
88
  ### 🎨 [SASS/SCSS Guide](docs/SASS_GUIDE.md)
81
89
  Complete guide to the theme's styling system, how to customize colors/fonts, and how to override styles without forking the theme.
82
90
 
91
+ ### 🗺️ [Project Overview](docs/PROJECT_OVERVIEW.md)
92
+ High-level architecture summary, repository conventions, layout hierarchy, and design philosophy.
93
+
94
+ ### 📜 [Completed Historical Audit](docs/COMPLETED_AUDIT.md)
95
+ Permanent engineering record of historical bug fixes, security hardening, and architectural upgrades.
96
+
83
97
  ## Project Structure
84
98
 
85
- ```
99
+ ```text
86
100
  bilingual-jekyll-resume-theme/
87
- ├── _layouts/ # HTML templates (default, resume-en, resume-ar, profile)
88
- ├── _includes/ # Reusable components (sections, headers, analytics)
89
- ├── _sass/ # SCSS stylesheets (RTL support, print styles)
90
- ├── _data/ # Theme data (includes ar/months.yml)
91
- ├── assets/ # CSS, images, favicons
92
- └── docs/ # Documentation and sample files
93
- ├── _data/ # Sample data files (copy to your site's _data/)
101
+ ├── _layouts/ # HTML templates (default, resume, profile, error)
102
+ ├── _includes/ # Reusable components (section dispatcher, date formatter, avatar, toggles)
103
+ ├── _sass/ # SCSS (LTR main styles, RTL overrides, dark mode tokens, print styles)
104
+ ├── _plugins/ # Error page generator and build-time resume validator
105
+ ├── _data/locales/ # Locale dictionaries: en, ar, es, fr, de, ur
106
+ ├── lib/ # Gem entrypoint and validator engine
107
+ ├── bin/ # validate-resume CLI
108
+ ├── assets/ # CSS entrypoints (cv-ltr, cv-rtl), images, favicons
109
+ └── docs/ # Documentation, demo pages, and sample files
110
+ ├── _data/ # Sample config and six-language demo data (copy to your site's _data/)
94
111
  └── *.md # Documentation guides
95
112
  ```
96
113
 
@@ -98,26 +115,26 @@ bilingual-jekyll-resume-theme/
98
115
 
99
116
  ### Data Paths
100
117
 
101
- **Recommended approach (for beginners):** Use language-specific folders. The theme supports separate data paths for English and Arabic:
118
+ Each language reads its data from the folder named by `languages.<lang>.data_path`:
102
119
  ```yaml
103
- active_resume_path_en: "en" # Uses _data/en/* (recommended)
104
- active_resume_path_ar: "ar" # Uses _data/ar/* (recommended)
120
+ languages:
121
+ en:
122
+ data_path: en # _data/en/*
123
+ ar:
124
+ data_path: ar # _data/ar/*
105
125
  ```
106
126
 
107
- This is the recommended approach even if you're only using one language, as it keeps your data organized and makes it easy to add more languages later. **Advanced users:** You can place files directly in `_data/` (root) by setting these to empty strings, but this is not recommended for beginners.
127
+ Use one folder per language even for a single-language site; adding a language later is then one more folder. Dot paths (`"2025-06.v1"`) select nested, versioned datasets, and `""` reads `_data/` itself.
108
128
 
109
- See the [Configuration Guide](docs/CONFIG_GUIDE.md#data-source-active_resume_path_en_ar) for details.
129
+ See the [Configuration Guide](docs/CONFIG_GUIDE.md#3-languages) for every per-language key.
110
130
 
111
131
  ### Sample Files
112
132
 
113
- The theme includes sample data files in `docs/_data/en/` and `docs/_data/ar/` that you can copy to your site. These files contain:
114
- - Commented examples for all 12 section types
115
- - Required vs optional field explanations
116
- - Multiple examples per section
133
+ `docs/_data/{en,ar,es,fr,de,ur}/` hold a complete Sherlock Holmes demo resume in six languages, covering all 12 section types. Copy the folders you need to your site.
117
134
 
118
- ### Arabic Month Support
135
+ ### Locales
119
136
 
120
- The theme includes `_data/ar/months.yml` with Arabic month names already configured. You don't need to create this file manually—it's included in the theme.
137
+ Month names, "Present" labels, section titles, fonts, and text direction come from `_data/locales/<lang>.yml`, shipped inside the gem for all six languages. Override single strings or add a new language from your site's own `_data/locales/`; see the [Multilingual Guide](docs/MULTILINGUAL_GUIDE.md).
121
138
 
122
139
  ## Development
123
140
 
@@ -127,17 +144,32 @@ To develop this theme locally:
127
144
  # Install dependencies
128
145
  bundle install
129
146
 
130
- # Run development server
131
- bundle exec jekyll serve
147
+ # Serve the six-language demo (sample config + demo overlay pointing data_dir at docs/_data)
148
+ bundle exec jekyll serve --config docs/_data/_config.sample.yml,docs/_data/_config.demo.yml
149
+
150
+ # Build static output
151
+ bundle exec jekyll build --config docs/_data/_config.sample.yml,docs/_data/_config.demo.yml
152
+
153
+ # Validate resume data schemas and parity (CLI or Rake)
154
+ ./bin/validate-resume docs/_data
155
+ bundle exec rake validate
156
+
157
+ # Check that the theme's own templates only reference real data keys (CLI or Rake)
158
+ ./bin/check-data-keys docs/_data
159
+ bundle exec rake check_data_keys
160
+
161
+ # Validators, RuboCop, and tests together
162
+ bundle exec rake
132
163
 
133
164
  # Build the gem
134
165
  gem build bilingual-jekyll-resume-theme.gemspec
135
166
  ```
136
167
 
137
- For more details, see [WARP.md](WARP.md) or the [Development section](#development) below.
168
+ For more details on resume schema checks, see [VALIDATION_GUIDE.md](docs/VALIDATION_GUIDE.md). Contributor and agent rules are in [AGENTS.md](AGENTS.md).
138
169
 
139
170
  ## Requirements
140
171
 
172
+ - Ruby 3.3+ (standard support on Ruby 3.3, 3.4, 4.0+; Ruby <= 3.2 is EOL)
141
173
  - Jekyll 4.4+ (specified in `bilingual-jekyll-resume-theme.gemspec`)
142
174
  - Required plugins (automatically included):
143
175
  - `jekyll-feed`
@@ -157,8 +189,10 @@ The theme is available as open source under the terms of the [MIT License](LICEN
157
189
 
158
190
  - 📖 Check the [documentation guides](docs/) for detailed information
159
191
  - 🐛 Report issues on [GitHub Issues](https://github.com/kmutahar/bilingual-jekyll-resume-theme/issues)
160
- - 💡 See [project_overview.md](project_overview.md) for a high-level architecture overview
192
+ - 💡 See [PROJECT_OVERVIEW.md](docs/PROJECT_OVERVIEW.md) for a high-level architecture overview
193
+ - 📜 See [COMPLETED_AUDIT.md](docs/COMPLETED_AUDIT.md) for historical remediations and architectural decisions
161
194
 
162
195
  ---
163
196
 
164
- **Created by Khaldoon Mutahar** | Version 0.4.0 | MIT License
197
+ **Created by Khaldoon Mutahar** | MIT License
198
+
@@ -0,0 +1,87 @@
1
+ direction: "rtl"
2
+ font_family: "'Cairo', sans-serif"
3
+ font_url: "https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700;900&display=swap"
4
+ line_height: 1.6
5
+ ui:
6
+ home: "الرئيسية"
7
+ skip_to_content: "الانتقال إلى المحتوى الرئيسي"
8
+ photo_alt: "الصورة الشخصية"
9
+ present: "حتى الآن"
10
+ date_of_birth: "تاريخ الميلاد:"
11
+ languages: "اللغات:"
12
+ contact_me: "تواصل معي"
13
+ cv_button: "السيرة الذاتية"
14
+ not_looking_for_work: "لستُ باحثاً عن عمل حالياً."
15
+ social_links: "روابط التواصل"
16
+ page_last_generated_on: "تم إنشاء هذه الصفحة بتاريخ"
17
+ cv_last_generated_on: "تم إنشاء هذه السيرة الذاتية بتاريخ"
18
+ at: "في"
19
+ credential_id: "معرّف الاعتماد:"
20
+ list_separator: "، "
21
+ dark_mode_toggle: "تبديل إلى الوضع الداكن"
22
+ language_switcher: "محدد اللغة"
23
+ language_name: "العربية"
24
+ reload_page: "إعادة تحميل الصفحة"
25
+ section_titles:
26
+ experience: "الخبرات العملية"
27
+ education: "التعليم"
28
+ certifications: "التراخيص والشهادات"
29
+ courses: "الدورات"
30
+ volunteering: "الأعمال التطوعية"
31
+ projects: "المشاريع"
32
+ skills: "المهارات"
33
+ recognitions: "الجوائز والتكريم"
34
+ associations: "العضويات"
35
+ interests: "الاهتمامات الخارجية"
36
+ languages: "اللغات"
37
+ links: "روابط إضافية"
38
+ social_labels:
39
+ email: "البريد الإلكتروني"
40
+ github: "جيت هاب"
41
+ twitter: "إكس (تويتر)"
42
+ medium: "ميديام"
43
+ dribbble: "دريبل"
44
+ facebook: "فيسبوك"
45
+ linkedin: "لينكد إن"
46
+ instagram: "إنستغرام"
47
+ website: "الموقع الشخصي"
48
+ whatsapp: "واتساب"
49
+ devto: "ديف تو"
50
+ flickr: "فليكر"
51
+ pinterest: "بينتيريست"
52
+ telegram: "تيليجرام"
53
+ youtube: "يوتيوب"
54
+ error_pages:
55
+ "404":
56
+ title: "الصفحة غير موجودة"
57
+ message: "ربما تمت إزالة الصفحة التي تبحث عنها، أو تم تغيير اسمها، أو أنها غير متوفرة مؤقتاً."
58
+ "403":
59
+ title: "الوصول محظور"
60
+ message: "ليس لديك الصلاحية اللازمة للوصول إلى هذا المورد أو الدليل المطلوب."
61
+ "500":
62
+ title: "خطأ داخلي في الخادم"
63
+ message: "واجه الخادم ظرفاً غير متوقع منعه من إكمال الطلب. يرجى المحاولة مرة أخرى لاحقاً."
64
+ "503":
65
+ title: "الخدمة غير متوفرة مؤقتاً"
66
+ message: "الخادم غير قادر على معالجة الطلب حالياً بسبب الصيانة أو زيادة الحمل."
67
+ return_link: "العودة إلى السيرة الذاتية"
68
+ search_label: "البحث في الموقع"
69
+ search_placeholder: "البحث في الموقع..."
70
+ search_button: "بحث"
71
+ present_values:
72
+ - "present"
73
+ - "حتى الآن"
74
+ - "حاليًا"
75
+ months:
76
+ - "يناير"
77
+ - "فبراير"
78
+ - "مارس"
79
+ - "أبريل"
80
+ - "مايو"
81
+ - "يونيو"
82
+ - "يوليو"
83
+ - "أغسطس"
84
+ - "سبتمبر"
85
+ - "أكتوبر"
86
+ - "نوفمبر"
87
+ - "ديسمبر"
@@ -0,0 +1,88 @@
1
+ direction: "ltr"
2
+ font_family: ""
3
+ font_url: ""
4
+ line_height: 1.5
5
+ ui:
6
+ home: "Startseite"
7
+ skip_to_content: "Zum Hauptinhalt springen"
8
+ photo_alt: "Profilfoto"
9
+ present: "Heute"
10
+ date_of_birth: "Geburtsdatum:"
11
+ languages: "Sprachen:"
12
+ contact_me: "Kontaktieren Sie mich"
13
+ cv_button: "Lebenslauf"
14
+ not_looking_for_work: "Ich bin derzeit nicht auf Jobsuche."
15
+ social_links: "Soziale Links"
16
+ page_last_generated_on: "Diese Seite wurde zuletzt generiert am"
17
+ cv_last_generated_on: "Dieser Lebenslauf wurde zuletzt generiert am"
18
+ at: "um"
19
+ credential_id: "Zertifikats-ID:"
20
+ list_separator: ", "
21
+ dark_mode_toggle: "Zum Dunkelmodus wechseln"
22
+ language_switcher: "Sprachauswahl"
23
+ language_name: "Deutsch"
24
+ reload_page: "Seite neu laden"
25
+ section_titles:
26
+ experience: "Berufserfahrung"
27
+ education: "Ausbildung"
28
+ certifications: "Lizenzen & Zertifizierungen"
29
+ courses: "Kurse"
30
+ volunteering: "Ehrenamt"
31
+ projects: "Projekte"
32
+ skills: "Fähigkeiten"
33
+ recognitions: "Auszeichnungen"
34
+ associations: "Mitgliedschaften"
35
+ interests: "Interessen"
36
+ languages: "Sprachen"
37
+ links: "Weitere Links"
38
+ social_labels:
39
+ email: "E-Mail"
40
+ github: "GitHub"
41
+ twitter: "X (Twitter)"
42
+ medium: "Medium"
43
+ dribbble: "Dribbble"
44
+ facebook: "Facebook"
45
+ linkedin: "LinkedIn"
46
+ instagram: "Instagram"
47
+ website: "Webseite"
48
+ whatsapp: "WhatsApp"
49
+ devto: "Dev.to"
50
+ flickr: "Flickr"
51
+ pinterest: "Pinterest"
52
+ telegram: "Telegram"
53
+ youtube: "YouTube"
54
+ error_pages:
55
+ "404":
56
+ title: "Seite Nicht Gefunden"
57
+ message: "Die gesuchte Seite wurde möglicherweise entfernt, umbenannt oder ist vorübergehend nicht verfügbar."
58
+ "403":
59
+ title: "Zugriff Verweigert"
60
+ message: "Sie haben keine Berechtigung, auf die angeforderte Ressource oder das Verzeichnis zuzugreifen."
61
+ "500":
62
+ title: "Interner Serverfehler"
63
+ message: "Der Server hat einen unerwarteten Zustand festgestellt, der die Bearbeitung der Anfrage verhindert hat. Bitte versuchen Sie es später erneut."
64
+ "503":
65
+ title: "Dienst Nicht Verfügbar"
66
+ message: "Der Server kann die Anfrage derzeit aufgrund von Wartungsarbeiten oder Überlastung nicht bearbeiten."
67
+ return_link: "Zurück zum Lebenslauf"
68
+ search_label: "Website durchsuchen"
69
+ search_placeholder: "Website durchsuchen..."
70
+ search_button: "Suchen"
71
+ present_values:
72
+ - "present"
73
+ - "heute"
74
+ - "aktuell"
75
+ - "gegenwärtig"
76
+ months:
77
+ - "Januar"
78
+ - "Februar"
79
+ - "März"
80
+ - "April"
81
+ - "Mai"
82
+ - "Juni"
83
+ - "Juli"
84
+ - "August"
85
+ - "September"
86
+ - "Oktober"
87
+ - "November"
88
+ - "Dezember"