bilingual-jekyll-resume-theme 0.5.2 → 0.7.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.
- checksums.yaml +4 -4
- data/403.html +6 -0
- data/404.html +6 -0
- data/500.html +6 -0
- data/CHANGELOG.md +53 -1
- data/README.md +6 -3
- data/_data/error_pages.yml +33 -0
- data/_includes/analytics-body.html +0 -16
- data/_includes/analytics-head.html +10 -4
- data/_includes/dark-mode-toggle.html +177 -0
- data/_includes/print-social-links.html +18 -14
- data/_includes/resume-head-ar.html +8 -8
- data/_includes/resume-head-en.html +0 -5
- data/_includes/resume-section-ar.html +6 -6
- data/_includes/resume-section-en.html +1 -1
- data/_includes/shared-head.html +26 -4
- data/_includes/social-links.html +28 -14
- data/_includes/vendors/lineicons-v5.0/dev.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/dribbble-symbol.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/facebook.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/flickr.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/github.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/globe-1.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/instagram.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/linkedin.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/medium-alt.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/pinterest.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/telegram.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/whatsapp.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/x.svg +1 -1
- data/_includes/vendors/lineicons-v5.0/youtube.svg +1 -1
- data/_layouts/default.html +18 -3
- data/_layouts/error.html +61 -0
- data/_layouts/profile.html +3 -1
- data/_layouts/resume-ar.html +39 -7
- data/_layouts/resume-en.html +38 -6
- data/_sass/_all-pages.scss +231 -17
- data/_sass/_base.scss +19 -6
- data/_sass/_dark-mode.scss +366 -0
- data/_sass/_mixins.scss +4 -4
- data/_sass/_profile.scss +21 -10
- data/_sass/_resume-rtl.scss +6 -0
- data/_sass/_resume.scss +11 -11
- data/_sass/_variables.scss +3 -3
- data/assets/css/cv-ar.scss +1 -0
- data/assets/css/cv.scss +1 -0
- data/assets/css/main.scss +1 -0
- data/docs/CONFIG_GUIDE.md +113 -3
- data/docs/DATA_GUIDE.md +42 -1
- data/docs/INCLUDES_GUIDE.md +36 -8
- data/docs/LAYOUTS_GUIDE.md +29 -6
- data/docs/SASS_GUIDE.md +33 -0
- data/docs/_data/_config.sample.yml +12 -2
- metadata +9 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2f374813b4f778e031ea8979e3f995f8fd800e511c65418a88fc524ca8db793
|
|
4
|
+
data.tar.gz: dddb715d231b8795b4dad38fe31c5ee066400460913768bd602440e4a7c5e0ad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b8551515a7d57937c754ec17ec2f5dbc1d44eb2645aa1a449210f4004a17bc3f6a4595abd5a186a483a3e5399a3786cf4c8594ad9260bb4f7084051bcb265dba
|
|
7
|
+
data.tar.gz: 368308d395c16d9cab00ccfe36a1e2c8c18118d2727b0a7d8d668ed659b3d71a001f1c0da8ec41c83b3cb8701dc19f282275c3f1248949653f67043b003d02db
|
data/403.html
ADDED
data/404.html
ADDED
data/500.html
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,57 @@ 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
|
+
## [0.7.0] - 2026-09-12
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
* Add bilingual error suite (404, 403, 500) and reusable layout ([`4eab127`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/4eab127d8cc3a4cedccca89943482fd3a067ee14))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
* Enhance README and DATA_GUIDE with dark mode, typography, and error page details ([`8284ee7`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/8284ee7c0ffe351b823ad8ea0854b8e6d6afecd5))
|
|
15
|
+
|
|
16
|
+
* Implement universal dark mode and isolate profile layout styles ([`853a9ac`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/853a9ac1eaf11aadec62f198f6b7e9cdb2d3c209))
|
|
17
|
+
|
|
18
|
+
* Update analytics configuration to support direct measurement ID for Google Analytics 4 ([`dff8c3d`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/dff8c3d3ce3bfebf2ebb37d3ada348ed1a603f3c))
|
|
19
|
+
|
|
20
|
+
* Integrate Google Tag Manager analytics snippet into resume layouts ([`54f5c96`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/54f5c9676766c2ee04cd44a9b64b1a3472ca4d70))
|
|
21
|
+
|
|
22
|
+
* Enhance contact information handling and improve schema markup in resume layouts ([`caf726c`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/caf726c557e8289c991b6cb15acc3cc54504867e))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
* Upgrade Arabic font loading and isolate print social links ([`ca6898b`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/ca6898b883a5264dbee9088c849bfd6a00fdf079))
|
|
27
|
+
|
|
28
|
+
* Scope global svg rules and add WCAG 2.1 AA accessible social links ([`d44dcb1`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/d44dcb15360ddd3c6e5eb42bc973564f882ee177))
|
|
29
|
+
|
|
30
|
+
* Centralize modern favicon suite and resolve subdirectory 404s ([`943d565`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/943d5653d5cbfa5f6189b4975a74f2e981c6ceb1))
|
|
31
|
+
|
|
32
|
+
* Add 'dir="ltr"' attribute to URLs for better text direction handling in resume sections ([`73da095`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/73da0959f2de2b7a6585d2c1c03fc59a4fa55f65))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Removed
|
|
36
|
+
* Remove conflicting duplicate canonical tag from shared head ([`8f8b22b`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/8f8b22bfdea4e40371366db47bdddd98d412631a))
|
|
37
|
+
|
|
38
|
+
## [0.6.1] - 2026-08-21
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
* 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.
|
|
42
|
+
|
|
43
|
+
## [0.6.0] - 2026-08-21
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
* Add CLAUDE.md for AI coding assistant guidance and project documentation ([`d68bb03`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/d68bb031043eb88dc7bc6eaaa30a00867f7f7afc))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
* Add dark mode toggle with system preference detection ([`2dcb813`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/2dcb8135817d05f97d8705ea09bfb326d244cd3d))
|
|
51
|
+
|
|
52
|
+
* Enhance CLAUDE.md with comprehensive project documentation and guidance for AI assistants ([`b3facba`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/b3facba6cac2caf853d3f70243dd8a9a2f87ab53))
|
|
53
|
+
|
|
54
|
+
* Revise SECURITY.md with version support and monitoring ([`34c78a0`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/34c78a08ee5e96fd0667b9896c07f6e18e380dd0))
|
|
55
|
+
|
|
56
|
+
* Potential fix for code scanning alert no. 1: Workflow does not contain permissions ([`915f9e7`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/915f9e77982a962e3eda844263d65b5a4ffb849b))
|
|
57
|
+
|
|
7
58
|
## [0.5.2] - 2026-05-09
|
|
8
59
|
|
|
9
60
|
### Added
|
|
@@ -143,7 +194,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
143
194
|
|
|
144
195
|
* Initial commit (New Theme Template) ([`00af662`](https://github.com/kmutahar/bilingual-jekyll-resume-theme/commit/00af6628dfec7aefe0ef7d7083bf98c9713a5ffd))
|
|
145
196
|
|
|
146
|
-
[0.
|
|
197
|
+
[0.6.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.5.2...v0.6.0
|
|
198
|
+
[0.5.2]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.5.1...v0.5.2
|
|
147
199
|
[0.5.1]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.5.0...v0.5.1
|
|
148
200
|
[0.5.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.4.0...v0.5.0
|
|
149
201
|
[0.4.0]: https://github.com/kmutahar/bilingual-jekyll-resume-theme/compare/v0.3.1...v0.4.0
|
data/README.md
CHANGED
|
@@ -7,11 +7,14 @@ Inspired by and originally forked from [Joel Glovier’s resume template](https:
|
|
|
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
|
|
10
|
+
- **Bilingual support**: Separate layouts for English (`resume-en.html`) and Arabic (`resume-ar.html`) with full RTL support and Cairo typography
|
|
11
|
+
- **Dark mode**: System preference detection (`prefers-color-scheme`) with optional interactive toggle, `localStorage` persistence, and zero-FOUC inline script
|
|
11
12
|
- **Data-driven architecture**: All resume content stored in YAML files, supporting multiple data paths and versioning
|
|
12
13
|
- **12 resume sections**: Experience, Education, Certifications, Courses, Volunteering, Projects, Skills, Recognition, Associations, Languages, Links, Interests
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
14
|
+
- **WCAG 2.1 AA Accessible**: Full screen reader and keyboard accessibility with `.sr-only` labels and declarative aria attributes
|
|
15
|
+
- **Modern favicon suite**: High-resolution favicons (Apple touch icon, 32x32, 16x16, webmanifest) with subpath-safe URLs and `_config.yml` override support
|
|
16
|
+
- **Print-friendly**: Optimized for PDF generation and printing with bidirectional text isolation (`dir="ltr"`) for URLs
|
|
17
|
+
- **SEO ready**: Built-in support for multilingual SEO, standardized canonical tags via `jekyll-seo-tag`, sitemaps, and feeds
|
|
15
18
|
- **Arabic month support**: Arabic date formatting included out of the box (`_data/ar/months.yml`)
|
|
16
19
|
|
|
17
20
|
## Quick Start
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Bilingual Error Page Definitions
|
|
2
|
+
# bilingual-jekyll-resume-theme
|
|
3
|
+
# Centralized English and Arabic content for HTTP error pages.
|
|
4
|
+
|
|
5
|
+
labels:
|
|
6
|
+
home: "Home / الرئيسية"
|
|
7
|
+
resume_en: "Resume (EN)"
|
|
8
|
+
resume_ar: "السيرة الذاتية (عربي)"
|
|
9
|
+
reload: "Reload Page / إعادة تحميل الصفحة"
|
|
10
|
+
|
|
11
|
+
"404":
|
|
12
|
+
title_en: "Page Not Found"
|
|
13
|
+
desc_en: "The page you are looking for might have been removed, had its name changed, or is temporarily unavailable."
|
|
14
|
+
title_ar: "الصفحة غير موجودة"
|
|
15
|
+
desc_ar: "ربما تمت إزالة الصفحة التي تبحث عنها، أو تم تغيير اسمها، أو أنها غير متوفرة مؤقتاً."
|
|
16
|
+
|
|
17
|
+
"403":
|
|
18
|
+
title_en: "Access Forbidden"
|
|
19
|
+
desc_en: "You do not have permission to access the requested resource or directory."
|
|
20
|
+
title_ar: "الوصول محظور"
|
|
21
|
+
desc_ar: "ليس لديك الصلاحية اللازمة للوصول إلى هذا المورد أو الدليل المطلوب."
|
|
22
|
+
|
|
23
|
+
"500":
|
|
24
|
+
title_en: "Internal Server Error"
|
|
25
|
+
desc_en: "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later."
|
|
26
|
+
title_ar: "خطأ داخلي في الخادم"
|
|
27
|
+
desc_ar: "واجه الخادم ظرفاً غير متوقع منعه من إكمال الطلب. يرجى المحاولة مرة أخرى لاحقاً."
|
|
28
|
+
|
|
29
|
+
"503":
|
|
30
|
+
title_en: "Service Unavailable"
|
|
31
|
+
desc_en: "The server is currently unable to handle the request due to maintenance or capacity overload."
|
|
32
|
+
title_ar: "الخدمة غير متوفرة مؤقتاً"
|
|
33
|
+
desc_ar: "الخادم غير قادر على معالجة الطلب حالياً بسبب الصيانة أو زيادة الحمل."
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
{%- if site.analytics.gtm -%}
|
|
2
|
-
|
|
3
2
|
<!-- Google Tag Manager (noscript) -->
|
|
4
3
|
<noscript>
|
|
5
4
|
<iframe
|
|
@@ -10,19 +9,4 @@
|
|
|
10
9
|
</iframe>
|
|
11
10
|
</noscript>
|
|
12
11
|
<!-- End Google Tag Manager (noscript) -->
|
|
13
|
-
|
|
14
|
-
{%- else -%}
|
|
15
|
-
|
|
16
|
-
{%- if site.analytics.ga -%}
|
|
17
|
-
|
|
18
|
-
{%- comment -%}
|
|
19
|
-
No Google Analytics gtag.js exists for body so this section will return a blank.
|
|
20
|
-
{%- endcomment -%}
|
|
21
|
-
|
|
22
|
-
{%- endif -%}
|
|
23
|
-
|
|
24
|
-
{%- else -%}
|
|
25
|
-
|
|
26
|
-
<!-- No Analytics Added -->
|
|
27
|
-
|
|
28
12
|
{%- endif -%}
|
|
@@ -16,15 +16,21 @@
|
|
|
16
16
|
f.parentNode.insertBefore(j, f);
|
|
17
17
|
})(window, document, 'script', 'dataLayer', '{{ site.analytics.gtm }}');
|
|
18
18
|
</script>
|
|
19
|
-
|
|
20
19
|
<!-- End Google Tag Manager -->
|
|
21
20
|
|
|
22
21
|
{%- else -%}
|
|
23
22
|
|
|
24
|
-
{%-
|
|
23
|
+
{%- assign ga_id = nil -%}
|
|
24
|
+
{%- if site.analytics.gtag and site.analytics.gtag != "" -%}
|
|
25
|
+
{%- assign ga_id = site.analytics.gtag -%}
|
|
26
|
+
{%- elsif site.analytics.ga and site.analytics.ga != true and site.analytics.ga != "" -%}
|
|
27
|
+
{%- assign ga_id = site.analytics.ga -%}
|
|
28
|
+
{%- endif -%}
|
|
29
|
+
|
|
30
|
+
{%- if ga_id -%}
|
|
25
31
|
|
|
26
32
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
27
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id={{
|
|
33
|
+
<script async src="https://www.googletagmanager.com/gtag/js?id={{ ga_id }}"></script>
|
|
28
34
|
<script>
|
|
29
35
|
window.dataLayer = window.dataLayer || [];
|
|
30
36
|
|
|
@@ -33,7 +39,7 @@
|
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
gtag('js', new Date());
|
|
36
|
-
gtag('config', '{{
|
|
42
|
+
gtag('config', '{{ ga_id }}');
|
|
37
43
|
</script>
|
|
38
44
|
|
|
39
45
|
{%- endif -%}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<!-- Dark Mode Toggle Button (Two-state: System Default vs Pinned Override) -->
|
|
2
|
+
<button
|
|
3
|
+
id="dark-mode-toggle"
|
|
4
|
+
class="dark-mode-toggle no-print"
|
|
5
|
+
type="button"
|
|
6
|
+
aria-label="Switch to dark mode"
|
|
7
|
+
title="Switch to dark mode"
|
|
8
|
+
aria-pressed="false"
|
|
9
|
+
data-pinned="false"
|
|
10
|
+
>
|
|
11
|
+
<!-- Sun Icon: Visible in dark mode / indicates switching to light mode -->
|
|
12
|
+
<svg
|
|
13
|
+
class="dark-mode-icon dark-mode-icon-sun"
|
|
14
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
15
|
+
width="20"
|
|
16
|
+
height="20"
|
|
17
|
+
viewBox="0 0 24 24"
|
|
18
|
+
fill="none"
|
|
19
|
+
stroke="currentColor"
|
|
20
|
+
stroke-width="2"
|
|
21
|
+
stroke-linecap="round"
|
|
22
|
+
stroke-linejoin="round"
|
|
23
|
+
aria-hidden="true"
|
|
24
|
+
focusable="false"
|
|
25
|
+
>
|
|
26
|
+
<circle cx="12" cy="12" r="5"></circle>
|
|
27
|
+
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|
28
|
+
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|
29
|
+
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|
30
|
+
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|
31
|
+
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|
32
|
+
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|
33
|
+
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|
34
|
+
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|
35
|
+
</svg>
|
|
36
|
+
|
|
37
|
+
<!-- Moon Icon: Visible in light mode / indicates switching to dark mode -->
|
|
38
|
+
<svg
|
|
39
|
+
class="dark-mode-icon dark-mode-icon-moon"
|
|
40
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
41
|
+
width="20"
|
|
42
|
+
height="20"
|
|
43
|
+
viewBox="0 0 24 24"
|
|
44
|
+
fill="none"
|
|
45
|
+
stroke="currentColor"
|
|
46
|
+
stroke-width="2"
|
|
47
|
+
stroke-linecap="round"
|
|
48
|
+
stroke-linejoin="round"
|
|
49
|
+
aria-hidden="true"
|
|
50
|
+
focusable="false"
|
|
51
|
+
>
|
|
52
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
|
53
|
+
</svg>
|
|
54
|
+
</button>
|
|
55
|
+
|
|
56
|
+
<script>
|
|
57
|
+
(function () {
|
|
58
|
+
var toggleBtn = document.getElementById('dark-mode-toggle');
|
|
59
|
+
if (!toggleBtn) return;
|
|
60
|
+
|
|
61
|
+
var metaTheme = document.querySelector('meta[name="color-scheme"]');
|
|
62
|
+
|
|
63
|
+
function getSystemTheme() {
|
|
64
|
+
if (window.matchMedia) {
|
|
65
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
66
|
+
}
|
|
67
|
+
return 'light';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getSavedTheme() {
|
|
71
|
+
try {
|
|
72
|
+
var val = localStorage.getItem('color-scheme');
|
|
73
|
+
if (val === 'dark' || val === 'light') {
|
|
74
|
+
return val;
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
} catch (e) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isArabicRTL() {
|
|
83
|
+
var docEl = document.documentElement;
|
|
84
|
+
var dir = docEl.getAttribute('dir');
|
|
85
|
+
var lang = docEl.getAttribute('lang') || docEl.lang;
|
|
86
|
+
return dir === 'rtl' || lang === 'ar';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function syncState() {
|
|
90
|
+
var saved = getSavedTheme();
|
|
91
|
+
if (saved !== null) {
|
|
92
|
+
document.documentElement.setAttribute('data-color-scheme', saved);
|
|
93
|
+
document.documentElement.setAttribute('data-theme', saved);
|
|
94
|
+
if (metaTheme) {
|
|
95
|
+
metaTheme.setAttribute('content', saved);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
document.documentElement.removeAttribute('data-color-scheme');
|
|
99
|
+
document.documentElement.removeAttribute('data-theme');
|
|
100
|
+
if (metaTheme) {
|
|
101
|
+
metaTheme.setAttribute('content', 'light dark');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function updateUI() {
|
|
107
|
+
var saved = getSavedTheme();
|
|
108
|
+
var isPinned = (saved !== null);
|
|
109
|
+
var effectiveTheme = isPinned ? saved : getSystemTheme();
|
|
110
|
+
var isRTL = isArabicRTL();
|
|
111
|
+
var label = '';
|
|
112
|
+
|
|
113
|
+
toggleBtn.setAttribute('data-pinned', isPinned ? 'true' : 'false');
|
|
114
|
+
toggleBtn.setAttribute('aria-pressed', isPinned ? 'true' : 'false');
|
|
115
|
+
toggleBtn.setAttribute('data-current-theme', effectiveTheme);
|
|
116
|
+
|
|
117
|
+
if (isPinned) {
|
|
118
|
+
label = isRTL
|
|
119
|
+
? 'إعادة ضبط المظهر إلى الوضع التلقائي للنظام'
|
|
120
|
+
: 'Reset to system theme';
|
|
121
|
+
} else {
|
|
122
|
+
var nextTheme = (effectiveTheme === 'dark') ? 'light' : 'dark';
|
|
123
|
+
if (isRTL) {
|
|
124
|
+
label = (nextTheme === 'dark')
|
|
125
|
+
? 'تبديل إلى الوضع الداكن'
|
|
126
|
+
: 'تبديل إلى الوضع الفاتح';
|
|
127
|
+
} else {
|
|
128
|
+
label = (nextTheme === 'dark')
|
|
129
|
+
? 'Switch to dark mode'
|
|
130
|
+
: 'Switch to light mode';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
toggleBtn.setAttribute('aria-label', label);
|
|
135
|
+
toggleBtn.setAttribute('title', label);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function toggleTheme() {
|
|
139
|
+
var saved = getSavedTheme();
|
|
140
|
+
if (saved !== null) {
|
|
141
|
+
// Currently pinned -> reset to system default
|
|
142
|
+
try {
|
|
143
|
+
localStorage.removeItem('color-scheme');
|
|
144
|
+
} catch (e) {}
|
|
145
|
+
syncState();
|
|
146
|
+
} else {
|
|
147
|
+
// Currently unpinned -> pin opposite of current system setting
|
|
148
|
+
var systemTheme = getSystemTheme();
|
|
149
|
+
var targetTheme = (systemTheme === 'dark') ? 'light' : 'dark';
|
|
150
|
+
try {
|
|
151
|
+
localStorage.setItem('color-scheme', targetTheme);
|
|
152
|
+
} catch (e) {}
|
|
153
|
+
syncState();
|
|
154
|
+
}
|
|
155
|
+
updateUI();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
toggleBtn.addEventListener('click', toggleTheme);
|
|
159
|
+
|
|
160
|
+
if (window.matchMedia) {
|
|
161
|
+
var darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
162
|
+
var mqListener = function () {
|
|
163
|
+
if (!getSavedTheme()) {
|
|
164
|
+
updateUI();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
if (darkQuery.addEventListener) {
|
|
168
|
+
darkQuery.addEventListener('change', mqListener);
|
|
169
|
+
} else if (darkQuery.addListener) {
|
|
170
|
+
darkQuery.addListener(mqListener);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
syncState();
|
|
175
|
+
updateUI();
|
|
176
|
+
})();
|
|
177
|
+
</script>
|
|
@@ -1,75 +1,79 @@
|
|
|
1
1
|
<!-- and guess where these are defined? Yup, you guessed it: the _config.yml file -->
|
|
2
2
|
{% if site.resume_print_social_links %}
|
|
3
|
+
{% assign is_ar = false %}
|
|
4
|
+
{% if page.layout == "resume-ar" or page.lang == "ar" or page.language == "ar" or layout.lang == "ar" %}
|
|
5
|
+
{% assign is_ar = true %}
|
|
6
|
+
{% endif %}
|
|
3
7
|
<ul>
|
|
4
8
|
|
|
5
9
|
{% if site.social_links.github %}
|
|
6
10
|
<!-- GitHub link -->
|
|
7
|
-
<li><strong>
|
|
11
|
+
<li><strong>{% if is_ar %}جيت هاب (GitHub){% else %}GitHub{% endif %}</strong>: <span dir="ltr">{{ site.social_links.github }}</span></li>
|
|
8
12
|
{% endif %}
|
|
9
13
|
|
|
10
14
|
{% if site.social_links.twitter %}
|
|
11
15
|
<!-- Twitter link -->
|
|
12
|
-
<li><strong>Twitter</strong>: {{ site.social_links.twitter }}</li>
|
|
16
|
+
<li><strong>{% if is_ar %}إكس / تويتر (X / Twitter){% else %}X (Twitter){% endif %}</strong>: <span dir="ltr">{{ site.social_links.twitter }}</span></li>
|
|
13
17
|
{% endif %}
|
|
14
18
|
|
|
15
19
|
{% if site.social_links.medium %}
|
|
16
20
|
<!-- Medium link -->
|
|
17
|
-
<li><strong>Medium</strong>: {{ site.social_links.medium }}</li>
|
|
21
|
+
<li><strong>{% if is_ar %}ميديام (Medium){% else %}Medium{% endif %}</strong>: <span dir="ltr">{{ site.social_links.medium }}</span></li>
|
|
18
22
|
{% endif %}
|
|
19
23
|
|
|
20
24
|
{% if site.social_links.dribbble %}
|
|
21
25
|
<!-- Dribbble link -->
|
|
22
|
-
<li><strong>Dribbble</strong>: {{ site.social_links.dribbble }}</li>
|
|
26
|
+
<li><strong>{% if is_ar %}دريبل (Dribbble){% else %}Dribbble{% endif %}</strong>: <span dir="ltr">{{ site.social_links.dribbble }}</span></li>
|
|
23
27
|
{% endif %}
|
|
24
28
|
|
|
25
29
|
{% if site.social_links.facebook %}
|
|
26
30
|
<!-- Facebook link -->
|
|
27
|
-
<li><strong>Facebook</strong>: {{ site.social_links.facebook }}</li>
|
|
31
|
+
<li><strong>{% if is_ar %}فيسبوك (Facebook){% else %}Facebook{% endif %}</strong>: <span dir="ltr">{{ site.social_links.facebook }}</span></li>
|
|
28
32
|
{% endif %}
|
|
29
33
|
|
|
30
34
|
{% if site.social_links.linkedin %}
|
|
31
35
|
<!-- LinkedIn link -->
|
|
32
|
-
<li><strong>LinkedIn</strong>: {{ site.social_links.linkedin }}</li>
|
|
36
|
+
<li><strong>{% if is_ar %}لينكد إن (LinkedIn){% else %}LinkedIn{% endif %}</strong>: <span dir="ltr">{{ site.social_links.linkedin }}</span></li>
|
|
33
37
|
{% endif %}
|
|
34
38
|
|
|
35
39
|
{% if site.social_links.instagram %}
|
|
36
40
|
<!-- Instagram link -->
|
|
37
|
-
<li><strong>Instagram</strong>: {{ site.social_links.instagram }}</li>
|
|
41
|
+
<li><strong>{% if is_ar %}إنستغرام (Instagram){% else %}Instagram{% endif %}</strong>: <span dir="ltr">{{ site.social_links.instagram }}</span></li>
|
|
38
42
|
{% endif %}
|
|
39
43
|
|
|
40
44
|
{% if site.social_links.website %}
|
|
41
45
|
<!-- Website link -->
|
|
42
|
-
<li><strong>Website</strong>: {{ site.social_links.website }}</li>
|
|
46
|
+
<li><strong>{% if is_ar %}الموقع الشخصي (Website){% else %}Website{% endif %}</strong>: <span dir="ltr">{{ site.social_links.website }}</span></li>
|
|
43
47
|
{% endif %}
|
|
44
48
|
|
|
45
49
|
{% if site.social_links.whatsapp %}
|
|
46
50
|
<!-- Whatsapp link -->
|
|
47
|
-
<li><strong>
|
|
51
|
+
<li><strong>{% if is_ar %}واتساب (WhatsApp){% else %}WhatsApp{% endif %}</strong>: <span dir="ltr">{{ site.social_links.whatsapp }}</span></li>
|
|
48
52
|
{% endif %}
|
|
49
53
|
|
|
50
54
|
{% if site.social_links.devto %}
|
|
51
55
|
<!-- Devto link -->
|
|
52
|
-
<li><strong>
|
|
56
|
+
<li><strong>{% if is_ar %}ديف تو (Dev.to){% else %}Dev.to{% endif %}</strong>: <span dir="ltr">{{ site.social_links.devto }}</span></li>
|
|
53
57
|
{% endif %}
|
|
54
58
|
|
|
55
59
|
{% if site.social_links.flickr %}
|
|
56
60
|
<!-- Flickr link -->
|
|
57
|
-
<li><strong>Flickr</strong>: {{ site.social_links.flickr }}</li>
|
|
61
|
+
<li><strong>{% if is_ar %}فليكر (Flickr){% else %}Flickr{% endif %}</strong>: <span dir="ltr">{{ site.social_links.flickr }}</span></li>
|
|
58
62
|
{% endif %}
|
|
59
63
|
|
|
60
64
|
{% if site.social_links.pinterest %}
|
|
61
65
|
<!-- Pinterest link -->
|
|
62
|
-
<li><strong>Pinterest</strong>: {{ site.social_links.pinterest }}</li>
|
|
66
|
+
<li><strong>{% if is_ar %}بينتيريست (Pinterest){% else %}Pinterest{% endif %}</strong>: <span dir="ltr">{{ site.social_links.pinterest }}</span></li>
|
|
63
67
|
{% endif %}
|
|
64
68
|
|
|
65
69
|
{% if site.social_links.telegram %}
|
|
66
70
|
<!-- Telegram link -->
|
|
67
|
-
<li><strong>Telegram</strong>: {{ site.social_links.telegram }}</li>
|
|
71
|
+
<li><strong>{% if is_ar %}تيليجرام (Telegram){% else %}Telegram{% endif %}</strong>: <span dir="ltr">{{ site.social_links.telegram }}</span></li>
|
|
68
72
|
{% endif %}
|
|
69
73
|
|
|
70
74
|
{% if site.social_links.youtube %}
|
|
71
75
|
<!-- Youtube link -->
|
|
72
|
-
<li><strong>
|
|
76
|
+
<li><strong>{% if is_ar %}يوتيوب (YouTube){% else %}YouTube{% endif %}</strong>: <span dir="ltr">{{ site.social_links.youtube }}</span></li>
|
|
73
77
|
{% endif %}
|
|
74
78
|
|
|
75
79
|
</ul>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
{% if site.
|
|
2
|
-
<!-- Arabic
|
|
3
|
-
<link
|
|
1
|
+
{% if site.font_ar_url %}
|
|
2
|
+
<!-- Custom Arabic Font Stylesheet -->
|
|
3
|
+
<link rel="stylesheet" href="{{ site.font_ar_url | relative_url }}">
|
|
4
|
+
{% elsif site.disable_google_fonts != true and site.resume_theme != 'no-custom-fonts' %}
|
|
5
|
+
<!-- Arabic-friendly font (Cairo) with preconnect for performance -->
|
|
6
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
7
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
8
|
+
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700;900&display=swap" rel="stylesheet">
|
|
4
9
|
{% endif %}
|
|
5
10
|
|
|
6
11
|
<link rel="stylesheet" type="text/css" href="{{ 'assets/css/cv-ar.css' | relative_url }}">
|
|
7
12
|
|
|
8
|
-
<!-- favicons generated by favicon.io -->
|
|
9
|
-
<link rel="apple-touch-icon" sizes="180x180" href="{{ 'assets/favicon/resume/apple-touch-icon.png' | relative_url }}">
|
|
10
|
-
<link rel="icon" type="image/png" sizes="32x32" href="{{ 'assets/favicon/resume/favicon-32x32.png' | relative_url }}">
|
|
11
|
-
<link rel="icon" type="image/png" sizes="16x16" href="{{ 'assets/favicon/resume/favicon-16x16.png' | relative_url }}">
|
|
12
|
-
<link rel="manifest" href="{{ 'assets/favicon/resume/site.webmanifest' | relative_url }}">
|
|
13
13
|
|
|
14
14
|
{% include hreflang.html %}
|
|
@@ -4,10 +4,5 @@
|
|
|
4
4
|
|
|
5
5
|
<link rel="stylesheet" type="text/css" href="{{ 'assets/css/cv.css' | relative_url }}">
|
|
6
6
|
|
|
7
|
-
<!-- favicons generated by favicon.io -->
|
|
8
|
-
<link rel="apple-touch-icon" sizes="180x180" href="{{ 'assets/favicon/resume/apple-touch-icon.png' | relative_url }}">
|
|
9
|
-
<link rel="icon" type="image/png" sizes="32x32" href="{{ 'assets/favicon/resume/favicon-32x32.png' | relative_url }}">
|
|
10
|
-
<link rel="icon" type="image/png" sizes="16x16" href="{{ 'assets/favicon/resume/favicon-16x16.png' | relative_url }}">
|
|
11
|
-
<link rel="manifest" href="{{ 'assets/favicon/resume/site.webmanifest' | relative_url }}">
|
|
12
7
|
|
|
13
8
|
{% include hreflang.html %}
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
<span class="resume-item-copy-license-cert-id">معرّف الاعتماد:
|
|
100
100
|
{% if certification.credential_url %}
|
|
101
101
|
<a href="{{ certification.credential_url }}" target="_blank" rel="noopener nofollow noreferrer">{{ certification.credential_id }}</a>
|
|
102
|
-
<span class="print-only-inline"> ({{ certification.credential_url }})</span>
|
|
102
|
+
<span class="print-only-inline" dir="ltr"> ({{ certification.credential_url }})</span>
|
|
103
103
|
</span>
|
|
104
104
|
{% else %}
|
|
105
105
|
{{ certification.credential_id }}
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
<p class="resume-item-copy">معرّف الاعتماد:
|
|
137
137
|
{% if course.credential_url %}
|
|
138
138
|
<a href="{{ course.credential_url }}" target="_blank" rel="noopener nofollow noreferrer">{{ course.credential_id }}</a>
|
|
139
|
-
<span class="print-only-inline"> ({{ course.credential_url }})</span>
|
|
139
|
+
<span class="print-only-inline" dir="ltr"> ({{ course.credential_url }})</span>
|
|
140
140
|
{% else %}
|
|
141
141
|
{{ course.credential_id }}
|
|
142
142
|
{% endif %}
|
|
@@ -210,7 +210,7 @@
|
|
|
210
210
|
</h3>
|
|
211
211
|
|
|
212
212
|
{% if project.url %}
|
|
213
|
-
<span class="print-only-inline" style="display: inline;"> {{ project.url }}</span>
|
|
213
|
+
<span class="print-only-inline" dir="ltr" style="display: inline;"> {{ project.url }}</span>
|
|
214
214
|
{% endif %}
|
|
215
215
|
|
|
216
216
|
<h4 class="resume-item-details" itemprop="description">{{ project.role }} • {{ project.duration }}</h4>
|
|
@@ -281,7 +281,7 @@
|
|
|
281
281
|
</h3>
|
|
282
282
|
|
|
283
283
|
{% if association.url %}
|
|
284
|
-
<span class="print-only-inline" style="display: inline;"> {{ association.url }}</span>
|
|
284
|
+
<span class="print-only-inline" dir="ltr" style="display: inline;"> {{ association.url }}</span>
|
|
285
285
|
{% endif %}
|
|
286
286
|
|
|
287
287
|
<h4 class="resume-item-details" itemprop="description">{{ association.role }} • {{ association.year }}</h4>
|
|
@@ -359,8 +359,8 @@
|
|
|
359
359
|
{% for link in resume_data.links %}
|
|
360
360
|
{% if link.active == true %}
|
|
361
361
|
<li>
|
|
362
|
-
<a href={{ link.url }} target="_blank" rel="noopener nofollow noreferrer" itemprop="url">{{ link.description }}</a>
|
|
363
|
-
<span class="print-only-inline"> {{ link.url }}</span>
|
|
362
|
+
<a href="{{ link.url }}" target="_blank" rel="noopener nofollow noreferrer" itemprop="url">{{ link.description }}</a>
|
|
363
|
+
<span class="print-only-inline" dir="ltr"> {{ link.url }}</span>
|
|
364
364
|
</li>
|
|
365
365
|
{% endif %}
|
|
366
366
|
{% endfor %}
|
|
@@ -358,7 +358,7 @@
|
|
|
358
358
|
{% for link in resume_data.links %}
|
|
359
359
|
{% if link.active == true %}
|
|
360
360
|
<li>
|
|
361
|
-
<a href={{ link.url }} target="_blank" rel="noopener nofollow noreferrer" itemprop="url">{{ link.description }}</a>
|
|
361
|
+
<a href="{{ link.url }}" target="_blank" rel="noopener nofollow noreferrer" itemprop="url">{{ link.description }}</a>
|
|
362
362
|
<span class="print-only-inline"> {{ link.url }}</span>
|
|
363
363
|
</li>
|
|
364
364
|
{% endif %}
|
data/_includes/shared-head.html
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
<meta charset="UTF-8">
|
|
2
2
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
3
3
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, viewport-fit=cover">
|
|
4
|
+
<meta name="color-scheme" content="light dark">
|
|
5
|
+
<script>
|
|
6
|
+
(function() {
|
|
7
|
+
try {
|
|
8
|
+
var saved = localStorage.getItem('color-scheme');
|
|
9
|
+
if (saved === 'dark' || saved === 'light') {
|
|
10
|
+
document.documentElement.setAttribute('data-color-scheme', saved);
|
|
11
|
+
document.documentElement.setAttribute('data-theme', saved);
|
|
12
|
+
var meta = document.querySelector('meta[name="color-scheme"]');
|
|
13
|
+
if (meta) {
|
|
14
|
+
meta.setAttribute('content', saved);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
} catch (e) {
|
|
18
|
+
// Graceful fallback if localStorage is restricted (private browsing / iframe sandboxing)
|
|
19
|
+
}
|
|
20
|
+
})();
|
|
21
|
+
</script>
|
|
4
22
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<link rel="
|
|
23
|
+
<!-- Favicons -->
|
|
24
|
+
{% assign favicon_path = site.favicon | default: 'assets/favicon/resume/favicon.ico' %}
|
|
25
|
+
<link rel="shortcut icon" href="{{ favicon_path | relative_url }}" type="image/x-icon">
|
|
26
|
+
<link rel="icon" href="{{ favicon_path | relative_url }}" type="image/x-icon">
|
|
27
|
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ site.apple_touch_icon | default: 'assets/favicon/resume/apple-touch-icon.png' | relative_url }}">
|
|
28
|
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ site.favicon_32 | default: 'assets/favicon/resume/favicon-32x32.png' | relative_url }}">
|
|
29
|
+
<link rel="icon" type="image/png" sizes="16x16" href="{{ site.favicon_16 | default: 'assets/favicon/resume/favicon-16x16.png' | relative_url }}">
|
|
30
|
+
<link rel="manifest" href="{{ 'assets/favicon/resume/site.webmanifest' | relative_url }}">
|
|
9
31
|
|
|
10
32
|
{% if page.noindex == true -%}
|
|
11
33
|
<meta name="robots" content="noindex noarchive nosnippet noimageindex">
|