jekyll-theme-satellite 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/assets/js/post.js ADDED
@@ -0,0 +1,197 @@
1
+ document.addEventListener('DOMContentLoaded', function(){
2
+ var content = document.querySelector('main');
3
+ let currentTheme = localStorage.getItem('theme');
4
+
5
+ // Lazy image loading
6
+ var images = content.querySelectorAll('img');
7
+
8
+ images.forEach((img) => {
9
+ img.setAttribute('loading', 'lazy');
10
+ });
11
+
12
+ // tocbot
13
+ var headings = content.querySelectorAll('h1, h2');
14
+ var headingMap = {};
15
+
16
+ Array.prototype.forEach.call(headings, function (heading) {
17
+ var id = heading.id ? heading.id : heading.textContent.trim().toLowerCase()
18
+ .split(' ').join('-').replace(/[\!\@\#\$\%\^\&\*\(\):]/ig, '');
19
+
20
+ headingMap[id] = !isNaN(headingMap[id]) ? ++headingMap[id] : 0;
21
+
22
+ if (headingMap[id]) {
23
+ heading.id = id + '-' + headingMap[id];
24
+ } else {
25
+ heading.id = id;
26
+ }
27
+ })
28
+
29
+ tocbot.init({
30
+ tocSelector: '.toc-board',
31
+ contentSelector: '.inner-content',
32
+ headingSelector:'h1, h2',
33
+ hasInnerContainers: false
34
+ });
35
+
36
+ // link (for hover effect)
37
+ var links = content.querySelectorAll('a:not(.related-item a)');
38
+
39
+ links.forEach((link) => {
40
+ link.setAttribute('data-content', link.innerText);
41
+ });
42
+
43
+ // code clipboard copy button
44
+ async function copyCode(block) {
45
+ let code = block.querySelector("code");
46
+ let text = code.innerText;
47
+
48
+ await navigator.clipboard.writeText(text);
49
+ }
50
+
51
+ let blocks = document.querySelectorAll("pre");
52
+
53
+ blocks.forEach((block) => {
54
+ // only add button if browser supports Clipboard API
55
+ if (navigator.clipboard) {
56
+ let clip_btn = document.createElement("button");
57
+ let clip_img = document.createElement("svg");
58
+
59
+ clip_btn.setAttribute('title', "Copy Code");
60
+ clip_img.ariaHidden = true;
61
+
62
+ block.appendChild(clip_btn);
63
+ clip_btn.appendChild(clip_img);
64
+
65
+ clip_btn.addEventListener("click", async () => {
66
+ await copyCode(block, clip_btn);
67
+ });
68
+ }
69
+ });
70
+
71
+ // Initialize/Change Giscus theme
72
+ var giscusTheme = "light";
73
+
74
+ const giscus_repo = $('meta[name="giscus_repo"]').attr("content");
75
+ const giscus_repoId = $('meta[name="giscus_repoId"]').attr("content");
76
+ const giscus_category = $('meta[name="giscus_category"]').attr("content");
77
+ const giscus_categoryId = $('meta[name="giscus_categoryId"]').attr("content");
78
+
79
+ console.log(giscus_repo);
80
+
81
+ if (giscus_repo !== undefined) {
82
+ if (currentTheme === 'dark'){
83
+ giscusTheme = "noborder_gray";
84
+ }
85
+
86
+ console.log("what?");
87
+
88
+ let giscusAttributes = {
89
+ "src": "https://giscus.app/client.js",
90
+ "data-repo": giscus_repo,
91
+ "data-repo-id": giscus_repoId,
92
+ "data-category": giscus_category,
93
+ "data-category-id": giscus_categoryId,
94
+ "data-mapping": "pathname",
95
+ "data-reactions-enabled": "1",
96
+ "data-emit-metadata": "1",
97
+ "data-theme": giscusTheme,
98
+ "data-lang": "en",
99
+ "crossorigin": "anonymous",
100
+ "async": "",
101
+ };
102
+
103
+ let giscusScript = document.createElement("script");
104
+ Object.entries(giscusAttributes).forEach(([key, value]) => giscusScript.setAttribute(key, value));
105
+ document.body.appendChild(giscusScript);
106
+
107
+ console.log("what??");
108
+ }
109
+
110
+ // Giscus IMetadataMessage event handler
111
+ function handleMessage(event) {
112
+ if (event.origin !== 'https://giscus.app') return;
113
+ if (!(typeof event.data === 'object' && event.data.giscus)) return;
114
+
115
+ const giscusData = event.data.giscus;
116
+
117
+ if (giscusData && giscusData.hasOwnProperty('discussion')) {
118
+ $('#num-comments').text(giscusData.discussion.totalCommentCount);
119
+ }
120
+ else {
121
+ $('#num-comments').text('0');
122
+ }
123
+ }
124
+
125
+ window.addEventListener('message', handleMessage);
126
+
127
+ // Tag EventListener
128
+ const searchPage = document.querySelector("#search");
129
+
130
+ document.querySelectorAll('.tag-box').forEach(function(tagButton){
131
+ tagButton.addEventListener('click', function() {
132
+ const contentID = tagButton.getAttribute('contentID');
133
+ searchPage.classList.add('active');
134
+
135
+ $('#search-input').val(contentID);
136
+ $('#search-input').trigger('keyup');
137
+ });
138
+ });
139
+
140
+ // Page Hits
141
+ const pageHits = document.getElementById('page-hits');
142
+
143
+ if (pageHits) {
144
+ const goatcounterCode = pageHits.getAttribute('usercode');
145
+ const requestURL = 'https://'
146
+ + goatcounterCode
147
+ + '.goatcounter.com/counter/'
148
+ + encodeURIComponent(location.pathname)
149
+ + '.json';
150
+
151
+ var resp = new XMLHttpRequest();
152
+ resp.open('GET', requestURL);
153
+ resp.onerror = function() { pageHits.innerText = "0"; };
154
+ resp.onload = function() { pageHits.innerText = JSON.parse(this.responseText).count; };
155
+ resp.send();
156
+ }
157
+
158
+ // Sweat Scroll
159
+ const scroller = new SweetScroll({
160
+ /* some options */
161
+ });
162
+
163
+ // Move to Top
164
+ if (document.querySelector('.thumbnail')){
165
+ const arrowButton = document.querySelector('.top-arrow');
166
+
167
+ setInterval(function(){
168
+ var scrollPos = document.documentElement.scrollTop;
169
+
170
+ if (scrollPos < 512){
171
+ arrowButton.classList.remove('arrow-open');
172
+ }
173
+ else {
174
+ arrowButton.classList.add('arrow-open');
175
+ }
176
+ }, 1000);
177
+ }
178
+
179
+ // Code highlighter
180
+ if (currentTheme === 'dark'){
181
+ // Disable highlighter default color theme
182
+ document.getElementById("highlight-default").disabled=true;
183
+ }
184
+ else {
185
+ // Disable highlighter dark color theme
186
+ document.getElementById("highlight-dark").disabled=true;
187
+ }
188
+
189
+ hljs.highlightAll();
190
+
191
+ // Disable code highlights to the plaintext codeblocks
192
+ document.querySelectorAll('.language-text, .language-plaintext').forEach(function(codeblock){
193
+ codeblock.querySelectorAll('.hljs-keyword, .hljs-meta, .hljs-selector-tag').forEach(function($){
194
+ $.outerHTML = $.innerHTML;
195
+ });
196
+ });
197
+ });
@@ -0,0 +1,168 @@
1
+ function searchPost(pages){
2
+ $('#search-input').on('keyup', function () {
3
+ var keyword = this.value.toLowerCase();
4
+ var searchResult = [];
5
+
6
+ if (keyword.length > 0) {
7
+ $('#search-result').show();
8
+ $('#btn-clear').show();
9
+ } else {
10
+ $('#search-result').hide();
11
+ $('#btn-clear').hide();
12
+ }
13
+
14
+ $('.result-item').remove();
15
+
16
+ for (var i = 0; i < pages.length; i++) {
17
+ var post = pages[i];
18
+
19
+ if (post.title === 'Home' && post.type == 'category') continue;
20
+
21
+ if (post.title.toLowerCase().indexOf(keyword) >= 0
22
+ || post.path.toLowerCase().indexOf(keyword) >= 0
23
+ || post.tags.toLowerCase().indexOf(keyword) >= 0){
24
+ searchResult.push(post);
25
+ }
26
+ }
27
+
28
+ if (searchResult.length === 0) {
29
+ $('#search-result').append(
30
+ '<li class="result-item"><span class="description">There is no search result.</span></li>'
31
+ );
32
+
33
+ return;
34
+ }
35
+
36
+ searchResult.sort(function (a, b) {
37
+ if (a.type == 'category') return 1;
38
+
39
+ return -1;
40
+ });
41
+
42
+ for (var i = 0; i < searchResult.length; i++) {
43
+ var highlighted_path = highlightKeyword(searchResult[i].path, keyword);
44
+
45
+ if (highlighted_path === '')
46
+ highlighted_path = "Home";
47
+
48
+ if (searchResult[i].type === 'post'){
49
+ var highlighted_title = highlightKeyword(searchResult[i].title, keyword);
50
+ var highlighted_tags = highlightKeyword(searchResult[i].tags, keyword);
51
+
52
+ if (highlighted_tags === '')
53
+ highlighted_tags = "none";
54
+
55
+ $('#search-result').append(
56
+ '<li class="result-item"><a href="' +
57
+ searchResult[i].url +
58
+ '"><table><thead><tr><th><svg class="ico-book"></svg></th><th>' + highlighted_title +
59
+ '</th></tr></thead><tbody><tr><td><svg class="ico-folder"></svg></td><td>' + highlighted_path +
60
+ '</td></tr><tr><td><svg class="ico-tags"></svg></td><td>' + highlighted_tags +
61
+ '</td></tr><tr><td><svg class="ico-calendar"></svg></td><td>' + searchResult[i].date +
62
+ '</td></tr></tbody></table></a></li>'
63
+ );
64
+ }
65
+ else {
66
+ $('#search-result').append(
67
+ '<li class="result-item"><a href="' +
68
+ searchResult[i].url +
69
+ '"><table><thead><tr><th><svg class="ico-folder"></svg></th><th>' + highlighted_path +
70
+ '</th></tr></thead></table></a></li>'
71
+ );
72
+ }
73
+ }
74
+ });
75
+
76
+ function highlightKeyword(txt, keyword) {
77
+ var index = txt.toLowerCase().lastIndexOf(keyword);
78
+
79
+ if (index >= 0) {
80
+ out = txt.substring(0, index) +
81
+ "<span class='highlight'>" +
82
+ txt.substring(index, index+keyword.length) +
83
+ "</span>" +
84
+ txt.substring(index + keyword.length);
85
+ return out;
86
+ }
87
+
88
+ return txt;
89
+ }
90
+ }
91
+
92
+ function searchRelated(pages){
93
+ const refBox = document.getElementById('related-box');
94
+
95
+ if (!refBox) return;
96
+
97
+ var relatedPosts = [];
98
+ var currPost = pages.find(obj => {return obj.url === location.pathname});
99
+
100
+ let currTags = currPost.tags.split(', ');
101
+ let currCategory = currPost.path.split(' > ').pop();
102
+
103
+ for (var i = 0; i < pages.length; i++) {
104
+ let page = pages[i];
105
+
106
+ if (page.type === 'category') continue;
107
+
108
+ if (page.title === currPost.title) continue;
109
+
110
+ let tags = page.tags.split(', ');
111
+ let category = page.path.split(' > ').pop();
112
+ let correlationScore = 0;
113
+
114
+ for (var j = 0; j < currTags.length; j++){
115
+ if (tags.indexOf(currTags[j]) != -1) correlationScore += 1;
116
+ }
117
+
118
+ if (category === currCategory) correlationScore += 1;
119
+
120
+ if (correlationScore == 0) continue;
121
+
122
+ relatedPosts.push({
123
+ 'title': page.title,
124
+ 'date': page.date,
125
+ 'category': category,
126
+ 'url': page.url,
127
+ 'thumbnail': page.image,
128
+ 'score': correlationScore
129
+ });
130
+ }
131
+
132
+ relatedPosts.sort(function (a, b) {
133
+ if(a.hasOwnProperty('score')){
134
+ return b.score - a.score;
135
+ }
136
+ });
137
+
138
+ if (relatedPosts.length == 0){
139
+ $('#related-box').hide();
140
+ return;
141
+ }
142
+
143
+ for (var i = 0; i < Math.min(relatedPosts.length, 6); i++){
144
+ let post = relatedPosts[i];
145
+ let date = '-';
146
+ let category = 'No category';
147
+
148
+ if (post.date !== '1900-01-01'){
149
+ date = new Date(post.date);
150
+ date = date.toLocaleString('en-US', {day: 'numeric', month:'long', year:'numeric'});
151
+ }
152
+
153
+ if (post.category !== '') category = post.category;
154
+
155
+ if (post.thumbnail === ''){
156
+ post.thumbnail = "/assets/img/thumbnail/empty.jpg";
157
+ }
158
+
159
+ $('#related-posts').append(
160
+ '<li class="related-item"><a href="' + post.url +
161
+ '"><img src="' + post.thumbnail +
162
+ '"/><p class="category">' + category +
163
+ '</p><p class="title">' + post.title +
164
+ '</p><p class="date">' + date +
165
+ '</p></a></li>'
166
+ );
167
+ }
168
+ }
@@ -0,0 +1,132 @@
1
+ document.addEventListener('DOMContentLoaded', function(){
2
+ // Loading page
3
+ window.addEventListener("load", () => {
4
+ var load_div = document.querySelector('#loading');
5
+
6
+ if(load_div != null){
7
+ setTimeout(function(){
8
+ load_div.style.transition = '.75s';
9
+ load_div.style.opacity = '0';
10
+ load_div.style.visibility = 'hidden';
11
+ }, 800);
12
+ }
13
+ });
14
+
15
+ // pagination
16
+ const paginationNumbers = document.querySelector("#pagination-numbers");
17
+ const paginatedList = document.querySelector(".paginated-list");
18
+
19
+ if (paginatedList) {
20
+ const listItems = paginatedList.querySelectorAll("li");
21
+ const nextButton = document.querySelector("#next-button");
22
+ const prevButton = document.querySelector("#prev-button");
23
+ const pageKey = "pageKey=" + document.URL;
24
+
25
+ const paginationLimit = 5;
26
+ const pageCount = Math.ceil(listItems.length / paginationLimit);
27
+ let currentPage = 1;
28
+
29
+ const disableButton = (button) => {
30
+ button.classList.add("disabled");
31
+ button.setAttribute("disabled", true);
32
+ };
33
+
34
+ const enableButton = (button) => {
35
+ button.classList.remove("disabled");
36
+ button.removeAttribute("disabled");
37
+ };
38
+
39
+ const handlePageButtonsStatus = () => {
40
+ if (currentPage === 1) {
41
+ disableButton(prevButton);
42
+ } else {
43
+ enableButton(prevButton);
44
+ }
45
+
46
+ if (pageCount === currentPage) {
47
+ disableButton(nextButton);
48
+ } else {
49
+ enableButton(nextButton);
50
+ }
51
+ };
52
+
53
+ const handleActivePageNumber = () => {
54
+ document.querySelectorAll(".pagination-number").forEach((button) => {
55
+ button.classList.remove("active");
56
+
57
+ const pageIndex = Number(button.getAttribute("page-index"));
58
+
59
+ if (pageIndex == currentPage) {
60
+ button.classList.add("active");
61
+ }
62
+ });
63
+ };
64
+
65
+ const appendPageNumber = (index) => {
66
+ const pageNumber = document.createElement("button");
67
+
68
+ pageNumber.className = "pagination-number";
69
+ pageNumber.innerHTML = index;
70
+ pageNumber.setAttribute("page-index", index);
71
+ pageNumber.setAttribute("aria-label", "Page " + index);
72
+
73
+ paginationNumbers.appendChild(pageNumber);
74
+ };
75
+
76
+ const getPaginationNumbers = () => {
77
+ for (let i = 1; i <= pageCount; i++) {
78
+ appendPageNumber(i);
79
+ }
80
+ };
81
+
82
+ const setCurrentPage = (pageNum) => {
83
+ currentPage = pageNum;
84
+
85
+ handleActivePageNumber();
86
+ handlePageButtonsStatus();
87
+
88
+ const prevRange = (pageNum - 1) * paginationLimit;
89
+ const currRange = pageNum * paginationLimit;
90
+
91
+ listItems.forEach((item, index) => {
92
+ item.classList.add("hidden");
93
+
94
+ if (index >= prevRange && index < currRange) {
95
+ item.classList.remove("hidden");
96
+ }
97
+ });
98
+
99
+ $('html, body').scrollTop(0);
100
+ localStorage.setItem(pageKey, currentPage);
101
+ };
102
+
103
+ window.addEventListener("load", (event) => {
104
+ // Load last visited page number
105
+ if (event.persisted
106
+ || (window.performance && window.performance.navigation.type == 2)) {
107
+ currentPage = localStorage.getItem(pageKey);
108
+ }
109
+
110
+ getPaginationNumbers();
111
+ setCurrentPage(currentPage);
112
+
113
+ prevButton.addEventListener("click", () => {
114
+ setCurrentPage(currentPage - 1);
115
+ });
116
+
117
+ nextButton.addEventListener("click", () => {
118
+ setCurrentPage(currentPage + 1);
119
+ });
120
+
121
+ document.querySelectorAll(".pagination-number").forEach((button) => {
122
+ const pageIndex = Number(button.getAttribute("page-index"));
123
+
124
+ if (pageIndex) {
125
+ button.addEventListener("click", () => {
126
+ setCurrentPage(pageIndex);
127
+ });
128
+ }
129
+ });
130
+ });
131
+ }
132
+ });
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-theme-satellite
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yankos
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-29 00:00:00.000000000 Z
11
+ date: 2024-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -24,6 +24,48 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jekyll-feed
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.12'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jekyll-sitemap
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jekyll-seo-tag
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.6'
27
69
  description:
28
70
  email:
29
71
  - byanko55@gmail.com
@@ -32,14 +74,19 @@ extensions: []
32
74
  extra_rdoc_files: []
33
75
  files:
34
76
  - LICENSE
35
- - _config.yml
77
+ - README.md
78
+ - _includes/category.html
79
+ - _includes/footer.html
80
+ - _includes/head.html
36
81
  - _includes/loading.html
37
82
  - _includes/navigation.html
38
83
  - _includes/pagination.html
39
84
  - _includes/post.html
40
85
  - _includes/search.html
86
+ - _includes/search_event.html
41
87
  - _includes/sidebar.html
42
88
  - _layouts/default.html
89
+ - _layouts/page.html
43
90
  - _sass/darkmode.scss
44
91
  - _sass/layout.scss
45
92
  - _sass/navigation.scss
@@ -49,6 +96,8 @@ files:
49
96
  - _sass/sidebar.scss
50
97
  - _sass/toc.scss
51
98
  - _sass/vars.scss
99
+ - assets/css/404.scss
100
+ - assets/css/fonts.scss
52
101
  - assets/css/highlight-dark.min.css
53
102
  - assets/css/highlight-default.min.css
54
103
  - assets/css/style.scss
@@ -73,9 +122,13 @@ files:
73
122
  - assets/img/thumbnail/sample.png
74
123
  - assets/img/tile.png
75
124
  - assets/js/404.js
125
+ - assets/js/background.js
126
+ - assets/js/common.js
127
+ - assets/js/fontfaceobserver.js
76
128
  - assets/js/highlight.min.js
77
- - assets/js/main.js
78
- - assets/js/stars.js
129
+ - assets/js/post.js
130
+ - assets/js/search.js
131
+ - assets/js/subject.js
79
132
  - assets/js/sweet-scroll.min.js
80
133
  - assets/js/tocbot.min.js
81
134
  homepage: https://github.com/byanko55/jekyll-theme-satellite
data/_config.yml DELETED
@@ -1,82 +0,0 @@
1
- # Welcome to Jekyll!
2
- #
3
- # This config file is meant for settings that affect your whole blog, values
4
- # which you are expected to set up once and rarely edit after that. If you find
5
- # yourself editing this file very often, consider using Jekyll's data files
6
- # feature for the data you need to update frequently.
7
- #
8
- # For technical reasons, this file is *NOT* reloaded automatically when you use
9
- # 'bundle exec jekyll serve'. If you change this file, please restart the server process.
10
- #
11
- # If you need help with YAML syntax, here are some quick references for you:
12
- # https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
13
- # https://learnxinyminutes.com/docs/yaml/
14
- #
15
- # Site settings
16
- # These are used to personalize your new site. If you look in the HTML files,
17
- # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
18
- # You can create any custom variable you would like, and they will be accessible
19
- # in the templates via {{ site.myvariable }}.
20
-
21
- title: Example.com
22
- username: username
23
- email: example@gmail.com
24
- github_username: github
25
- twitter_username: twitter
26
- instagram_username: instagram
27
- linkedin_username: linkedin
28
- facebook_username: facebook
29
- description: "Satellite - jekyll blog theme"
30
- baseurl: "" # the subpath of your site, e.g. /blog
31
- url: "localhost:4000" # the base hostname & protocol for your site, e.g. http://example.com
32
- repo_url: "https://github.com/byanko55/jekyll-theme-satellite"
33
- goatcounter_code:
34
- google_analytics:
35
-
36
- # Build settings
37
- plugins:
38
- - jekyll-feed
39
- - jekyll-sitemap
40
- - jekyll-seo-tag
41
-
42
- exclude:
43
- - guide/
44
-
45
- collections:
46
- pages:
47
- output: true
48
- permalink: /:path.html
49
-
50
- defaults:
51
- -
52
- scope:
53
- path: ""
54
- type: "pages"
55
- values:
56
- layout: "default"
57
- date: "1900-01-01"
58
-
59
- # Markdown newline activator
60
- kramdown:
61
- input: GFM
62
- hard_wrap: true
63
-
64
- # Exclude from processing.
65
- # The following items will not be processed, by default.
66
- # Any item listed under the `exclude:` key here will be automatically added to
67
- # the internal "default list".
68
- #
69
- # Excluded items can be processed by explicitly listing the directories or
70
- # their entries' file path in the `include:` list.
71
- #
72
- # exclude:
73
- # - .sass-cache/
74
- # - .jekyll-cache/
75
- # - gemfiles/
76
- # - Gemfile
77
- # - Gemfile.lock
78
- # - node_modules/
79
- # - vendor/bundle/
80
- # - vendor/cache/
81
- # - vendor/gems/
82
- # - vendor/ruby/