imdhemy-jekyll-theme 0.1.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +133 -1
  3. data/_includes/archive-header.html +7 -7
  4. data/_includes/content.html +1 -1
  5. data/_includes/contributions.html +11 -9
  6. data/_includes/footer.html +4 -4
  7. data/_includes/header.html +50 -28
  8. data/_includes/hero.html +17 -8
  9. data/_includes/latest-posts.html +9 -7
  10. data/_includes/page-header.html +6 -6
  11. data/_includes/pagination-links.html +6 -6
  12. data/_includes/post-header.html +16 -23
  13. data/_includes/post-item.html +14 -8
  14. data/_includes/post-navigation.html +18 -0
  15. data/_includes/post-tags.html +4 -2
  16. data/_includes/reading-progress.html +3 -0
  17. data/_includes/related-posts.html +49 -0
  18. data/_includes/social-media-meta.html +16 -0
  19. data/_includes/social.html +12 -12
  20. data/_includes/testimonials.html +16 -15
  21. data/_layouts/archive.html +10 -9
  22. data/_layouts/blog.html +11 -9
  23. data/_layouts/default.html +39 -9
  24. data/_layouts/page.html +11 -2
  25. data/_layouts/post.html +11 -2
  26. data/_sass/base/_reset.scss +227 -0
  27. data/_sass/base/_typography.scss +24 -0
  28. data/_sass/components/_core.scss +1544 -0
  29. data/_sass/style.scss +9 -273
  30. data/_sass/utilities/_interactive.scss +100 -0
  31. data/_sass/utilities/_layout.scss +370 -0
  32. data/_sass/utilities/_responsive.scss +99 -0
  33. data/_sass/utilities/_typography.scss +72 -0
  34. data/_sass/utilities/_visual.scss +119 -0
  35. data/assets/css/main.scss +1 -2
  36. data/assets/images/social.png +0 -0
  37. data/assets/js/dist/main.js +1 -1
  38. metadata +63 -13
  39. data/_data/.gitinclude +0 -0
  40. data/_sass/.gitinclude +0 -0
  41. data/_sass/tailwind.src.scss +0 -4
  42. data/assets/css/tailwind.css +0 -1
  43. data/assets/js/src/index.js +0 -1
  44. /data/_sass/{_highlight.scss → components/_highlight.scss} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1515c0ede2f0e2f57a4ba4a73ab0d572884b971d7d403eddfc3eb10effc63711
4
- data.tar.gz: 7fd36ddbd7002a8942de8be2395de69e6498c62947d1db15437898729b73ace4
3
+ metadata.gz: 68a2421fc01b914158903f38955d459bdadcd29e8daf429cf68db51871921ba8
4
+ data.tar.gz: 1ffae175b00a683ef6e42746332ec76ad48784560e5d1b4a0ef886c842bcfe45
5
5
  SHA512:
6
- metadata.gz: 74e4c503fbcdc91e5b21a1076f0928286dec9d50350a883460bdefce263f33b2d0090d59764e0163a48f620b06367d225ea404d37785d44c31fe44c4966e46bb
7
- data.tar.gz: cab8c356554ef5cb0e598eda95ebad05bce0897209183d74af96e4ee8638eed3abf6a120f0e3ffb92478ac661ac7a23704de4e83b04b82782b29fec1b65ebae2
6
+ metadata.gz: d4104d5d88e7915ae5b1648b3987fc5d6b74cd3eb3e29a1fe15928b6a3a27a02d421371455066d3730d144665760fe7cf437f1603c4775b83af0c2483ba5df8a
7
+ data.tar.gz: 3095cf8e24b5308c8a0f5578c4179c5cf8e1cd68ab7af867ff3484d9901d43d06f8f5ba9598e3404a09d1154c5d9a09f9573721be71c8604a11a77730f5c1af3
data/README.md CHANGED
@@ -1,2 +1,134 @@
1
1
  # Imdhemy Jekyll Theme
2
- [...]
2
+
3
+ Jekyll theme for my personal website. [imdhemy.com](https://imdhemy.com)
4
+
5
+ ## Installation (Recommended: RubyGem)
6
+
7
+ Install the theme as a gem and pin a semantic version.
8
+
9
+ Add to your site's `Gemfile`:
10
+
11
+ ```ruby
12
+ gem "imdhemy-jekyll-theme", "1.0.0"
13
+ ```
14
+
15
+ Set the theme in your site's `_config.yml`:
16
+
17
+ ```yaml
18
+ theme: imdhemy-jekyll-theme
19
+ ```
20
+
21
+ Then run:
22
+
23
+ ```bash
24
+ bundle install
25
+ ```
26
+
27
+ ## Migrating From `remote_theme`
28
+
29
+ If your site currently uses:
30
+
31
+ ```yaml
32
+ remote_theme: imdhemy/imdhemy-jekyll-theme
33
+ ```
34
+
35
+ Migrate to the gem flow:
36
+
37
+ 1. Remove `remote_theme` from `_config.yml`.
38
+ 2. Add `theme: imdhemy-jekyll-theme` to `_config.yml`.
39
+ 3. Add `gem "imdhemy-jekyll-theme", "<semantic-version>"` to your `Gemfile`.
40
+ 4. Run `bundle install`.
41
+
42
+ ## Usage
43
+
44
+ You can find examples in the [example](/example) directory.
45
+
46
+ ## Customize Theme Copy
47
+
48
+ The theme exposes UI text keys so users can control the added content from `_config.yml`.
49
+
50
+ ```yaml
51
+ theme_text:
52
+ hero_kicker: "Personal blog and engineering notes"
53
+ hero_cta_label: "Start reading"
54
+ hero_secondary_cta_label: "About me"
55
+ hero_secondary_cta_url: "/about"
56
+ latest_posts_subtitle: "Fresh writing you can read in a few minutes."
57
+ read_article_label: "Read article"
58
+ back_to_posts_label: "Back to all posts"
59
+ previous_article_label: "Previous article"
60
+ next_article_label: "Next article"
61
+ related_posts_heading: "Keep reading"
62
+
63
+ theme_features:
64
+ reading_progress: true
65
+
66
+ theme_style:
67
+ accent: "#3b82f6"
68
+ accent_strong: "#2563eb"
69
+ accent_soft: "#dbeafe"
70
+ accent_surface: "#eff6ff"
71
+ success: "#16a34a"
72
+ info: "#2563eb"
73
+ warning: "#d97706"
74
+ danger: "#dc2626"
75
+ background: "#eef4ff"
76
+ surface: "#ffffff"
77
+ text: "#0f172a"
78
+ muted: "#475569"
79
+ border: "#c9d8f2"
80
+ ```
81
+
82
+ ## Development Quick Start
83
+
84
+ Use this sequence every time you start working on the theme locally.
85
+
86
+ ### 1. Prerequisites
87
+
88
+ - Ruby 3.3.4 + Bundler
89
+ - Node.js 24 + npm
90
+
91
+ The project pins runtime versions in:
92
+
93
+ - `.ruby-version`
94
+ - `.nvmrc`
95
+ - `.node-version`
96
+ - `.tool-versions`
97
+
98
+ ### 2. Install dependencies
99
+
100
+ ```bash
101
+ bundle install
102
+ npm install
103
+ ```
104
+
105
+ ### 3. Start development
106
+
107
+ Run the theme preview and JS watcher together:
108
+
109
+ ```bash
110
+ npm start
111
+ ```
112
+
113
+ This runs:
114
+
115
+ - `bundle exec rake preview` to serve the example site from `http://127.0.0.1:4000/example/`
116
+ - `vite build --watch` to rebuild `assets/js/dist/main.js` on JS changes
117
+
118
+ ### 4. Day-to-day workflow
119
+
120
+ - Edit layouts/includes/styles in the theme root.
121
+ - Edit sample content under `example/` to verify real pages.
122
+ - Keep `npm start` running while you work.
123
+
124
+ ### 5. Useful standalone commands
125
+
126
+ ```bash
127
+ npm run rake # Jekyll preview only
128
+ npm run js:build # JS production build
129
+ npm run js:watch # JS watcher only
130
+ ```
131
+
132
+ ## License
133
+
134
+ The theme is available as open source under the terms of the [MIT License](/LICENSE.txt).
@@ -1,10 +1,10 @@
1
- <section class="bg-white p-0">
2
- <div class="container mx-auto">
3
- <div class="max-w-screen-md mx-auto border-b border-b-gray-200 py-16 mb-16">
4
- <div class="flex-col px-5 lg:px-0">
5
- <h1 class="text-8xl mb-8 font-bold text-center relative">{{ page.title }}</h1>
6
- <p class="text-center text-xl text-gray-700">Check out the <a
7
- class="text-black font-bold border-b-2 border-transparent hover:border-b-violet-600 ease-in duration-300"
1
+ <section class="page-header-wrap page-header-wrap--archive">
2
+ <div class="page-header-wrap__container">
3
+ <div class="page-header page-header--archive page-header--archive-hub">
4
+ <div class="page-header__layout page-header__layout--stacked">
5
+ <h1 class="page-header__title page-header__title--centered">{{ page.title }}</h1>
6
+ <p class="page-header__description page-header__description--centered">Check out the <a
7
+ class="archive-header__blog-link"
8
8
  href="{{ site.baseurl }}/blog">blog</a> for all
9
9
  posts.</p>
10
10
  </div>
@@ -1,3 +1,3 @@
1
- <div class="max-w-screen-md mx-auto bg-white p-5 text-xl content">
1
+ <div class="content-shell content read-surface">
2
2
  {{ content }}
3
3
  </div>
@@ -1,16 +1,17 @@
1
- <section class="mb-8">
2
- <div class="container mx-auto">
3
- <div class="p-5 max-w-screen-lg mx-auto">
4
- <h2 class="text-3xl font-bold text-center mb-8">Contributions</h2>
1
+ {% if site.contributions.size > 0 %}
2
+ <section class="contributions">
3
+ <div class="contributions__container">
4
+ <div class="contributions__inner">
5
+ <h2 class="contributions__title">Contributions</h2>
5
6
 
6
- <p class="text-center text-2xl text-gray-500 mb-8">I have contributed to some great projects</p>
7
+ <p class="contributions__subtitle">I have contributed to some great projects</p>
7
8
 
8
- <div class="grid gap-4 grid-cols-1 lg:grid-cols-3">
9
+ <div class="contributions__grid">
9
10
  {% for contribution in site.contributions %}
10
- <div class="py-5 flex items-center flex-col">
11
- <a href="{{ contribution.url }}" class="block ease-linear">
11
+ <div class="contributions__item">
12
+ <a href="{{ contribution.url }}" class="contributions__link">
12
13
  <img src="{{ site.baseurl }}{{ contribution.logo }}"
13
- class="h-8 block" alt="{{ contribution.name }}">
14
+ class="contributions__logo" alt="{{ contribution.name }}">
14
15
  </a>
15
16
  </div>
16
17
  {% endfor %}
@@ -18,3 +19,4 @@
18
19
  </div>
19
20
  </div>
20
21
  </section>
22
+ {% endif %}
@@ -1,7 +1,7 @@
1
- <section class="sticky top-[100vh]">
2
- <div class="p-10">
3
- <div class="max-w-screen-md mx-auto">
4
- <p class="text-center">
1
+ <section class="site-footer">
2
+ <div class="site-footer__inner">
3
+ <div class="site-footer__container">
4
+ <p class="site-footer__text">
5
5
  <!-- 2001 - jekyll current year -->
6
6
  &copy; 2021 - {{ site.time | date: '%Y' }} . imdhemy.com Published by Jekyll, hosted on GitHub Pages.
7
7
  </p>
@@ -1,47 +1,69 @@
1
- <header class="relative" id="main-header">
2
- <div class="container mx-auto">
3
- <div class="flex py-6 lg:py-14 p-5 lg:px-0">
1
+ <header class="site-header" id="main-header">
2
+ <div class="site-header__container">
3
+ <div class="site-header__inner">
4
4
  <!-- begin logo -->
5
- <div class="flex-auto">
6
- <div>
7
- <a href="{{ site.baseurl }}/" class="text-gray-900 text-3xl font-bold">
8
- {{ site.title }}
9
- </a>
10
- </div>
5
+ <div class="site-header__brand">
6
+ <a href="{{ site.baseurl }}/" class="site-logo">
7
+ {{ site.title }}
8
+ </a>
11
9
  </div>
12
10
  <!-- end logo -->
13
11
  <!-- begin right part -->
14
- <div class="flex-auto">
15
- <div class="flex justify-end lg:hidden">
16
- <button type="button">
12
+ <div class="site-header__actions">
13
+ <div class="site-header__mobile-toggle-wrap">
14
+ <button type="button" class="site-header__toggle" data-target="#mobile-nav" aria-controls="mobile-nav"
15
+ aria-expanded="false" aria-label="Toggle navigation menu">
17
16
  <ion-icon name="menu-outline"></ion-icon>
18
17
  </button>
19
18
  </div>
20
19
 
21
- <div class="hidden lg:flex justify-end">
22
- <ul class="flex items-center">
23
- {% for page in site.navigation %}
24
- <li class="ml-10">
25
- <a href="{{ site.baseurl }}{{ page.url }}"
26
- class="text-base font-semibold p-2 text-gray-900 ease-linear hover:text-blue-600 active:text-blue-600">
27
- {{ page.title }}
20
+ <nav class="site-header__desktop-nav" aria-label="Primary navigation">
21
+ <ul class="site-nav-list">
22
+ {% assign current_path = page.url | default: "/" | split: "?" | first | replace: "index.html", "" | replace: ".html", "" %}
23
+ {% assign current_norm = current_path | append: "/" | replace: "//", "/" %}
24
+ {% for nav_page in site.navigation %}
25
+ {% assign nav_path = nav_page.url | default: "/" | split: "?" | first | replace: "index.html", "" | replace: ".html", "" %}
26
+ {% assign nav_norm = nav_path | append: "/" | replace: "//", "/" %}
27
+ {% assign is_active = false %}
28
+ {% if current_norm == nav_norm %}
29
+ {% assign is_active = true %}
30
+ {% endif %}
31
+ {% if nav_norm == "/blog/" and (current_norm contains "/blog/" or current_norm contains "/tag/" or page.layout == "post" or page.layout == "archive" or page.collection == "posts") %}
32
+ {% assign is_active = true %}
33
+ {% endif %}
34
+ <li class="site-nav-list__item">
35
+ <a href="{{ site.baseurl }}{{ nav_page.url }}"
36
+ class="nav-link{% if is_active %} is-active{% endif %}">
37
+ {{ nav_page.title }}
28
38
  </a>
29
39
  </li>
30
40
  {% endfor %}
31
41
  </ul>
32
- </div>
42
+ </nav>
33
43
  <!-- end right part -->
34
44
  </div>
35
45
  <!-- begin mobile nav -->
36
46
  <nav id="mobile-nav"
37
- class="-z-10 opacity-0 absolute top-32 right-6 block min-w-fit w-40 bg-white p-5 rounded-md shadow-md ease-linear">
38
- <div class="ml-auto">
39
- <ul class="p-0 m-0 flex-column items-center">
40
- {% for page in site.navigation %}
41
- <li class="block flex-1 w-full m-0">
42
- <a href="{{ site.baseurl }}{{ page.url }}"
43
- class="block text-right text-base font-semibold p-2 text-gray-900 ease-linear hover:text-blue-600 active:text-blue-600">
44
- {{ page.title }}
47
+ class="site-mobile-nav is-hidden"
48
+ aria-label="Mobile navigation">
49
+ <div class="site-mobile-nav__inner">
50
+ <ul class="site-mobile-nav__list">
51
+ {% assign current_path = page.url | default: "/" | split: "?" | first | replace: "index.html", "" | replace: ".html", "" %}
52
+ {% assign current_norm = current_path | append: "/" | replace: "//", "/" %}
53
+ {% for nav_page in site.navigation %}
54
+ {% assign nav_path = nav_page.url | default: "/" | split: "?" | first | replace: "index.html", "" | replace: ".html", "" %}
55
+ {% assign nav_norm = nav_path | append: "/" | replace: "//", "/" %}
56
+ {% assign is_active = false %}
57
+ {% if current_norm == nav_norm %}
58
+ {% assign is_active = true %}
59
+ {% endif %}
60
+ {% if nav_norm == "/blog/" and (current_norm contains "/blog/" or current_norm contains "/tag/" or page.layout == "post" or page.layout == "archive" or page.collection == "posts") %}
61
+ {% assign is_active = true %}
62
+ {% endif %}
63
+ <li class="site-mobile-nav__item">
64
+ <a href="{{ site.baseurl }}{{ nav_page.url }}"
65
+ class="site-mobile-nav__link nav-link{% if is_active %} is-active{% endif %}">
66
+ {{ nav_page.title }}
45
67
  </a>
46
68
  </li>
47
69
  {% endfor %}
data/_includes/hero.html CHANGED
@@ -1,14 +1,23 @@
1
- <section class="bg-white py-16">
2
- <div class="container mx-auto">
3
- <div class="flex flex-col items-center flex-wrap">
4
- <div class="flex-1 px-8 max-w-2xl">
5
- <div class="text-center mx-auto">
6
- <h1 class="text-3xl lg:text-6xl mb-8 lg:text-5xl font-bold">
7
- Hi, I'm <span class="text-blue-500">{{ site.author.name }}</span>
1
+ {% assign hero_kicker = site.theme_text.hero_kicker | default: "Personal blog and engineering notes" %}
2
+ {% assign hero_cta_label = site.theme_text.hero_cta_label | default: "Start reading" %}
3
+ {% assign hero_secondary_cta_label = site.theme_text.hero_secondary_cta_label | default: "About me" %}
4
+ {% assign hero_secondary_cta_url = site.theme_text.hero_secondary_cta_url | default: "/about" %}
5
+ <section class="hero-section">
6
+ <div class="hero-section__container">
7
+ <div class="hero-section__layout">
8
+ <div class="hero-section__content">
9
+ <div class="hero-section__content-inner">
10
+ <p class="hero-kicker">{{ hero_kicker }}</p>
11
+ <h1 class="hero-title">
12
+ Hi, I'm <span class="hero-title__accent">{{ site.author.name }}</span>
8
13
  </h1>
9
- <p class="text-lg lg:text-2xl leading-8 lg:leading-10 text-gray-500">
14
+ <p class="hero-description">
10
15
  {{ site.author.description }}
11
16
  </p>
17
+ <div class="hero-cta hero-cta--dual">
18
+ <a href="{{ site.baseurl }}/blog" class="primary-button">{{ hero_cta_label }}</a>
19
+ <a href="{{ site.baseurl }}{{ hero_secondary_cta_url }}" class="secondary-button">{{ hero_secondary_cta_label }}</a>
20
+ </div>
12
21
  </div>
13
22
  </div>
14
23
  </div>
@@ -1,15 +1,17 @@
1
- <section class="mb-8">
2
- <div class="container mx-auto">
3
- <div class="p-5">
4
- <h2 class="text-3xl font-bold text-center mb-8">Latest Posts</h2>
5
- <div class="max-w-screen-md mx-auto">
1
+ {% assign latest_posts_subtitle = site.theme_text.latest_posts_subtitle | default: "Fresh writing you can read in a few minutes." %}
2
+ <section class="latest-posts" id="latest-posts">
3
+ <div class="latest-posts__container">
4
+ <div class="latest-posts__inner">
5
+ <h2 class="latest-posts__title">Latest Posts</h2>
6
+ <p class="section-subtitle">{{ latest_posts_subtitle }}</p>
7
+ <div class="latest-posts__list">
6
8
  {% for post in site.posts limit:3 %}
7
9
  {% include post-item.html %}
8
10
  {% endfor %}
9
11
  </div>
10
- <div class="mt-16 text-center">
12
+ <div class="latest-posts__cta">
11
13
  <a href="{{ site.baseurl }}/blog"
12
- class="py-4 px-6 bg-violet-700 text-lg font-semibold rounded-3xl text-white ease-in duration-300 hover:bg-violet-800">
14
+ class="primary-button">
13
15
  All Posts &rarr;
14
16
  </a>
15
17
  </div>
@@ -1,9 +1,9 @@
1
- <section class="bg-white p-0">
2
- <div class="container mx-auto">
3
- <div class="max-w-screen-xl mx-auto border-b border-b-gray-200 py-16 mb-16">
4
- <div class="flex flex-col lg:flex-row justify-between px-5 lg:px-0">
5
- <h1 class="text-8xl mb-8 font-bold">{{ page.title }}</h1>
6
- <p class="max-w-screen-sm text-xl text-gray-600">{{ page.description }} </p>
1
+ <section class="page-header-wrap page-header-wrap--blog">
2
+ <div class="page-header-wrap__container">
3
+ <div class="page-header page-header--page page-header--blog">
4
+ <div class="page-header__layout">
5
+ <h1 class="page-header__title">{{ page.title }}</h1>
6
+ <p class="page-header__description">{{ page.description }} </p>
7
7
  </div>
8
8
  </div>
9
9
  </div>
@@ -1,18 +1,18 @@
1
1
  {% if paginator.total_pages > 1 %}
2
- <section class="mx-auto max-w-screen-md px-5">
3
- <nav class="flex items-center justify-between">
2
+ <section class="pagination-shell">
3
+ <nav class="pagination-nav" aria-label="Pagination">
4
4
  {% if paginator.previous_page %}
5
- <a class="inline-block font-semibold border-b-2 border-transparent hover:border-indigo-600"
5
+ <a class="pagination-link"
6
6
  href="{{ paginator.previous_page_path | relative_url }}">Prev</a>
7
7
  {% else %}
8
- <span class="inline-block font-semibold text-gray-300 cursor-not-allowed">Previous</span>
8
+ <span class="pagination-link is-disabled">Previous</span>
9
9
  {% endif %}
10
10
 
11
11
  {% if paginator.next_page %}
12
- <a class="inline-block font-semibold border-b-2 border-transparent hover:border-indigo-600"
12
+ <a class="pagination-link"
13
13
  href="{{ paginator.next_page_path | relative_url }}">Next</a>
14
14
  {% else %}
15
- <span class="inline-block font-semibold text-gray-300 cursor-not-allowed">Next</span>
15
+ <span class="pagination-link is-disabled">Next</span>
16
16
  {% endif %}
17
17
  </nav>
18
18
  </section>
@@ -1,32 +1,25 @@
1
- <div class="max-w-screen-lg mx-auto bg-white p-5">
2
- <h1 class="font-black font-sans text-2xl lg:text-7xl post-title">{{ page.title }}</h1>
3
- </div>
4
-
5
- <div class="max-w-screen-md mx-auto bg-white p-5">
6
- <div class="flex justify-between flex-wrap my-2">
7
- <div class="flex items-center mr-8">
8
- <img src="{{ site.baseurl }}/{{ site.author.avatar }}" alt="{{ author.name }}"
9
- class="rounded-full w-10 h-10 mr-3 block"/>
10
- <div>
11
- <p class="text-gray-700 text-sm font-bold">{{ site.author.name }}</p>
12
- <p class="text-gray-500 text-xs">
13
- {{ page.date | date: "%B %-d, %Y" }} - {{ page.content |
14
- number_of_words | divided_by: 200 }} min read
15
- </p>
16
- </div>
17
- </div>
18
- </div>
19
-
1
+ {% assign read_minutes = page.content | number_of_words | divided_by: 200 | at_least: 1 %}
2
+ {% assign back_to_posts_label = site.theme_text.back_to_posts_label | default: "Back to all posts" %}
3
+ <div class="post-header">
4
+ <a class="post-back-link" href="{{ site.baseurl }}/blog">&larr; {{ back_to_posts_label }}</a>
5
+ <p class="post-header__meta">{{ page.date | date: "%b %-d, %Y" }} · {{ read_minutes }} min read</p>
20
6
  <div>
21
7
  {% assign tags = page.tags %}
22
8
  {% include post-tags.html %}
23
9
  </div>
10
+ <h1 class="post-title">{{ page.title }}</h1>
24
11
 
25
12
  {% if page.image %}
26
- <div class="relative overflow-hidden">
27
- <img src="{{ site.baseurl }}/{{ page.image }}"
28
- alt="{{ page.title }}"
29
- class="w-full h-auto rounded"/>
13
+ <div class="post-image-wrap">
14
+ <img src="{{ site.baseurl }}{{ page.image }}"
15
+ alt="{{ page.image_alt | default: page.title }}"
16
+ class="post-image"/>
17
+ <!-- Image source -->
18
+ {% if page.image_source %}
19
+ <div class="post-image-source">
20
+ Image source: {{ page.image_source }}
21
+ </div>
22
+ {% endif %}
30
23
  </div>
31
24
  {% endif %}
32
25
  </div>
@@ -1,24 +1,30 @@
1
- <article class="flex flex-col lg:flex-row items-center mb-8 pb-8 border-b border-gray-200">
1
+ {% assign reading_minutes = post.content | number_of_words | divided_by: 200 | at_least: 1 %}
2
+ {% assign read_article_label = site.theme_text.read_article_label | default: "Read article" %}
3
+ <article class="post-card">
2
4
  <!-- thumbnail -->
5
+ {% if post.image %}
3
6
  <a href="{{ site.baseurl }}{{ post.url }}"
4
- class="w-full relative block lg:min-w-[250px] lg:max-w-[250px] lg:max-h-[250px] aspect-square lg:mr-5 mb-5 lg:mb-0 rounded-lg overflow-hidden">
7
+ class="post-card__image">
5
8
  <img src="{{ site.baseurl }}{{ post.image }}"
6
- class="absolute inset-0 w-full h-full object-cover hover:scale-105 ease-in duration-300"
7
- alt="{{ post.title }}"/>
9
+ class="post-card__image-el"
10
+ alt="{{ post.image_alt | default: post.title }}"/>
8
11
  </a>
12
+ {% endif %}
9
13
  <!-- content -->
10
- <div>
14
+ <div class="post-card__content">
15
+ <p class="post-card__meta">{{ post.date | date: "%b %-d, %Y" }} · {{ reading_minutes }} min read</p>
11
16
  {% assign tags = post.tags %}
12
17
  {% include post-tags.html %}
13
18
  <!-- title -->
14
- <h2 class="text-3xl font-black mb-5 font-sans">
15
- <a class="border-b-2 border-transparent hover:border-b-violet-600 ease-in duration-300"
19
+ <h2 class="post-card__title">
20
+ <a class="post-card__title-link"
16
21
  href="{{ site.baseurl }}{{ post.url }}">{{
17
22
  post.title }}</a>
18
23
  </h2>
19
24
  <!-- excerpt -->
20
- <div class="text-gray-500 text-lg mb-0">
25
+ <div class="post-card__excerpt">
21
26
  {{ post.excerpt | strip_html | truncatewords: 20 }}
22
27
  </div>
28
+ <a class="post-card__read-link" href="{{ site.baseurl }}{{ post.url }}">{{ read_article_label }} &rarr;</a>
23
29
  </div>
24
30
  </article>
@@ -0,0 +1,18 @@
1
+ {% assign previous_article_label = site.theme_text.previous_article_label | default: "Previous article" %}
2
+ {% assign next_article_label = site.theme_text.next_article_label | default: "Next article" %}
3
+ <section class="post-navigation-shell">
4
+ <div class="post-navigation-shell__inner post-navigation">
5
+ {% if page.previous.url %}
6
+ <a class="post-navigation__item" href="{{ site.baseurl }}{{ page.previous.url }}">
7
+ <span class="post-navigation__label">{{ previous_article_label }}</span>
8
+ <span class="post-navigation__title">{{ page.previous.title }}</span>
9
+ </a>
10
+ {% endif %}
11
+ {% if page.next.url %}
12
+ <a class="post-navigation__item post-navigation__item--next" href="{{ site.baseurl }}{{ page.next.url }}">
13
+ <span class="post-navigation__label">{{ next_article_label }}</span>
14
+ <span class="post-navigation__title">{{ page.next.title }}</span>
15
+ </a>
16
+ {% endif %}
17
+ </div>
18
+ </section>
@@ -1,9 +1,11 @@
1
- <div class="flex mb-5">
1
+ {% if tags and tags.size > 0 %}
2
+ <div class="post-tags">
2
3
  {% for tag in tags %}
3
4
  {% assign tag_link = tag | slugify %}
4
5
  <a href="{{ site.baseurl }}/tag/{{ tag_link }}"
5
- class="text-sm text-gray-500 hover:text-gray-700 mr-3">
6
+ class="tag-pill">
6
7
  #{{ tag }}
7
8
  </a>
8
9
  {% endfor %}
9
10
  </div>
11
+ {% endif %}
@@ -0,0 +1,3 @@
1
+ <div class="reading-progress" aria-hidden="true">
2
+ <span class="reading-progress__bar" data-reading-progress></span>
3
+ </div>
@@ -0,0 +1,49 @@
1
+ {% assign related_limit = 3 %}
2
+ {% assign related_count = 0 %}
3
+ {% assign related_urls = "" %}
4
+ {% assign related_posts_heading = site.theme_text.related_posts_heading | default: "Keep reading" %}
5
+
6
+ <section class="related-posts-shell">
7
+ <div class="related-posts-shell__inner">
8
+ <h2 class="related-posts__heading">{{ related_posts_heading }}</h2>
9
+ <div class="related-posts">
10
+ {% if page.tags and page.tags.size > 0 %}
11
+ {% for post in site.posts %}
12
+ {% if post.url != page.url and related_count < related_limit %}
13
+ {% assign has_shared_tag = false %}
14
+ {% for tag in page.tags %}
15
+ {% if post.tags contains tag %}
16
+ {% assign has_shared_tag = true %}
17
+ {% break %}
18
+ {% endif %}
19
+ {% endfor %}
20
+ {% if has_shared_tag %}
21
+ <a class="related-posts__item" href="{{ site.baseurl }}{{ post.url }}">
22
+ <span class="related-posts__title">{{ post.title }}</span>
23
+ <span class="related-posts__meta">{{ post.date | date: "%b %-d, %Y" }}</span>
24
+ </a>
25
+ {% assign related_urls = related_urls | append: "|" | append: post.url %}
26
+ {% assign related_count = related_count | plus: 1 %}
27
+ {% endif %}
28
+ {% endif %}
29
+ {% endfor %}
30
+ {% endif %}
31
+
32
+ {% if related_count < related_limit %}
33
+ {% for post in site.posts %}
34
+ {% if post.url != page.url and related_count < related_limit %}
35
+ {% assign seen_key = "|" | append: post.url %}
36
+ {% unless related_urls contains seen_key %}
37
+ <a class="related-posts__item" href="{{ site.baseurl }}{{ post.url }}">
38
+ <span class="related-posts__title">{{ post.title }}</span>
39
+ <span class="related-posts__meta">{{ post.date | date: "%b %-d, %Y" }}</span>
40
+ </a>
41
+ {% assign related_urls = related_urls | append: "|" | append: post.url %}
42
+ {% assign related_count = related_count | plus: 1 %}
43
+ {% endunless %}
44
+ {% endif %}
45
+ {% endfor %}
46
+ {% endif %}
47
+ </div>
48
+ </div>
49
+ </section>
@@ -0,0 +1,16 @@
1
+ <!-- Facebook Meta Tags -->
2
+ <meta property="og:title" content="{{ page.title | escape }}">
3
+ <meta property="og:type" content="article">
4
+ <meta property="og:image" content="{{ site.url }}{{ site.baseurl }}{{ page.image }}">
5
+ <meta property="og:url" content="{{ site.url }}{{ site.baseurl }}{{ page.url }}">
6
+ <meta property="og:description"
7
+ content="{{ page.excerpt | default: site.description | strip_html | normalize_whitespace | truncate: 160 | escape }}">
8
+ <meta property="og:site_name" content="{{ site.title | escape }}">
9
+
10
+ <!-- Twitter Meta Tags -->
11
+ <meta name="twitter:card" content="summary_large_image">
12
+ <meta name="twitter:title" content="{{ page.title | escape }}">
13
+ <meta name="twitter:description"
14
+ content="{{ page.excerpt | default: site.description | strip_html | normalize_whitespace | truncate: 160 | escape }}">
15
+ <meta name="twitter:image" content="{{ site.url }}{{ site.baseurl }}{{ page.image }}">
16
+