klise 1.0.1 → 1.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 +4 -4
- data/README.md +40 -13
- data/_includes/footer.html +13 -5
- data/_includes/header.html +15 -2
- data/_includes/schema.html +56 -0
- data/_includes/toc.html +34 -0
- data/_layouts/404.html +24 -2
- data/_layouts/default.html +24 -2
- data/_layouts/page.html +24 -2
- data/_layouts/post.html +30 -4
- data/_sass/klise/_base.scss +24 -6
- data/_sass/klise/_dark.scss +20 -1
- data/_sass/klise/_fonts.scss +14 -0
- data/_sass/klise/_layout.scss +51 -4
- data/_sass/klise/_miscellaneous.scss +45 -0
- data/_sass/klise/_post.scss +94 -1
- metadata +29 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dc8b52939500630b7e1e4fc48e93f7b3aecf28e824234b79717c7f6fa6e31120
|
|
4
|
+
data.tar.gz: 31d160ae8043ee92676cc2a33bb02e3038cfd2861af1b8e7cd52947ba5318774
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67c5dc052e8feb591e3127f03adbb2053a3c7fd402c62a507c6c37a43e9ee68de76c9b79d4ec2d12c7a69d7bcf6e9991c4307e43eeabb63f0b0ccb5b8603f22a
|
|
7
|
+
data.tar.gz: 0d7bf3fbd21f4c1019f4e74047a9281e8be649e323998d10c78b40b329aae25653079f6aebe6abcde1a945bc7f60c069b65c2cfde6a323b6f96fcc35182e9ccf
|
data/README.md
CHANGED
|
@@ -5,15 +5,20 @@ For demo <a href="https://klise.now.sh" target="_blank" rel="noopener">klise.now
|
|
|
5
5
|
|
|
6
6
|
## Features
|
|
7
7
|
|
|
8
|
-
- [x] Light & Dark Mode support :waxing_crescent_moon:
|
|
8
|
+
- [x] Light & Dark Mode support, follows OS preference by default :waxing_crescent_moon:
|
|
9
9
|
- [x] Customizable (using `.scss`)
|
|
10
10
|
- [x] Responsive (desktop, tab and mobile)
|
|
11
|
+
- [x] RTL / LTR text direction support
|
|
11
12
|
- [x] Mobile First Design
|
|
12
13
|
- [x] SEO Optimized
|
|
14
|
+
- [x] schema.org structured data (JSON-LD)
|
|
13
15
|
- [x] Images of post Organized ([`jekyll-postfiles`](https://github.com/nhoizey/jekyll-postfiles))
|
|
16
|
+
- [x] Image lightbox (click an image in a post to zoom, no dependencies)
|
|
17
|
+
- [x] Image gallery (`<div class="gallery">`) — neat responsive rows of images
|
|
14
18
|
- [x] Generate Sitemap ([`jekyll-sitemap`](https://github.com/jekyll/jekyll-sitemap))
|
|
15
19
|
- [x] RSS Feed ([`jekyll-feed`](https://github.com/jekyll/jekyll-feed))
|
|
16
20
|
- [x] Syntax Highlighter ([`rouge`](https://github.com/rouge-ruby/rouge))
|
|
21
|
+
- [x] Table of contents, opt-in per post with `toc: true`
|
|
17
22
|
- [x] Next & Previous Post
|
|
18
23
|
- [x] Comment layout, enable in frontmatter if you wish
|
|
19
24
|
- [x] Google analytics
|
|
@@ -23,37 +28,59 @@ For demo <a href="https://klise.now.sh" target="_blank" rel="noopener">klise.now
|
|
|
23
28
|
|
|
24
29
|

|
|
25
30
|
|
|
26
|
-
## Backlogs
|
|
27
|
-
|
|
28
|
-
- [ ] Intergrated with PhotoSwipe.
|
|
29
|
-
- [ ] Add schema.org meta information.
|
|
30
|
-
- [ ] Transform class selector to BEM metodology.
|
|
31
|
-
|
|
32
31
|
## Installation
|
|
33
32
|
|
|
33
|
+
Requires **Ruby >= 3.0** and **Jekyll ~> 4.4**.
|
|
34
|
+
|
|
34
35
|
Run local server:
|
|
35
36
|
|
|
36
37
|
```bash
|
|
37
|
-
git clone https://github.com/piharpi/jekyll-klise.git
|
|
38
|
-
cd jekyll-klise
|
|
39
|
-
bundle install
|
|
40
|
-
bundle exec jekyll serve
|
|
38
|
+
$ git clone https://github.com/piharpi/jekyll-klise.git
|
|
39
|
+
$ cd jekyll-klise
|
|
40
|
+
$ bundle install
|
|
41
|
+
$ bundle exec jekyll serve
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
Navigate to `localhost:4000`. You're Welcome, Fork and be Stargazer.
|
|
44
45
|
|
|
45
|
-
[](https://app.netlify.com/start/deploy?repository=https://github.com/piharpi/jekyll-klise) [](https://vercel.com/import/project?template=https://github.com/piharpi/jekyll-klise)
|
|
46
|
+
[](https://app.netlify.com/start/deploy?repository=https://github.com/piharpi/jekyll-klise) [](https://vercel.com/import/project?template=https://github.com/piharpi/jekyll-klise) [](https://portal.azure.com/?feature.customportal=false&WT.mc_id=javascript-0000-jopapa#create/Microsoft.StaticApp)
|
|
47
|
+
|
|
48
|
+
## Table of contents
|
|
49
|
+
|
|
50
|
+
Add `toc: true` to a post's front matter to render an automatic table of
|
|
51
|
+
contents (built from its `h2`/`h3` headings) above the article:
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
---
|
|
55
|
+
title: My post
|
|
56
|
+
toc: true
|
|
57
|
+
---
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Text direction (RTL)
|
|
61
|
+
|
|
62
|
+
Set the site-wide direction in `_config.yml`:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
direction: rtl # "ltr" (default) | "rtl"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
You can override it per page/post in the front matter with `direction: rtl`.
|
|
69
|
+
Post content also resolves its direction per paragraph, so an LTR site can
|
|
70
|
+
host individual RTL posts (and vice versa) without extra markup.
|
|
46
71
|
|
|
47
72
|
## Limitation
|
|
48
73
|
|
|
49
|
-
- Since [`jekyll-postfiles`](https://github.com/nhoizey/jekyll-postfiles#compatibility) plugin isn't supported by github pages, this cause will make your site problems, path broken or post images won't show up, you can host alternatively using likes [netlify.com](https://netlify.com), [vercel.com](https://vercel.com) or [surge.sh](https://surge.sh) services, which support 3rd party.
|
|
74
|
+
- Since [`jekyll-postfiles`](https://github.com/nhoizey/jekyll-postfiles#compatibility) plugin isn't supported by github pages, this cause will make your site problems, path broken or post images won't show up, you can host alternatively using likes [netlify.com](https://netlify.com), [vercel.com](https://vercel.com), [azure.com](https://docs.microsoft.com/azure/static-web-apps/publish-jekyll) or [surge.sh](https://surge.sh) services, which support 3rd party.
|
|
50
75
|
|
|
51
76
|
## Contributing
|
|
52
77
|
|
|
53
78
|
If you see any typos or formatting errors in a post, or want to helping reduce backlogs or any other issue that needs to be addressed, please do not hesitate to open a pull request and fix it!, please read [contributing](./CONTRIBUTING.md) before PR.
|
|
54
79
|
|
|
55
80
|
Yeaaa feel free to open a pull request.
|
|
81
|
+
## Support
|
|
56
82
|
|
|
83
|
+
[](https://ko-fi.com/W7W7MJ4X) [](https://saweria.co/piharpi)
|
|
57
84
|
## License
|
|
58
85
|
|
|
59
86
|
This project is open source and available under the [MIT License](LICENSE).
|
data/_includes/footer.html
CHANGED
|
@@ -18,12 +18,20 @@
|
|
|
18
18
|
</small>
|
|
19
19
|
</footer>
|
|
20
20
|
<script src="/assets/js/main.js" defer="defer"></script>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<script
|
|
21
|
+
{%- if site.google_analytics -%}
|
|
22
|
+
<!-- Google tag (gtag.js) -->
|
|
23
|
+
<script
|
|
24
|
+
async
|
|
25
|
+
src="https://www.googletagmanager.com/gtag/js?id={{ site.google_analytics }}"
|
|
26
|
+
></script>
|
|
24
27
|
<script>
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
window.dataLayer = window.dataLayer || [];
|
|
29
|
+
function gtag() {
|
|
30
|
+
dataLayer.push(arguments);
|
|
31
|
+
}
|
|
32
|
+
gtag("js", new Date());
|
|
33
|
+
|
|
34
|
+
gtag("config", "{{ site.google_analytics }}");
|
|
27
35
|
</script>
|
|
28
36
|
{%- endif -%}
|
|
29
37
|
{%- if page.url == '/archive/' -%}
|
data/_includes/header.html
CHANGED
|
@@ -59,13 +59,13 @@
|
|
|
59
59
|
<meta
|
|
60
60
|
property="og:site_name"
|
|
61
61
|
content="{% if page.title %}{{ page.title | escape }} | {{
|
|
62
|
-
site.author.
|
|
62
|
+
site.author.name
|
|
63
63
|
}}{% else %}{{ site.title | escape }}{% endif %}"
|
|
64
64
|
/>
|
|
65
65
|
<meta
|
|
66
66
|
property="og:title"
|
|
67
67
|
content="{% if page.title %}{{ page.title | escape }} | {{
|
|
68
|
-
site.author.
|
|
68
|
+
site.author.name
|
|
69
69
|
}}{% else %}{{ site.title | escape }}{% endif %}"
|
|
70
70
|
/>
|
|
71
71
|
{% if page.location %}
|
|
@@ -161,4 +161,17 @@
|
|
|
161
161
|
<meta name="theme-color" content="#2c2c2c" />
|
|
162
162
|
|
|
163
163
|
<link rel="stylesheet" href="/assets/css/style.css" />
|
|
164
|
+
|
|
165
|
+
<!-- for mathjax support -->
|
|
166
|
+
{% if page.usemathjax %}
|
|
167
|
+
<script type="text/x-mathjax-config">
|
|
168
|
+
MathJax.Hub.Config({
|
|
169
|
+
TeX: { equationNumbers: { autoNumber: "AMS" } }
|
|
170
|
+
});
|
|
171
|
+
</script>
|
|
172
|
+
<script type="text/javascript" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
173
|
+
{% endif %}
|
|
174
|
+
|
|
175
|
+
{% include schema.html %}
|
|
176
|
+
|
|
164
177
|
</head>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
schema.org structured data (JSON-LD).
|
|
3
|
+
Emits BlogPosting for posts and WebSite for every other page.
|
|
4
|
+
{%- endcomment -%}
|
|
5
|
+
{%- capture description -%}
|
|
6
|
+
{{ page.description | default: page.excerpt | default: site.description | strip_html | normalize_whitespace | truncate: 200 }}
|
|
7
|
+
{%- endcapture -%}
|
|
8
|
+
{%- assign description = description | strip -%}
|
|
9
|
+
{%- if page.image -%}
|
|
10
|
+
{%- assign page_image = page.image | absolute_url -%}
|
|
11
|
+
{%- else -%}
|
|
12
|
+
{%- assign page_image = site.image | absolute_url -%}
|
|
13
|
+
{%- endif -%}
|
|
14
|
+
|
|
15
|
+
<script type="application/ld+json">
|
|
16
|
+
{%- if page.layout == 'post' -%}
|
|
17
|
+
{
|
|
18
|
+
"@context": "https://schema.org",
|
|
19
|
+
"@type": "BlogPosting",
|
|
20
|
+
"mainEntityOfPage": {
|
|
21
|
+
"@type": "WebPage",
|
|
22
|
+
"@id": {{ page.url | absolute_url | jsonify }}
|
|
23
|
+
},
|
|
24
|
+
"headline": {{ page.title | jsonify }},
|
|
25
|
+
"description": {{ description | jsonify }},
|
|
26
|
+
"image": {{ page_image | jsonify }},
|
|
27
|
+
"datePublished": {{ page.date | date_to_xmlschema | jsonify }},
|
|
28
|
+
"dateModified": {{ page.modified | default: page.date | date_to_xmlschema | jsonify }},
|
|
29
|
+
"author": {
|
|
30
|
+
"@type": "Person",
|
|
31
|
+
"name": {{ site.author.name | jsonify }},
|
|
32
|
+
"url": {{ site.url | append: site.baseurl | jsonify }}
|
|
33
|
+
},
|
|
34
|
+
"publisher": {
|
|
35
|
+
"@type": "Organization",
|
|
36
|
+
"name": {{ site.author.name | jsonify }},
|
|
37
|
+
"logo": {
|
|
38
|
+
"@type": "ImageObject",
|
|
39
|
+
"url": {{ site.author.avatar | default: site.image | absolute_url | jsonify }}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
{%- else -%}
|
|
44
|
+
{
|
|
45
|
+
"@context": "https://schema.org",
|
|
46
|
+
"@type": "WebSite",
|
|
47
|
+
"name": {{ site.title | jsonify }},
|
|
48
|
+
"url": {{ site.url | append: site.baseurl | jsonify }},
|
|
49
|
+
"description": {{ description | jsonify }},
|
|
50
|
+
"author": {
|
|
51
|
+
"@type": "Person",
|
|
52
|
+
"name": {{ site.author.name | jsonify }}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
{%- endif -%}
|
|
56
|
+
</script>
|
data/_includes/toc.html
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Builds a table of contents from the h2/h3 headings in the given HTML.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
{% include toc.html html=content %}
|
|
6
|
+
|
|
7
|
+
Optional parameters:
|
|
8
|
+
* title (string) : "Table of Contents" - heading shown above the list
|
|
9
|
+
{% endcomment %}
|
|
10
|
+
|
|
11
|
+
{%- assign toc_nodes = include.html | split: '<h' -%}
|
|
12
|
+
{%- capture toc_items -%}
|
|
13
|
+
{%- for node in toc_nodes -%}
|
|
14
|
+
{%- assign level = node | slice: 0, 1 -%}
|
|
15
|
+
{%- if level == '2' or level == '3' -%}
|
|
16
|
+
{%- assign heading = node | split: '</h' | first -%}
|
|
17
|
+
{%- if heading contains 'id="' -%}
|
|
18
|
+
{%- assign id = heading | split: 'id="' | last | split: '"' | first -%}
|
|
19
|
+
{%- assign text = heading | split: '>' | last | strip_html | strip -%}
|
|
20
|
+
<li class="toc-item toc-h{{ level }}"><a href="#{{ id }}">{{ text }}</a></li>
|
|
21
|
+
{%- endif -%}
|
|
22
|
+
{%- endif -%}
|
|
23
|
+
{%- endfor -%}
|
|
24
|
+
{%- endcapture -%}
|
|
25
|
+
{%- assign toc_items = toc_items | strip -%}
|
|
26
|
+
|
|
27
|
+
{%- if toc_items != '' -%}
|
|
28
|
+
<nav class="toc" aria-label="Table of contents">
|
|
29
|
+
<p class="toc-title">{{ include.title | default: 'Table of Contents' }}</p>
|
|
30
|
+
<ul class="toc-list">
|
|
31
|
+
{{ toc_items }}
|
|
32
|
+
</ul>
|
|
33
|
+
</nav>
|
|
34
|
+
{%- endif -%}
|
data/_layouts/404.html
CHANGED
|
@@ -3,10 +3,32 @@ layout: compress
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
<!DOCTYPE html>
|
|
6
|
-
<html lang="{{ page.lang | default: site.lang | default: " en " }}">
|
|
6
|
+
<html lang="{{ page.lang | default: site.lang | default: " en " }}" dir="{{ page.direction | default: site.direction | default: 'ltr' }}">
|
|
7
7
|
|
|
8
8
|
{% include header.html %}
|
|
9
|
-
<body>
|
|
9
|
+
<body data-theme="{{ site.mode }}" class="notransition">
|
|
10
|
+
|
|
11
|
+
<script>
|
|
12
|
+
const body = document.body;
|
|
13
|
+
|
|
14
|
+
const initTheme = (state) => {
|
|
15
|
+
if (state === "dark") {
|
|
16
|
+
body.setAttribute("data-theme", "dark");
|
|
17
|
+
} else if (state === "light") {
|
|
18
|
+
body.removeAttribute("data-theme");
|
|
19
|
+
} else {
|
|
20
|
+
// No stored preference yet: follow the OS color scheme.
|
|
21
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
22
|
+
? body.setAttribute("data-theme", "dark")
|
|
23
|
+
: body.removeAttribute("data-theme");
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
initTheme(localStorage.getItem("theme"));
|
|
28
|
+
|
|
29
|
+
setTimeout(() => body.classList.remove("notransition"), 75);
|
|
30
|
+
</script>
|
|
31
|
+
|
|
10
32
|
{% include navbar.html %}
|
|
11
33
|
<div class="wrapper">
|
|
12
34
|
<main aria-label="Content">
|
data/_layouts/default.html
CHANGED
|
@@ -2,10 +2,32 @@
|
|
|
2
2
|
layout: compress
|
|
3
3
|
---
|
|
4
4
|
<!DOCTYPE html>
|
|
5
|
-
<html lang="{{ page.lang | default: site.lang | default: " en " }}">
|
|
5
|
+
<html lang="{{ page.lang | default: site.lang | default: " en " }}" dir="{{ page.direction | default: site.direction | default: 'ltr' }}">
|
|
6
6
|
{% include header.html %}
|
|
7
7
|
|
|
8
|
-
<body data-theme="{{ site.mode }}">
|
|
8
|
+
<body data-theme="{{ site.mode }}" class="notransition">
|
|
9
|
+
|
|
10
|
+
<script>
|
|
11
|
+
const body = document.body;
|
|
12
|
+
|
|
13
|
+
const initTheme = (state) => {
|
|
14
|
+
if (state === "dark") {
|
|
15
|
+
body.setAttribute("data-theme", "dark");
|
|
16
|
+
} else if (state === "light") {
|
|
17
|
+
body.removeAttribute("data-theme");
|
|
18
|
+
} else {
|
|
19
|
+
// No stored preference yet: follow the OS color scheme.
|
|
20
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
21
|
+
? body.setAttribute("data-theme", "dark")
|
|
22
|
+
: body.removeAttribute("data-theme");
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
initTheme(localStorage.getItem("theme"));
|
|
27
|
+
|
|
28
|
+
setTimeout(() => body.classList.remove("notransition"), 75);
|
|
29
|
+
</script>
|
|
30
|
+
|
|
9
31
|
{% include navbar.html %}
|
|
10
32
|
<div class="wrapper">
|
|
11
33
|
{% include author.html %}
|
data/_layouts/page.html
CHANGED
|
@@ -3,11 +3,33 @@ layout: compress
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
<!DOCTYPE html>
|
|
6
|
-
<html lang="{{ page.lang | default: site.lang | default: " en " }}">
|
|
6
|
+
<html lang="{{ page.lang | default: site.lang | default: " en " }}" dir="{{ page.direction | default: site.direction | default: 'ltr' }}">
|
|
7
7
|
|
|
8
8
|
{% include header.html %}
|
|
9
9
|
|
|
10
|
-
<body data-theme="{{ site.mode }}">
|
|
10
|
+
<body data-theme="{{ site.mode }}" class="notransition">
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
const body = document.body;
|
|
14
|
+
|
|
15
|
+
const initTheme = (state) => {
|
|
16
|
+
if (state === "dark") {
|
|
17
|
+
body.setAttribute("data-theme", "dark");
|
|
18
|
+
} else if (state === "light") {
|
|
19
|
+
body.removeAttribute("data-theme");
|
|
20
|
+
} else {
|
|
21
|
+
// No stored preference yet: follow the OS color scheme.
|
|
22
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
23
|
+
? body.setAttribute("data-theme", "dark")
|
|
24
|
+
: body.removeAttribute("data-theme");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
initTheme(localStorage.getItem("theme"));
|
|
29
|
+
|
|
30
|
+
setTimeout(() => body.classList.remove("notransition"), 75);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
11
33
|
{% include navbar.html %}
|
|
12
34
|
<div class="wrapper">
|
|
13
35
|
<header class="header">
|
data/_layouts/post.html
CHANGED
|
@@ -3,11 +3,33 @@ layout: compress
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
<!DOCTYPE html>
|
|
6
|
-
<html lang="{{ page.lang | default: site.lang | default: "en" }}">
|
|
6
|
+
<html lang="{{ page.lang | default: site.lang | default: "en" }}" dir="{{ page.direction | default: site.direction | default: 'ltr' }}">
|
|
7
7
|
|
|
8
8
|
{% include header.html %}
|
|
9
9
|
|
|
10
|
-
<body data-theme="{{ site.mode }}">
|
|
10
|
+
<body data-theme="{{ site.mode }}" class="notransition">
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
const body = document.body;
|
|
14
|
+
|
|
15
|
+
const initTheme = (state) => {
|
|
16
|
+
if (state === "dark") {
|
|
17
|
+
body.setAttribute("data-theme", "dark");
|
|
18
|
+
} else if (state === "light") {
|
|
19
|
+
body.removeAttribute("data-theme");
|
|
20
|
+
} else {
|
|
21
|
+
// No stored preference yet: follow the OS color scheme.
|
|
22
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
23
|
+
? body.setAttribute("data-theme", "dark")
|
|
24
|
+
: body.removeAttribute("data-theme");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
initTheme(localStorage.getItem("theme"));
|
|
29
|
+
|
|
30
|
+
setTimeout(() => body.classList.remove("notransition"), 75);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
11
33
|
{% include navbar.html %}
|
|
12
34
|
<div class="wrapper post">
|
|
13
35
|
<main class="page-content" aria-label="Content">
|
|
@@ -44,6 +66,10 @@ layout: compress
|
|
|
44
66
|
{% endif %}
|
|
45
67
|
</header>
|
|
46
68
|
|
|
69
|
+
{% if page.toc %}
|
|
70
|
+
{% include toc.html html=content %}
|
|
71
|
+
{% endif %}
|
|
72
|
+
|
|
47
73
|
<div class="page-content" itemprop="articleBody">
|
|
48
74
|
{% include anchor_headings.html html=content anchorClass="anchor-head" beforeHeading=true h_min=1 h_max=4 %}
|
|
49
75
|
{% if page.tweet %}
|
|
@@ -55,7 +81,7 @@ layout: compress
|
|
|
55
81
|
</article>
|
|
56
82
|
|
|
57
83
|
{% if page.comments %}
|
|
58
|
-
{% include comments.html%}
|
|
84
|
+
{% include comments.html %}
|
|
59
85
|
{% endif %}
|
|
60
86
|
|
|
61
87
|
</main>
|
|
@@ -71,4 +97,4 @@ layout: compress
|
|
|
71
97
|
</div>
|
|
72
98
|
</body>
|
|
73
99
|
|
|
74
|
-
</html>
|
|
100
|
+
</html>
|
data/_sass/klise/_base.scss
CHANGED
|
@@ -7,9 +7,28 @@
|
|
|
7
7
|
transition: background-color 75ms ease-in, border-color 75ms ease-in;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
.notransition {
|
|
11
|
+
-webkit-transition: none;
|
|
12
|
+
-moz-transition: none;
|
|
13
|
+
-ms-transition: none;
|
|
14
|
+
-o-transition: none;
|
|
15
|
+
transition: none;
|
|
16
|
+
}
|
|
17
|
+
|
|
10
18
|
html {
|
|
11
19
|
overflow-x: hidden;
|
|
20
|
+
overflow-y: scroll;
|
|
12
21
|
width: 100%;
|
|
22
|
+
// Give the canvas its own background. Safari does not always propagate
|
|
23
|
+
// the body background to the canvas when the body has `overflow-x:
|
|
24
|
+
// hidden`, which left the area below short pages blank (#45).
|
|
25
|
+
background-color: $white;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@media (prefers-color-scheme: dark) {
|
|
29
|
+
html {
|
|
30
|
+
background-color: $dark-black;
|
|
31
|
+
}
|
|
13
32
|
}
|
|
14
33
|
|
|
15
34
|
body,
|
|
@@ -139,7 +158,7 @@ ul {
|
|
|
139
158
|
top: -1px;
|
|
140
159
|
width: 1.2em;
|
|
141
160
|
position: relative;
|
|
142
|
-
margin-
|
|
161
|
+
margin-inline-start: -1.3em;
|
|
143
162
|
font-weight: 700;
|
|
144
163
|
}
|
|
145
164
|
}
|
|
@@ -154,10 +173,9 @@ ol {
|
|
|
154
173
|
content: counter(li);
|
|
155
174
|
display: inline-block;
|
|
156
175
|
width: 1em;
|
|
157
|
-
margin-
|
|
158
|
-
margin-
|
|
159
|
-
text-align:
|
|
160
|
-
direction: rtl;
|
|
176
|
+
margin-inline-end: 0.5em;
|
|
177
|
+
margin-inline-start: -1.6em;
|
|
178
|
+
text-align: end;
|
|
161
179
|
font-weight: $bold-weight;
|
|
162
180
|
font-size: $small-font-size;
|
|
163
181
|
}
|
|
@@ -167,7 +185,7 @@ ol {
|
|
|
167
185
|
ul,
|
|
168
186
|
ol {
|
|
169
187
|
margin-top: 0;
|
|
170
|
-
margin-
|
|
188
|
+
margin-inline-start: $spacing-full;
|
|
171
189
|
}
|
|
172
190
|
|
|
173
191
|
li {
|
data/_sass/klise/_dark.scss
CHANGED
|
@@ -234,12 +234,31 @@ body[data-theme="dark"] {
|
|
|
234
234
|
.solution:hover {
|
|
235
235
|
color: $dark-text-link-blue-active;
|
|
236
236
|
}
|
|
237
|
-
}
|
|
237
|
+
}
|
|
238
238
|
|
|
239
239
|
.search-article {
|
|
240
240
|
input[type="search"] {
|
|
241
241
|
color: $dark-text-base-color;
|
|
242
|
+
&::-webkit-input-placeholder {
|
|
243
|
+
color: rgba(128,128,128,0.8);
|
|
244
|
+
}
|
|
242
245
|
}
|
|
243
246
|
}
|
|
244
247
|
|
|
248
|
+
// Table of contents
|
|
249
|
+
.toc {
|
|
250
|
+
border-color: $dark-light;
|
|
251
|
+
|
|
252
|
+
.toc-title {
|
|
253
|
+
color: $dark-gray;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.toc-item a {
|
|
257
|
+
color: $dark-text-base-color;
|
|
258
|
+
|
|
259
|
+
&:hover {
|
|
260
|
+
color: $dark-text-link-blue;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
245
264
|
}
|
data/_sass/klise/_fonts.scss
CHANGED
|
@@ -710,3 +710,17 @@
|
|
|
710
710
|
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
|
|
711
711
|
U+FEFF, U+FFFD;
|
|
712
712
|
}
|
|
713
|
+
|
|
714
|
+
// Arabic / Farsi subset (Vazirmatn) mapped onto the Roboto family so RTL
|
|
715
|
+
// content renders with proper glyphs. Credit: @srezasm (PR #94).
|
|
716
|
+
@font-face {
|
|
717
|
+
font-family: "Roboto";
|
|
718
|
+
font-style: normal;
|
|
719
|
+
font-weight: 100 900;
|
|
720
|
+
font-display: swap;
|
|
721
|
+
src: url(https://fonts.gstatic.com/s/vazirmatn/v13/Dxxo8j6PP2D_kU2muijlGMWWMmk.woff2)
|
|
722
|
+
format("woff2");
|
|
723
|
+
unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891,
|
|
724
|
+
U+0898-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41,
|
|
725
|
+
U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
|
|
726
|
+
}
|
data/_sass/klise/_layout.scss
CHANGED
|
@@ -338,18 +338,27 @@
|
|
|
338
338
|
}
|
|
339
339
|
|
|
340
340
|
input[type="search"] {
|
|
341
|
-
border: 0;
|
|
342
341
|
top: 0;
|
|
343
342
|
left: 0;
|
|
344
|
-
|
|
343
|
+
border: 0;
|
|
345
344
|
width: 100%;
|
|
345
|
+
height: 40px;
|
|
346
|
+
outline: none;
|
|
347
|
+
position: absolute;
|
|
346
348
|
border-radius: 5px;
|
|
347
349
|
padding: 10px 10px 10px 35px;
|
|
348
|
-
font-size: $base-font-size;
|
|
349
350
|
color: $text-base-color;
|
|
351
|
+
-webkit-appearance: none;
|
|
352
|
+
font-size: $base-font-size;
|
|
350
353
|
background-color: rgba(128, 128, 128, 0.1);
|
|
351
354
|
border: 1px solid rgba(128, 128, 128, 0.1);
|
|
352
|
-
|
|
355
|
+
&::-webkit-input-placeholder {
|
|
356
|
+
color: #808080;
|
|
357
|
+
}
|
|
358
|
+
&::-webkit-search-decoration,
|
|
359
|
+
&::-webkit-search-results-decoration {
|
|
360
|
+
display: none;
|
|
361
|
+
}
|
|
353
362
|
}
|
|
354
363
|
}
|
|
355
364
|
|
|
@@ -368,4 +377,42 @@
|
|
|
368
377
|
border: 1px solid rgba(128, 128, 128, 0.1);
|
|
369
378
|
background-color: rgba(128, 128, 128, 0.1);
|
|
370
379
|
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// RTL adjustments: floats and relative offsets do not mirror on their
|
|
383
|
+
// own, so flip the pieces that are positioned by physical side.
|
|
384
|
+
[dir="rtl"] {
|
|
385
|
+
.menu {
|
|
386
|
+
a#mode {
|
|
387
|
+
float: right;
|
|
388
|
+
left: auto;
|
|
389
|
+
right: 8px;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.trigger {
|
|
393
|
+
float: left;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.menu-link:not(:last-child) {
|
|
397
|
+
margin-right: 0;
|
|
398
|
+
margin-left: 5px;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
@include media-query($on-mobile) {
|
|
402
|
+
a#mode {
|
|
403
|
+
left: auto;
|
|
404
|
+
right: 10px;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.menu-icon {
|
|
408
|
+
right: auto;
|
|
409
|
+
left: 0;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.post-item .post-item-date {
|
|
415
|
+
padding-right: 0;
|
|
416
|
+
padding-left: 10px;
|
|
417
|
+
}
|
|
371
418
|
}
|
|
@@ -39,3 +39,48 @@
|
|
|
39
39
|
position: absolute;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
// Image lightbox
|
|
44
|
+
.page-content img.zoomable {
|
|
45
|
+
cursor: zoom-in;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
body.lightbox-open {
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.lightbox-overlay {
|
|
53
|
+
position: fixed;
|
|
54
|
+
top: 0;
|
|
55
|
+
right: 0;
|
|
56
|
+
bottom: 0;
|
|
57
|
+
left: 0;
|
|
58
|
+
z-index: 100;
|
|
59
|
+
display: flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
padding: 20px;
|
|
63
|
+
cursor: zoom-out;
|
|
64
|
+
background-color: rgba(0, 0, 0, 0.85);
|
|
65
|
+
opacity: 0;
|
|
66
|
+
visibility: hidden;
|
|
67
|
+
transition: opacity 0.2s ease, visibility 0.2s ease;
|
|
68
|
+
|
|
69
|
+
&.is-open {
|
|
70
|
+
opacity: 1;
|
|
71
|
+
visibility: visible;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.lightbox-image {
|
|
75
|
+
max-width: 100%;
|
|
76
|
+
max-height: 100%;
|
|
77
|
+
border-radius: 2px;
|
|
78
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@media (prefers-reduced-motion: reduce) {
|
|
83
|
+
.lightbox-overlay {
|
|
84
|
+
transition: none;
|
|
85
|
+
}
|
|
86
|
+
}
|
data/_sass/klise/_post.scss
CHANGED
|
@@ -71,6 +71,22 @@
|
|
|
71
71
|
.page-content {
|
|
72
72
|
padding-top: 8px;
|
|
73
73
|
|
|
74
|
+
// Resolve direction per block from its own text, so a mostly-LTR
|
|
75
|
+
// theme can still host RTL content (and vice versa) without manual
|
|
76
|
+
// markup. In LTR text this behaves exactly like the defaults.
|
|
77
|
+
p,
|
|
78
|
+
li,
|
|
79
|
+
blockquote,
|
|
80
|
+
h1,
|
|
81
|
+
h2,
|
|
82
|
+
h3,
|
|
83
|
+
h4,
|
|
84
|
+
h5,
|
|
85
|
+
h6 {
|
|
86
|
+
unicode-bidi: plaintext;
|
|
87
|
+
text-align: start;
|
|
88
|
+
}
|
|
89
|
+
|
|
74
90
|
iframe {
|
|
75
91
|
text-align: center;
|
|
76
92
|
}
|
|
@@ -157,7 +173,7 @@
|
|
|
157
173
|
&::before {
|
|
158
174
|
content: "#";
|
|
159
175
|
position: absolute;
|
|
160
|
-
|
|
176
|
+
inset-inline-end: -3px;
|
|
161
177
|
width: 1em;
|
|
162
178
|
font-weight: $bold-weight;
|
|
163
179
|
}
|
|
@@ -191,6 +207,83 @@
|
|
|
191
207
|
}
|
|
192
208
|
}
|
|
193
209
|
|
|
210
|
+
// Table of contents
|
|
211
|
+
.toc {
|
|
212
|
+
margin-top: $spacing-full;
|
|
213
|
+
padding: 15px 20px;
|
|
214
|
+
border: 1px solid $light;
|
|
215
|
+
border-radius: 4px;
|
|
216
|
+
|
|
217
|
+
.toc-title {
|
|
218
|
+
margin: 0 0 8px;
|
|
219
|
+
color: $gray;
|
|
220
|
+
font-weight: $bold-weight;
|
|
221
|
+
font-size: $small-font-size;
|
|
222
|
+
letter-spacing: 0.5px;
|
|
223
|
+
text-transform: uppercase;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.toc-list {
|
|
227
|
+
margin: 0;
|
|
228
|
+
padding: 0;
|
|
229
|
+
list-style: none;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.toc-item {
|
|
233
|
+
line-height: 1.6;
|
|
234
|
+
|
|
235
|
+
&::before {
|
|
236
|
+
content: none;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
a {
|
|
240
|
+
color: $text-base-color;
|
|
241
|
+
text-decoration: none;
|
|
242
|
+
|
|
243
|
+
&:hover {
|
|
244
|
+
color: $text-link-blue;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.toc-h3 {
|
|
250
|
+
padding-left: 18px;
|
|
251
|
+
font-size: $small-font-size;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Image gallery: a neat, responsive row of equal-height images.
|
|
256
|
+
// Wrap images in <div class="gallery"> … </div>; each stays zoomable.
|
|
257
|
+
.page-content .gallery {
|
|
258
|
+
display: grid;
|
|
259
|
+
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
260
|
+
gap: 10px;
|
|
261
|
+
margin-top: $spacing-full - 15;
|
|
262
|
+
margin-bottom: $spacing-full - 15;
|
|
263
|
+
|
|
264
|
+
img {
|
|
265
|
+
width: 100%;
|
|
266
|
+
height: 180px;
|
|
267
|
+
margin: 0;
|
|
268
|
+
object-fit: cover;
|
|
269
|
+
border-radius: 2px;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
figure {
|
|
273
|
+
margin: 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Images inside list items render as small, aligned thumbnails so the
|
|
278
|
+
// list stays tidy. They remain zoomable via the lightbox.
|
|
279
|
+
.page-content li img {
|
|
280
|
+
max-height: 2.4em;
|
|
281
|
+
width: auto;
|
|
282
|
+
margin: 0 0.3em;
|
|
283
|
+
vertical-align: middle;
|
|
284
|
+
border-radius: 2px;
|
|
285
|
+
}
|
|
286
|
+
|
|
194
287
|
.post-nav {
|
|
195
288
|
display: flex;
|
|
196
289
|
position: relative;
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: klise
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mahendrata Harpi
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-10-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jekyll
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '4.
|
|
19
|
+
version: '4.4'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '4.
|
|
26
|
+
version: '4.4'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: jekyll-feed
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0.
|
|
33
|
+
version: '0.18'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0.
|
|
40
|
+
version: '0.18'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: jekyll-sitemap
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -58,14 +58,14 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 0.12
|
|
61
|
+
version: '0.12'
|
|
62
62
|
type: :runtime
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 0.12
|
|
68
|
+
version: '0.12'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: jekyll-postfiles
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,6 +80,20 @@ dependencies:
|
|
|
80
80
|
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '3.1'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: webrick
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '1.8'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '1.8'
|
|
83
97
|
- !ruby/object:Gem::Dependency
|
|
84
98
|
name: bundler
|
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -94,7 +108,7 @@ dependencies:
|
|
|
94
108
|
- - "~>"
|
|
95
109
|
- !ruby/object:Gem::Version
|
|
96
110
|
version: '2.1'
|
|
97
|
-
description:
|
|
111
|
+
description:
|
|
98
112
|
email:
|
|
99
113
|
- justharpi@gmail.com
|
|
100
114
|
executables: []
|
|
@@ -111,6 +125,8 @@ files:
|
|
|
111
125
|
- _includes/navbar.html
|
|
112
126
|
- _includes/navigation.html
|
|
113
127
|
- _includes/pagination.html
|
|
128
|
+
- _includes/schema.html
|
|
129
|
+
- _includes/toc.html
|
|
114
130
|
- _layouts/404.html
|
|
115
131
|
- _layouts/compress.html
|
|
116
132
|
- _layouts/default.html
|
|
@@ -130,7 +146,7 @@ licenses:
|
|
|
130
146
|
- MIT
|
|
131
147
|
metadata:
|
|
132
148
|
plugin_type: theme
|
|
133
|
-
post_install_message:
|
|
149
|
+
post_install_message:
|
|
134
150
|
rdoc_options: []
|
|
135
151
|
require_paths:
|
|
136
152
|
- lib
|
|
@@ -145,8 +161,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
145
161
|
- !ruby/object:Gem::Version
|
|
146
162
|
version: '0'
|
|
147
163
|
requirements: []
|
|
148
|
-
rubygems_version: 3.
|
|
149
|
-
signing_key:
|
|
164
|
+
rubygems_version: 3.5.22
|
|
165
|
+
signing_key:
|
|
150
166
|
specification_version: 4
|
|
151
167
|
summary: "\U0001F3D6 Klisé is a minimalist Jekyll theme for running a personal site
|
|
152
168
|
or blog, light & dark mode support."
|