jekyll-theme-manpage 0.1.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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +193 -0
- data/_includes/comments.html +21 -0
- data/_includes/fun_facts.html +9 -0
- data/_includes/head-custom-google-analytics.html +10 -0
- data/_includes/head-custom.html +64 -0
- data/_includes/read_time.html +11 -0
- data/_includes/skin.html +4 -0
- data/_includes/social_links.html +8 -0
- data/_layouts/default.html +63 -0
- data/_layouts/home.html +19 -0
- data/_layouts/post.html +29 -0
- data/_layouts/writing.html +173 -0
- data/_sass/jekyll-theme-manpage.scss +825 -0
- data/_sass/normalize.scss +426 -0
- data/_sass/skins/_dracula.scss +118 -0
- data/_sass/skins/_github.scss +118 -0
- data/_sass/skins/_monokai.scss +118 -0
- data/_sass/skins/_nord.scss +118 -0
- data/_sass/skins/_purple.scss +118 -0
- data/_sass/skins/_tomorrow.scss +118 -0
- data/_sass/variables.scss +61 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_AMS-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_AMS-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Bold.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Bold.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Bold.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Italic.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Italic.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Italic.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Main-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Math-Italic.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Math-Italic.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Math-Italic.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Script-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Script-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Script-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size1-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size1-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size2-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size2-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size3-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size3-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size4-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size4-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- data/assets/css/plugins/katex.0.11.1/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- data/assets/css/plugins/katex.0.11.1/katex.min.css +1 -0
- data/assets/css/style.scss +7 -0
- data/assets/images/favicon.svg +3 -0
- data/assets/images/profile.png +0 -0
- data/assets/js/theme-switcher.js +47 -0
- data/assets/readme/preview.png +0 -0
- data/assets/themes/dracula.png +0 -0
- data/assets/themes/dracula_dark.png +0 -0
- data/assets/themes/github.png +0 -0
- data/assets/themes/github_dark.png +0 -0
- data/assets/themes/monokai.png +0 -0
- data/assets/themes/monokai_dark.png +0 -0
- data/assets/themes/nord.png +0 -0
- data/assets/themes/nord_dark.png +0 -0
- data/assets/themes/purple.png +0 -0
- data/assets/themes/purple_dark.png +0 -0
- data/assets/themes/tomorrow.png +0 -0
- data/assets/themes/tomorrow_dark.png +0 -0
- metadata +269 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bb5cb53e1adde0574281d3c8b1fb171253760abfe92ba4ac5ad03f288a65f81f
|
4
|
+
data.tar.gz: 6955c84eefa6f386f3c289262861f608896fb91e84fc8f72f36ece80b290fb30
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 53e1cfb61ca31dff33ac66e6294f8c0379a975eec7009630f0d1abfda62faf1b7ff7815e88124c80777b4fec4ae50dfe41f09d277c068944d6bc5ebaea20c5f2
|
7
|
+
data.tar.gz: 2afdf5844b528b4ba34d0a60cc411fb8522112d9b116d296295d36ef00f2023041dbdecd898c4971c92d00f70a577304471ffab42cdff119cd36c68358008961
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Drshika Asher
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# 📇 Jekyll Theme Manpage
|
2
|
+
|
3
|
+
> This theme is currently being beta tested and any feedback is greatly appreciated!
|
4
|
+
|
5
|
+
[](https://app.netlify.com/sites/jekyll-theme-manpage/deploys)
|
6
|
+
|
7
|
+
A minimalist Jekyll theme inspired by Linux man pages. Perfect for personal websites, portfolios, and blogs with a technical focus.
|
8
|
+
|
9
|
+

|
10
|
+
|
11
|
+
## Features
|
12
|
+
|
13
|
+
- 🖥️ Linux man page inspired design
|
14
|
+
- 📱 Fully responsive layout
|
15
|
+
- 🌙 Automatic dark mode support
|
16
|
+
- ✍️ Blog/writing section with:
|
17
|
+
- Full-text search
|
18
|
+
- Tag filtering
|
19
|
+
- Table of contents
|
20
|
+
- Reading Time
|
21
|
+
- 📐 LaTeX support for mathematical expressions
|
22
|
+
- 🎨 Multiple color themes with light/dark variants
|
23
|
+
- 🚀 Fast and lightweight
|
24
|
+
- 📱 Mobile-first approach
|
25
|
+
- 🔍 SEO optimized
|
26
|
+
- 📊 Sitemap generation
|
27
|
+
- 💬 Giscus comments integration
|
28
|
+
- 📡 RSS feed support
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
### Local Installation
|
33
|
+
|
34
|
+
Add this line to your Jekyll site's `Gemfile`:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
gem "jekyll-theme-manpage"
|
38
|
+
```
|
39
|
+
|
40
|
+
And add this line to your Jekyll site's `_config.yml`:
|
41
|
+
|
42
|
+
```yaml
|
43
|
+
theme: jekyll-theme-manpage
|
44
|
+
```
|
45
|
+
|
46
|
+
Then run
|
47
|
+
|
48
|
+
```bash
|
49
|
+
bundle install
|
50
|
+
```
|
51
|
+
|
52
|
+
### GitHub Pages Installation
|
53
|
+
|
54
|
+
(NOT SUPPORTED YET) For GitHub Pages, add this to your site's `_config.yml`:
|
55
|
+
|
56
|
+
```yaml
|
57
|
+
remote_theme: drshika/jekyll-theme-manpage
|
58
|
+
plugins:
|
59
|
+
- jekyll-remote-theme
|
60
|
+
```
|
61
|
+
|
62
|
+
Add `jekyll-remote-theme` to the Gemfile:
|
63
|
+
|
64
|
+
```ruby:Gemfile
|
65
|
+
gem 'jekyll-remote-theme'
|
66
|
+
```
|
67
|
+
|
68
|
+
## Usage
|
69
|
+
|
70
|
+
### Basic Setup
|
71
|
+
|
72
|
+
1. Create your site structure following Jekyll conventions
|
73
|
+
2. Configure `_config.yml` with your settings
|
74
|
+
3. Add content to `index.md` using the provided template
|
75
|
+
|
76
|
+
### Writing Posts
|
77
|
+
|
78
|
+
Create posts in `_posts` directory following this format:
|
79
|
+
|
80
|
+
```markdown
|
81
|
+
---
|
82
|
+
layout: post
|
83
|
+
title: Your Post Title
|
84
|
+
description: Brief description
|
85
|
+
tags: [tag1, tag2]
|
86
|
+
toc: true # Optional table of contents
|
87
|
+
---
|
88
|
+
Your content here...
|
89
|
+
```
|
90
|
+
|
91
|
+
Make sure to name the file with the `YYYY-MM-DD-Title.md`.
|
92
|
+
|
93
|
+
|
94
|
+
### Customization
|
95
|
+
|
96
|
+
#### Color Themes
|
97
|
+
|
98
|
+
The theme comes with several preset color schemes. Currently changing the theme is only supported for local development.
|
99
|
+
|
100
|
+
### Light Themes
|
101
|
+
| Theme | Preview |
|
102
|
+
|-------|---------|
|
103
|
+
| Purple |  |
|
104
|
+
| Tomorrow |  |
|
105
|
+
| GitHub |  |
|
106
|
+
| Dracula |  |
|
107
|
+
| Nord |  |
|
108
|
+
| Monokai |  |
|
109
|
+
|
110
|
+
### Dark Themes
|
111
|
+
| Theme | Preview |
|
112
|
+
|-------|---------|
|
113
|
+
| Purple |  |
|
114
|
+
| Tomorrow |  |
|
115
|
+
| GitHub |  |
|
116
|
+
| Dracula |  |
|
117
|
+
| Nord |  |
|
118
|
+
| Monokai |  |
|
119
|
+
|
120
|
+
|
121
|
+
To use any of these themes, update your `_sass/variables.scss`:
|
122
|
+
|
123
|
+
```scss
|
124
|
+
// Theme selection
|
125
|
+
$default-theme: 'nord';
|
126
|
+
$default-mode: 'light';
|
127
|
+
```
|
128
|
+
|
129
|
+
#### Typography
|
130
|
+
|
131
|
+
This theme uses Nitti as its default font. You can purchase Nitti from [Adobe Fonts](https://fonts.adobe.com/fonts/nitti). If you don't have Nitti, the theme will fallback to Fira Code.
|
132
|
+
|
133
|
+
## Development
|
134
|
+
|
135
|
+
(For local use only!) To set up your environment to develop this theme:
|
136
|
+
|
137
|
+
1. Clone this repo
|
138
|
+
2. Run `bundle install`
|
139
|
+
3. Run `bundle exec jekyll serve`
|
140
|
+
4. Visit `http://localhost:4000`
|
141
|
+
|
142
|
+
## Optional Features
|
143
|
+
|
144
|
+
Enable optional features in your `_config.yml`:
|
145
|
+
|
146
|
+
```yaml
|
147
|
+
features:
|
148
|
+
comments: true # Set to true to enable Giscus comments
|
149
|
+
rss_feed: true # Set to true to enable RSS feed
|
150
|
+
search: true # Set to true to enable search
|
151
|
+
google_analytics: false # Set to true to enable Google Analytics
|
152
|
+
tags: true # Set to true to enable tags
|
153
|
+
read_time: true # Set to true to enable read time
|
154
|
+
back_to_top: false # Set to true to enable back to top button
|
155
|
+
```
|
156
|
+
|
157
|
+
### Comments
|
158
|
+
|
159
|
+
To enable comments:
|
160
|
+
|
161
|
+
1. Set `features.comments: true` in your `_config.yml`
|
162
|
+
2. Get your Giscus script from [giscus.app](https://giscus.app)
|
163
|
+
3. Paste the generated script into `_includes/comments.html`
|
164
|
+
|
165
|
+
Disable comments for specific posts by adding `comments: false` to the post's front matter.
|
166
|
+
|
167
|
+
### RSS Feed
|
168
|
+
|
169
|
+
To enable RSS feed:
|
170
|
+
|
171
|
+
1. Set `features.rss_feed: true` in your `_config.yml`
|
172
|
+
|
173
|
+
Your feed will be available at `/feed.xml`.
|
174
|
+
|
175
|
+
### RSS Feed
|
176
|
+
|
177
|
+
To enable RSS feed:
|
178
|
+
|
179
|
+
1. Set `features.rss_feed: true` in your `_config.yml`
|
180
|
+
|
181
|
+
Your feed will be available at `/feed.xml`. See [Jekyll Feed documentation](https://github.com/jekyll/jekyll-feed) for additional configuration options.
|
182
|
+
|
183
|
+
## Contributing
|
184
|
+
|
185
|
+
Bug reports and pull requests are welcome on GitHub. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct.
|
186
|
+
|
187
|
+
## License
|
188
|
+
|
189
|
+
The theme is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
190
|
+
|
191
|
+
## Credits
|
192
|
+
|
193
|
+
Created with ❤️ by Drshika Asher
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{% if site.features.comments %}
|
2
|
+
<div class="comments">
|
3
|
+
<h2>Comments</h2>
|
4
|
+
<script src="https://giscus.app/client.js"
|
5
|
+
data-repo="drshika/jekyll-theme-manpage"
|
6
|
+
data-repo-id="R_kgDONlmNQQ"
|
7
|
+
data-category="Announcements"
|
8
|
+
data-category-id="DIC_kwDONlmNQc4Clurt"
|
9
|
+
data-mapping="og:title"
|
10
|
+
data-strict="0"
|
11
|
+
data-reactions-enabled="1"
|
12
|
+
data-emit-metadata="1"
|
13
|
+
data-input-position="top"
|
14
|
+
data-theme="preferred_color_scheme"
|
15
|
+
data-lang="en"
|
16
|
+
data-loading="lazy"
|
17
|
+
crossorigin="anonymous"
|
18
|
+
async>
|
19
|
+
</script>
|
20
|
+
</div>
|
21
|
+
{% endif %}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
{% if site.google_analytics %}
|
2
|
+
<script>
|
3
|
+
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
4
|
+
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
5
|
+
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
6
|
+
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
7
|
+
ga('create', '{{ site.google_analytics }}', 'auto');
|
8
|
+
ga('send', 'pageview');
|
9
|
+
</script>
|
10
|
+
{% endif %}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<!-- start custom head snippets -->
|
2
|
+
|
3
|
+
<!-- Theme Switcher -->
|
4
|
+
<script src="{{ '/assets/js/theme-switcher.js' | relative_url }}"></script>
|
5
|
+
|
6
|
+
<!-- Common meta tags -->
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com">
|
9
|
+
|
10
|
+
<!-- KaTeX - only load if page.katex is true -->
|
11
|
+
{% if page.katex %}
|
12
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/katex.min.css"
|
13
|
+
integrity="sha384-7lU0muIg/i1plk7MgygDUp3/bNRA65orrBub4/OSWHECgwEsY83HaS1x3bljA/XV" crossorigin="anonymous">
|
14
|
+
<!-- The loading of KaTeX is deferred to speed up page rendering -->
|
15
|
+
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/katex.min.js"
|
16
|
+
integrity="sha384-RdymN7NRJ+XoyeRY4185zXaxq9QWOOx3O7beyyrRK4KQZrPlCDQQpCu95FoCGPAE"
|
17
|
+
crossorigin="anonymous"></script>
|
18
|
+
<!-- To automatically render math in text elements, include the auto-render extension: -->
|
19
|
+
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/contrib/auto-render.min.js"
|
20
|
+
integrity="sha384-hCXGrW6PitJEwbkoStFjeJxv+fSOOQKOPbJxSfM6G5sWZjAyWhXiTIIAmQqnlLlh" crossorigin="anonymous"
|
21
|
+
onload="renderMathInElement(document.body);"></script>
|
22
|
+
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/contrib/mhchem.min.js"
|
23
|
+
integrity="sha384-F2ptQFZqNJuqfGGl28mIXyQ5kXH48spn7rcoS0Y9psqIKAcZPLd1NzwFlm/bl1mH"
|
24
|
+
crossorigin="anonymous"></script>
|
25
|
+
<script>
|
26
|
+
document.addEventListener("DOMContentLoaded", function () {
|
27
|
+
renderMathInElement(document.body, {
|
28
|
+
delimiters: [
|
29
|
+
{ left: "$$", right: "$$", display: true },
|
30
|
+
{ left: "\\[", right: "\\]", display: true },
|
31
|
+
{ left: "$", right: "$", display: false },
|
32
|
+
{ left: "\\(", right: "\\)", display: false }
|
33
|
+
]
|
34
|
+
|
35
|
+
});
|
36
|
+
});
|
37
|
+
</script>
|
38
|
+
{% endif %}
|
39
|
+
|
40
|
+
<!-- Favicons -->
|
41
|
+
{% if site.favicon %}
|
42
|
+
{% if site.favicon.svg %}
|
43
|
+
<link rel="icon" type="image/svg+xml" href="{{ site.favicon.svg | relative_url }}">
|
44
|
+
{% endif %}
|
45
|
+
{% if site.favicon.ico %}
|
46
|
+
<link rel="alternate icon" type="image/x-icon" href="{{ site.favicon.ico | relative_url }}">
|
47
|
+
{% endif %}
|
48
|
+
{% if site.favicon.png32 %}
|
49
|
+
<link rel="alternate icon" type="image/png" sizes="32x32" href="{{ site.favicon.png32 | relative_url }}">
|
50
|
+
{% endif %}
|
51
|
+
{% if site.favicon.png16 %}
|
52
|
+
<link rel="alternate icon" type="image/png" sizes="16x16" href="{{ site.favicon.png16 | relative_url }}">
|
53
|
+
{% endif %}
|
54
|
+
{% endif %}
|
55
|
+
|
56
|
+
<!-- RSS Feed -->
|
57
|
+
{% if site.features.rss_feed %}
|
58
|
+
{% feed_meta %}
|
59
|
+
{% endif %}
|
60
|
+
|
61
|
+
<!-- Google Analytics -->
|
62
|
+
{% include head-custom-google-analytics.html %}
|
63
|
+
|
64
|
+
<!-- end custom head snippets -->
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!-- Credits: https://carlosbecker.com/posts/jekyll-reading-time-without-plugins/ -->
|
2
|
+
|
3
|
+
<span class="reading-time" title="Estimated read time">
|
4
|
+
{% assign words = content | number_of_words %}
|
5
|
+
{% if words < 360 %}
|
6
|
+
1 min read
|
7
|
+
{% else %}
|
8
|
+
{{ words | divided_by:180 }} min read
|
9
|
+
{% endif %}
|
10
|
+
</span>
|
11
|
+
|
data/_includes/skin.html
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
<div class="social-links">
|
2
|
+
<span class="link-group">
|
3
|
+
[<a href="{{ site.data.social_links.resume.url }}">{{ site.data.social_links.resume.text }}</a>][{{ site.data.social_links.email }}]
|
4
|
+
</span>
|
5
|
+
<span class="link-group">
|
6
|
+
{% for link in site.data.social_links.social %}[{{ link.name | capitalize }}:<a href="{{ link.url }}">{{ link.text }}</a>]{% endfor %}
|
7
|
+
</span>
|
8
|
+
</div>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="{{ site.lang | default: " en-US" }}">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
{% seo %}
|
7
|
+
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
|
8
|
+
{% include head-custom.html %}
|
9
|
+
</head>
|
10
|
+
|
11
|
+
<body>
|
12
|
+
<header class="page-header">
|
13
|
+
<h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>
|
14
|
+
</header>
|
15
|
+
|
16
|
+
<main id="content" class="main-content" role="main">
|
17
|
+
{{ content }}
|
18
|
+
<button id="scrollToTop" title="Go to top">↑</button>
|
19
|
+
<footer class="site-footer">
|
20
|
+
|
21
|
+
{% if page.layout == 'post' %}
|
22
|
+
<a href="/writing" class="back-link">← back to Writing</a>
|
23
|
+
{% else %}
|
24
|
+
<span class="site-footer-credits" style="text-align: center;">{{ site.author }}, 2025</span>
|
25
|
+
{% endif %}
|
26
|
+
</footer>
|
27
|
+
</main>
|
28
|
+
<script>
|
29
|
+
console.log({
|
30
|
+
'data-theme': document.documentElement.getAttribute('data-theme'),
|
31
|
+
'color-scheme': document.documentElement.getAttribute('color-scheme'),
|
32
|
+
'root-bg': getComputedStyle(document.documentElement).getPropertyValue('--bg-color'),
|
33
|
+
'root-color': getComputedStyle(document.documentElement).getPropertyValue('--text-color')
|
34
|
+
});
|
35
|
+
</script>
|
36
|
+
{% if site.features.back_to_top %}
|
37
|
+
<script>
|
38
|
+
document.addEventListener('DOMContentLoaded', function () {
|
39
|
+
// Get the button
|
40
|
+
const scrollButton = document.getElementById("scrollToTop");
|
41
|
+
|
42
|
+
if (scrollButton) {
|
43
|
+
// Show button when user scrolls down 20px from top
|
44
|
+
window.onscroll = function () {
|
45
|
+
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
|
46
|
+
scrollButton.style.display = "block";
|
47
|
+
} else {
|
48
|
+
scrollButton.style.display = "none";
|
49
|
+
}
|
50
|
+
};
|
51
|
+
|
52
|
+
// Scroll to top when button is clicked
|
53
|
+
scrollButton.onclick = function () {
|
54
|
+
document.body.scrollTop = 0; // For Safari
|
55
|
+
document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
|
56
|
+
};
|
57
|
+
}
|
58
|
+
});
|
59
|
+
</script>
|
60
|
+
{% endif %}
|
61
|
+
</body>
|
62
|
+
|
63
|
+
</html>
|
data/_layouts/home.html
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
---
|
4
|
+
<!-- Nav Links -->
|
5
|
+
{% for item in site.data.navigation.pages %}
|
6
|
+
{% if item.name == "Writing" %}
|
7
|
+
<a href="{{item.link}}" alt="{{item.name}}" style="text-transform: uppercase;">{{item.name}}</a>
|
8
|
+
{% else %}
|
9
|
+
<a href="{{item.link}}" alt="{{item.name}}" style="text-transform: uppercase;">{{item.name}}</a> |
|
10
|
+
{% endif %}
|
11
|
+
{% endfor %}
|
12
|
+
<!-- End Nav Links -->
|
13
|
+
|
14
|
+
{{ content | replace: '<h2>NEWS</h2>', '<h2>NEWS</h2>
|
15
|
+
<div class="news-section">' |
|
16
|
+
replace: '<h2>EXTRAS</h2>', '</div>
|
17
|
+
<h2>EXTRAS</h2>' |
|
18
|
+
replace: '<ul>', '<ul class="linked-list">' |
|
19
|
+
replace: '<p><strong>', '<p class="role"><strong class="title">' }}
|
data/_layouts/post.html
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
---
|
4
|
+
<div class="post-meta">
|
5
|
+
<span class="post-date">{{ page.date | date_to_string: "ordinal", "US" }}</span>
|
6
|
+
{% if page.tags %}
|
7
|
+
<div class="post-tags">
|
8
|
+
{% for tag in page.tags %}
|
9
|
+
<span class="tag">{{ tag }}</span>
|
10
|
+
{% endfor %}
|
11
|
+
</div>
|
12
|
+
{% endif %}
|
13
|
+
|
14
|
+
{% if site.features.read_time %}
|
15
|
+
{% include read_time.html %}
|
16
|
+
{% endif %}
|
17
|
+
|
18
|
+
{% if page.toc %}
|
19
|
+
<div class="toc">
|
20
|
+
<h2>Table of Contents</h2>
|
21
|
+
{% toc %}
|
22
|
+
</div>
|
23
|
+
{% endif %}
|
24
|
+
|
25
|
+
</div>
|
26
|
+
|
27
|
+
{{ content }}
|
28
|
+
|
29
|
+
{% include comments.html %}
|
@@ -0,0 +1,173 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="{{ site.lang | default: " en-US" }}">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
{% seo %}
|
7
|
+
<link rel="preconnect" href="https://fonts.gstatic.com">
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
9
|
+
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
|
10
|
+
<title>{{ page.title }}</title>
|
11
|
+
{% include head-custom.html %}
|
12
|
+
</head>
|
13
|
+
|
14
|
+
<body>
|
15
|
+
<header class="page-header">
|
16
|
+
<h1 class="project-name">→ ~ ls -lt /writing</h1>
|
17
|
+
|
18
|
+
<!-- Search bar -->
|
19
|
+
<div class="search-container" {% unless site.features.search %}style="display: none;" {% endunless %}>
|
20
|
+
<input type="text" id="search-input" placeholder="Search posts...">
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<!-- Tag filter -->
|
24
|
+
<div class="tag-container" {% unless site.features.tags %}style="display: none;" {% endunless %}>
|
25
|
+
{% capture tags_string %}{% for tag in site.tags %}{{ tag | first }}:{{ tag | last | size }}|{% endfor %}{% endcapture %}
|
26
|
+
{% assign tags = tags_string | split: '|' | pop | sort | reverse %}
|
27
|
+
{% for tag_info in tags %}
|
28
|
+
{% assign tag_parts = tag_info | split: ':' %}
|
29
|
+
{% assign tag_name = tag_parts[0] | strip %}
|
30
|
+
{% assign tag_count = tag_parts[1] | strip %}
|
31
|
+
<button class="tag-button" data-tag="{{ tag_name }}">
|
32
|
+
{{ tag_name }} ({{ tag_count }})
|
33
|
+
</button>
|
34
|
+
{% endfor %}
|
35
|
+
</div>
|
36
|
+
</header>
|
37
|
+
|
38
|
+
<main id="content" class="main-content" role="main">
|
39
|
+
<!-- Post listing -->
|
40
|
+
<div class="posts-container">
|
41
|
+
{% for post in site.posts %}
|
42
|
+
<article class="post-preview" data-tags="{{ post.tags | join: ' ' }}">
|
43
|
+
<h2>
|
44
|
+
<span class="post-date">{{ post.date | date: "%Y-%m-%d" }}</span>
|
45
|
+
<a href="{{ post.url }}">{{ post.title }}</a>
|
46
|
+
</h2>
|
47
|
+
{% if post.tags %}
|
48
|
+
<div class="post-tags">
|
49
|
+
{% for tag in post.tags %}
|
50
|
+
<span class="tag">{{ tag }}</span>
|
51
|
+
{% endfor %}
|
52
|
+
</div>
|
53
|
+
{% endif %}
|
54
|
+
<div class="post-excerpt">
|
55
|
+
{{ post.excerpt | strip_html | truncatewords:25 }}
|
56
|
+
</div>
|
57
|
+
</article>
|
58
|
+
{% endfor %}
|
59
|
+
</div>
|
60
|
+
|
61
|
+
<!-- No results message -->
|
62
|
+
<div id="no-results" class="hidden">
|
63
|
+
No posts found matching your criteria.
|
64
|
+
</div>
|
65
|
+
|
66
|
+
<footer class="site-footer">
|
67
|
+
<a href="/" class="back-link">← back to Home</a>
|
68
|
+
</footer>
|
69
|
+
</main>
|
70
|
+
|
71
|
+
<!-- ... existing code ... -->
|
72
|
+
|
73
|
+
<!-- Search and filter script -->
|
74
|
+
<script>
|
75
|
+
document.addEventListener('DOMContentLoaded', function () {
|
76
|
+
const searchInput = document.getElementById('search-input')
|
77
|
+
const postsContainer = document.querySelector('.posts-container')
|
78
|
+
const noResults = document.getElementById('no-results')
|
79
|
+
const tagButtons = document.querySelectorAll('.tag-button')
|
80
|
+
const activeTags = new Set()
|
81
|
+
let searchIndex = null
|
82
|
+
|
83
|
+
// Load and cache search index
|
84
|
+
async function loadSearchIndex() {
|
85
|
+
if (searchIndex) return searchIndex
|
86
|
+
|
87
|
+
try {
|
88
|
+
const response = await fetch('/search_index.json')
|
89
|
+
searchIndex = await response.json()
|
90
|
+
return searchIndex
|
91
|
+
} catch (error) {
|
92
|
+
console.error('Error loading search index:', error)
|
93
|
+
return { posts: [] }
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
function renderPost(post) {
|
98
|
+
return `
|
99
|
+
<article class="post-preview" data-tags="${post.tags.join(' ')}">
|
100
|
+
<h2>
|
101
|
+
<span class="post-date">${post.date}</span>
|
102
|
+
<a href="${post.url}">${post.title}</a>
|
103
|
+
</h2>
|
104
|
+
${post.tags.length ? `
|
105
|
+
<div class="post-tags">
|
106
|
+
${post.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
107
|
+
</div>
|
108
|
+
` : ''}
|
109
|
+
<div class="post-excerpt">
|
110
|
+
${post.excerpt}
|
111
|
+
</div>
|
112
|
+
</article>
|
113
|
+
`
|
114
|
+
}
|
115
|
+
|
116
|
+
async function filterPosts() {
|
117
|
+
const searchTerm = searchInput.value.toLowerCase()
|
118
|
+
const data = await loadSearchIndex()
|
119
|
+
|
120
|
+
const filteredPosts = data.posts.filter(post => {
|
121
|
+
const matchesSearch = searchTerm === '' ||
|
122
|
+
post.title.toLowerCase().includes(searchTerm) ||
|
123
|
+
post.content.toLowerCase().includes(searchTerm)
|
124
|
+
|
125
|
+
const postTags = new Set(post.tags)
|
126
|
+
const matchesTags = activeTags.size === 0 ||
|
127
|
+
Array.from(activeTags).every(tag => postTags.has(tag))
|
128
|
+
|
129
|
+
return matchesSearch && matchesTags
|
130
|
+
})
|
131
|
+
|
132
|
+
postsContainer.innerHTML = filteredPosts.map(renderPost).join('')
|
133
|
+
noResults.classList.toggle('hidden', filteredPosts.length > 0)
|
134
|
+
}
|
135
|
+
|
136
|
+
// Debounce function to limit how often filterPosts runs
|
137
|
+
function debounce(func, wait) {
|
138
|
+
let timeout
|
139
|
+
return function executedFunction(...args) {
|
140
|
+
const later = () => {
|
141
|
+
clearTimeout(timeout)
|
142
|
+
func(...args)
|
143
|
+
}
|
144
|
+
clearTimeout(timeout)
|
145
|
+
timeout = setTimeout(later, wait)
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
// Add event listeners
|
150
|
+
searchInput.addEventListener('input', debounce(filterPosts, 300))
|
151
|
+
|
152
|
+
tagButtons.forEach(button => {
|
153
|
+
button.addEventListener('click', () => {
|
154
|
+
const tag = button.dataset.tag
|
155
|
+
if (activeTags.has(tag)) {
|
156
|
+
activeTags.delete(tag)
|
157
|
+
button.classList.remove('active')
|
158
|
+
} else {
|
159
|
+
activeTags.add(tag)
|
160
|
+
button.classList.add('active')
|
161
|
+
}
|
162
|
+
filterPosts()
|
163
|
+
})
|
164
|
+
})
|
165
|
+
|
166
|
+
// Initial load of search index
|
167
|
+
loadSearchIndex()
|
168
|
+
})
|
169
|
+
</script>
|
170
|
+
|
171
|
+
</body>
|
172
|
+
|
173
|
+
</html>
|