Browse Source

added theme files

banshee 1 năm trước cách đây
mục cha
commit
97f108fb8f
41 tập tin đã thay đổi với 1349 bổ sung1 xóa
  1. 3 0
      .gitignore
  2. 13 0
      custom-theme/requirements.txt
  3. 1 0
      custom-theme/static/bootstrap/bootstrap.min.css
  4. 1 0
      custom-theme/static/bootstrap/bootstrap.min.js
  5. 1 0
      custom-theme/static/extra/admonition.min.css
  6. 2 0
      custom-theme/static/extra/bootstrap-toc.min.css
  7. 2 0
      custom-theme/static/extra/bootstrap-toc.min.js
  8. 1 0
      custom-theme/static/jquery/jquery-3.4.1.min.js
  9. 0 0
      custom-theme/static/pygment/friendly.min.css
  10. 12 0
      custom-theme/static/style.css
  11. 46 0
      custom-theme/static/style.js
  12. 43 0
      custom-theme/static/tipuesearch/tipuesearch.cfg.js
  13. 0 0
      custom-theme/static/tipuesearch/tipuesearch.min.css
  14. 17 0
      custom-theme/static/tipuesearch/tipuesearch.min.js
  15. 75 0
      custom-theme/templates/404.html
  16. 37 0
      custom-theme/templates/archives.html
  17. 214 0
      custom-theme/templates/article.html
  18. 359 0
      custom-theme/templates/base.html
  19. 78 0
      custom-theme/templates/categories.html
  20. 1 0
      custom-theme/templates/include/claim_bing.html
  21. 1 0
      custom-theme/templates/include/claim_google.html
  22. 10 0
      custom-theme/templates/include/disqus.html
  23. 1 0
      custom-theme/templates/include/disqus_count.html
  24. 11 0
      custom-theme/templates/include/ga.html
  25. 7 0
      custom-theme/templates/include/gtag.html
  26. 12 0
      custom-theme/templates/include/gtm.html
  27. 3 0
      custom-theme/templates/include/gtm_noscript.html
  28. 4 0
      custom-theme/templates/include/ha.html
  29. 10 0
      custom-theme/templates/include/jsonld.html
  30. 23 0
      custom-theme/templates/include/jsonld_article.html
  31. 19 0
      custom-theme/templates/include/matomo.html
  32. 12 0
      custom-theme/templates/include/neighbors.html
  33. 12 0
      custom-theme/templates/include/og.html
  34. 23 0
      custom-theme/templates/include/og_article.html
  35. 12 0
      custom-theme/templates/include/pagination.html
  36. 17 0
      custom-theme/templates/include/piwik.html
  37. 73 0
      custom-theme/templates/index.html
  38. 39 0
      custom-theme/templates/page.html
  39. 61 0
      custom-theme/templates/search.html
  40. 92 0
      custom-theme/templates/tags.html
  41. 1 1
      pelicanconf.py

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+.venv
+output
+__pycache__

+ 13 - 0
custom-theme/requirements.txt

@@ -0,0 +1,13 @@
+pelican
+markdown
+beautifulsoup4
+typogrify
+markdown-captions
+markdown-checklist
+pelican-sitemap
+pelican-related_posts
+pelican-neighbors
+pelican-share_post
+pelican-tag_cloud
+minchin.pelican.plugins.post_stats
+git+https://github.com/getpelican/pelican-plugins/#egg=pelican-tipue-search&subdirectory=tipue_search

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
custom-theme/static/bootstrap/bootstrap.min.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
custom-theme/static/bootstrap/bootstrap.min.js


+ 1 - 0
custom-theme/static/extra/admonition.min.css

@@ -0,0 +1 @@
+div.admonition{padding:8px 35px 8px 0;margin-bottom:20px;color:#c09853;text-shadow:0 1px 0 rgba(255,255,255,.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}div.admonition p{margin:.5em 1em .5em 1em;padding:0}div.admonition p a{color:inherit!important}div.admonition pre{margin:.4em 1em .4em 1em}div.admonition p.admonition-title{margin:0;padding:.1em 0 .1em .5em;font-weight:700}div.admonition ol,div.admonition ul{margin:.1em .5em .5em 3em;padding:0}div.danger,div.error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}div.important,div.note{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}div.hint,div.tip{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}div.attention p.admonition-title:before,div.caution p.admonition-title:before,div.danger p.admonition-title:before,div.error p.admonition-title:before,div.hint p.admonition-title:before,div.important p.admonition-title:before,div.note p.admonition-title:before,div.tip p.admonition-title:before,div.warning p.admonition-title:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}div.danger p.admonition-title:before,div.error p.admonition-title:before{content:"\f06a\00a0"}div.attention p.admonition-title:before,div.caution p.admonition-title:before,div.warning p.admonition-title:before{content:"\f071\00a0"}div.important p.admonition-title:before,div.note p.admonition-title:before{content:"\f05a\00a0"}div.hint p.admonition-title:before,div.tip p.admonition-title:before{content:"\f0eb\00a0"}

+ 2 - 0
custom-theme/static/extra/bootstrap-toc.min.css

@@ -0,0 +1,2 @@
+/*! Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/) Copyright 2015 Aidan Feldman Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
+nav[data-toggle=toc] .nav>li>a{display:block;padding:4px 20px;font-size:13px;font-weight:500;color:#767676}nav[data-toggle=toc] .nav>li>a:focus,nav[data-toggle=toc] .nav>li>a:hover{padding-left:19px;color:#563d7c;text-decoration:none;background-color:transparent;border-left:1px solid #563d7c}nav[data-toggle=toc] .nav-link.active,nav[data-toggle=toc] .nav-link.active:focus,nav[data-toggle=toc] .nav-link.active:hover{padding-left:18px;font-weight:700;color:#563d7c;background-color:transparent;border-left:2px solid #563d7c}nav[data-toggle=toc] .nav-link+ul{display:none;padding-bottom:10px}nav[data-toggle=toc] .nav .nav>li>a{padding-top:1px;padding-bottom:1px;padding-left:30px;font-size:12px;font-weight:400}nav[data-toggle=toc] .nav .nav>li>a:focus,nav[data-toggle=toc] .nav .nav>li>a:hover{padding-left:29px}nav[data-toggle=toc] .nav .nav>li>.active,nav[data-toggle=toc] .nav .nav>li>.active:focus,nav[data-toggle=toc] .nav .nav>li>.active:hover{padding-left:28px;font-weight:500}nav[data-toggle=toc] .nav-link.active+ul{display:block}

+ 2 - 0
custom-theme/static/extra/bootstrap-toc.min.js

@@ -0,0 +1,2 @@
+/*! Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/) Copyright 2015 Aidan Feldman Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
+!function(a){"use strict";window.Toc={helpers:{findOrFilter:function(e,t){var n=e.find(t);return e.filter(t).add(n).filter(":not([data-toc-skip])")},generateUniqueIdBase:function(e){return a(e).text().trim().replace(/\'/gi,"").replace(/[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\\n\t\b\v]/g,"-").replace(/-{2,}/g,"-").substring(0,64).replace(/^-+|-+$/gm,"").toLowerCase()||e.tagName.toLowerCase()},generateUniqueId:function(e){for(var t=this.generateUniqueIdBase(e),n=0;;n++){var r=t;if(0<n&&(r+="-"+n),!document.getElementById(r))return r}},generateAnchor:function(e){if(e.id)return e.id;var t=this.generateUniqueId(e);return e.id=t},createNavList:function(){return a('<ul class="nav navbar-nav"></ul>')},createChildNavList:function(e){var t=this.createNavList();return e.append(t),t},generateNavEl:function(e,t){var n=a('<a class="nav-link"></a>');n.attr("href","#"+e),n.text(t);var r=a("<li></li>");return r.append(n),r},generateNavItem:function(e){var t=this.generateAnchor(e),n=a(e),r=n.data("toc-text")||n.text();return this.generateNavEl(t,r)},getTopLevel:function(e){for(var t=1;t<=6;t++){if(1<this.findOrFilter(e,"h"+t).length)return t}return 1},getHeadings:function(e,t){var n="h"+t,r="h"+(t+1);return this.findOrFilter(e,n+","+r)},getNavLevel:function(e){return parseInt(e.tagName.charAt(1),10)},populateNav:function(r,a,e){var i,s=r,c=this;e.each(function(e,t){var n=c.generateNavItem(t);c.getNavLevel(t)===a?s=r:i&&s===r&&(s=c.createChildNavList(i)),s.append(n),i=n})},parseOps:function(e){var t;return(t=e.jquery?{$nav:e}:e).$scope=t.$scope||a(document.body),t}},init:function(e){(e=this.helpers.parseOps(e)).$nav.attr("data-toggle","toc");var t=this.helpers.createChildNavList(e.$nav),n=this.helpers.getTopLevel(e.$scope),r=this.helpers.getHeadings(e.$scope,n);this.helpers.populateNav(t,n,r)}},a(function(){a('nav[data-toggle="toc"]').each(function(e,t){var n=a(t);Toc.init(n)})})}(jQuery);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
custom-theme/static/jquery/jquery-3.4.1.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
custom-theme/static/pygment/friendly.min.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 12 - 0
custom-theme/static/style.css


+ 46 - 0
custom-theme/static/style.js

@@ -0,0 +1,46 @@
+/*! 
+ * Theme for Simplify blog
+ * vuquangtrong.github.io 
+ */
+
+/* function to add line number into codeblock */
+/*
+(function() {
+    var pre = document.getElementsByTagName('pre'),
+        pl = pre.length;
+    for (var i = 0; i < pl; i++) {
+        pre[i].innerHTML = '<span class="line-number"></span>' + pre[i].innerHTML + '<span class="cl"></span>';
+        var num = pre[i].innerHTML.split(/\n/).length;
+        for (var j = 0; j < (num - 1); j++) {
+            var line_num = pre[i].getElementsByTagName('span')[0];
+            line_num.innerHTML += '<span>' + (j + 1) + '</span>';
+        }
+    }
+})();
+*/
+
+/* force to hide expanded navbar when scroll down */
+$(window).scroll(function(e) {
+    var scroll = $(window).scrollTop();
+    if (scroll >= 150) {
+        $('#navbarMenu').collapse('hide');
+    }
+    if (scroll >= 300) {
+        $('#backToTop').fadeIn();
+    } else {
+        $('#backToTop').fadeOut();
+    }
+});
+
+/* add classes into tables */
+$("table:not(.highlighttable)").addClass("table table-hover table-sm table-bordered");
+$("thead").addClass("thead-light");
+
+/* add classes into images */
+$("img").addClass("img-fluid mx-auto shadow-lg");
+
+/* action to back to top */
+$('#backToTop').click(function() {
+    $("html, body").animate({ scrollTop: 0 }, 600);
+    return false;
+});

+ 43 - 0
custom-theme/static/tipuesearch/tipuesearch.cfg.js

@@ -0,0 +1,43 @@
+/* Tipue Search 7.1 Copyright (c) 2019 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */
+// Stop words list from http://www.ranks.nl/stopwords
+var tipuesearch_stop_words = ["a", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"];
+
+// Word replace
+var tipuesearch_replace = {'words': [
+]};
+
+
+// Weighting
+var tipuesearch_weight = {'weight': [
+]};
+
+// Illogical stemming
+var tipuesearch_stem = {'words': [
+]};
+
+// Related
+var tipuesearch_related = {'Related': [
+]};
+
+// Internal strings
+var tipuesearch_string_1 = 'No title';
+var tipuesearch_string_2 = 'Showing results for';
+var tipuesearch_string_3 = 'Search instead for';
+var tipuesearch_string_4 = '1 result';
+var tipuesearch_string_5 = 'results';
+var tipuesearch_string_6 = '<';
+var tipuesearch_string_7 = '>';
+var tipuesearch_string_8 = 'Nothing found.';
+var tipuesearch_string_9 = 'Common words are largely ignored.';
+var tipuesearch_string_10 = 'Related';
+var tipuesearch_string_11 = 'Search should be one character or more.';
+var tipuesearch_string_12 = 'Search should be';
+var tipuesearch_string_13 = 'characters or more.';
+var tipuesearch_string_14 = 'seconds';
+var tipuesearch_string_15 = 'Open Image';
+var tipuesearch_string_16 = 'Goto Page';
+
+// Internals
+
+// Timer for showTime
+var startTimer = new Date().getTime();

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
custom-theme/static/tipuesearch/tipuesearch.min.css


+ 17 - 0
custom-theme/static/tipuesearch/tipuesearch.min.js

@@ -0,0 +1,17 @@
+(function(l){l.fn.tipuesearch=function(B){var d=l.extend({contextBuffer:60,contextLength:60,contextStart:90,debug:!1,descriptiveWords:25,footerPages:3,highlightTerms:!0,imageZoom:!0,minimumLength:3,newWindow:!1,show:10,showContext:!0,showRelated:!0,showTime:!0,showTitleCount:!0,showURL:!0,wholeWords:!0},B);return this.each(function(){function z(d){d=((new RegExp("[?|&]"+d+"=([^&;]+?)(&|#|;|$)")).exec(location.search)||[,""])[1].replace(/\+/g,"%20");try{d=decodeURIComponent(d)}catch(w){d=unescape(d)}return d||
+null}function x(u,w){window.scrollTo(0,0);var e="",t=!1,k=!1,p=!0,n=0,g=[],m=l("#tipue_search_input").val();m=m.replace(/\+/g," ").replace(/\s\s+/g," ");m=l.trim(m);var h=m.toLowerCase();if(h.match('^"')&&h.match('"$')||h.match("^'")&&h.match("'$"))p=!1;var c=h.split(" ");if(p){h="";for(var a=0;a<c.length;a++){for(var v=!0,b=0;b<tipuesearch_stop_words.length;b++)c[a]==tipuesearch_stop_words[b]&&(v=!1,k=!0);v&&(h=h+" "+c[a])}h=l.trim(h);c=h.split(" ")}else h=h.substring(1,h.length-1);if(h.length>=
+d.minimumLength){if(p){if(w){var r=h;for(a=0;a<c.length;a++)for(b=0;b<tipuesearch_replace.words.length;b++)c[a]==tipuesearch_replace.words[b].word&&(h=h.replace(c[a],tipuesearch_replace.words[b].replace_with),t=!0);c=h.split(" ")}k=h;for(a=0;a<c.length;a++)for(b=0;b<tipuesearch_stem.words.length;b++)c[a]==tipuesearch_stem.words[b].word&&(k=k+" "+tipuesearch_stem.words[b].stem);c=k.split(" ");for(a=0;a<tipuesearch.pages.length;a++){k=0;v=tipuesearch.pages[a].text;for(b=0;b<c.length;b++){var f=d.wholeWords?
+new RegExp("\\b"+c[b]+"\\b","gi"):new RegExp(c[b],"gi");if(-1!=tipuesearch.pages[a].title.search(f)){var q=tipuesearch.pages[a].title.match(f).length;k+=20*q}-1!=tipuesearch.pages[a].text.search(f)&&(q=tipuesearch.pages[a].text.match(f).length,k+=20*q);tipuesearch.pages[a].tags&&-1!=tipuesearch.pages[a].tags.search(f)&&(q=tipuesearch.pages[a].tags.match(f).length,k+=10*q);-1!=tipuesearch.pages[a].url.search(f)&&(k+=20);if(0!=k)for(f=0;f<tipuesearch_weight.weight.length;f++)tipuesearch.pages[a].url==
+tipuesearch_weight.weight[f].url&&(k+=tipuesearch_weight.weight[f].score);c[b].match("^-")&&(f=new RegExp(c[b].substring(1),"i"),-1!=tipuesearch.pages[a].title.search(f)||-1!=tipuesearch.pages[a].text.search(f)||-1!=tipuesearch.pages[a].tags.search(f))&&(k=0)}0!=k&&(g.push({score:k,title:tipuesearch.pages[a].title,desc:v,img:tipuesearch.pages[a].img,url:tipuesearch.pages[a].url,note:tipuesearch.pages[a].note}),n++)}}else for(a=0;a<tipuesearch.pages.length;a++){k=0;v=tipuesearch.pages[a].text;f=new RegExp(h,
+"gi");-1!=tipuesearch.pages[a].title.search(f)&&(q=tipuesearch.pages[a].title.match(f).length,k+=20*q);-1!=tipuesearch.pages[a].text.search(f)&&(q=tipuesearch.pages[a].text.match(f).length,k+=20*q);tipuesearch.pages[a].tags&&-1!=tipuesearch.pages[a].tags.search(f)&&(q=tipuesearch.pages[a].tags.match(f).length,k+=10*q);-1!=tipuesearch.pages[a].url.search(f)&&(k+=20);if(0!=k)for(f=0;f<tipuesearch_weight.weight.length;f++)tipuesearch.pages[a].url==tipuesearch_weight.weight[f].url&&(k+=tipuesearch_weight.weight[f].score);
+0!=k&&(g.push({score:k,title:tipuesearch.pages[a].title,desc:v,img:tipuesearch.pages[a].img,url:tipuesearch.pages[a].url,note:tipuesearch.pages[a].note}),n++)}if(0!=n){d.showTitleCount&&0==A&&(document.title="("+n+") "+document.title,A++);1==n?e+='<div id="tipue_search_results_count">'+tipuesearch_string_4:(a=n.toString().replace(/\B(?=(\d{3})+(?!\d))/g,","),e+='<div id="tipue_search_results_count">'+a+" "+tipuesearch_string_5);d.showTime&&(a=((new Date).getTime()-startTimer)/1E3,e+=" ("+a.toFixed(2)+
+" "+tipuesearch_string_14+")",d.showTime=!1);e+="</div>";if(d.showRelated&&p){c="";for(a=b=0;a<tipuesearch_related.Related.length;a++)h==tipuesearch_related.Related[a].search&&(b||(e+='<div class="tipue_search_related">'+tipuesearch_string_10+": "),t&&(m=h),c+='<a class="tipue_search_related_btn" id="'+(tipuesearch_related.Related[a].include?m+" "+tipuesearch_related.Related[a].related:tipuesearch_related.Related[a].related)+'">'+tipuesearch_related.Related[a].related+"</a>, ",b++);b&&(c=c.slice(0,
+-2),e+=c+".</div>")}t&&(e+='<div id="tipue_search_replace">'+tipuesearch_string_2+" "+h+". "+tipuesearch_string_3+' <a id="tipue_search_replaced">'+r+"</a></div>");g.sort(function(a,b){return b.score-a.score});t=0;d.imageZoom&&(e+='<div id="tipue_search_image_modal"><div class="tipue_search_image_close">&#10005;</div><div class="tipue_search_image_block"><a id="tipue_search_zoom_url"><img id="tipue_search_zoom_img"></a><div id="tipue_search_zoom_text"></div></div></div>');for(a=0;a<g.length;a++){if(t>=
+u&&t<d.show+u){e+='<div class="tipue_search_result">';e+='<div class="tipue_search_content_title"><a href="'+g[a].url+'"'+y+">"+g[a].title+"</a></div>";d.debug&&(e+='<div class="tipue_search_content_debug">Score: '+g[a].score+"</div>");d.showURL&&(b=g[a].url.toLowerCase(),0==b.indexOf("http://")&&(b=b.slice(7)),e+='<div class="tipue_search_content_url"><a href="'+g[a].url+'"'+y+">"+b+"</a></div>");g[a].img&&(e=d.imageZoom?e+('<div class="tipue_search_image"><img class="tipue_search_img tipue_search_image_zoom" src="'+
+g[a].img+'" alt="'+g[a].title+'" data-url="'+g[a].url+'"></div>'):e+('<div class="tipue_search_image"><a href="'+g[a].url+'"'+y+'><img class="tipue_search_img" src="'+g[a].img+'" alt="'+g[a].title+'"></a></div>'));if(g[a].desc){m=g[a].desc;d.showContext&&(c=h.split(" "),b=g[a].desc.toLowerCase().indexOf(c[0]),b>d.contextStart&&(c=m.substr(b-d.contextBuffer),c=c.indexOf(" "),c=m.substr(b-d.contextBuffer+c),c=l.trim(c),c.length>d.contextLength&&(m="... "+c)));if(p)for(c=h.split(" "),b=0;b<c.length;b++)d.highlightTerms&&
+(r=new RegExp("("+c[b]+")","gi"),m=m.replace(r,"<h0011>$1<h0012>"));else d.highlightTerms&&(r=new RegExp("("+h+")","gi"),m=m.replace(r,'<span class="tipue_search_content_bold">$1</span>'));c="";r=m.split(" ");if(r.length<d.descriptiveWords)c=m;else for(b=0;b<d.descriptiveWords;b++)c+=r[b]+" ";c=l.trim(c);"."!=c.charAt(c.length-1)&&(c+=" ...");c=c.replace(/h0011/g,'span class="tipue_search_content_bold"');c=c.replace(/h0012/g,"/span");e+='<div class="tipue_search_content_text">'+c+"</div>"}g[a].note&&
+(e+='<div class="tipue_search_note">'+g[a].note+"</div>");e+="</div>"}t++}if(n>d.show){p=Math.ceil(n/d.show);n=u/d.show;3>d.footerPages&&(d.footerPages=3);e+='<div id="tipue_search_foot"><ul id="tipue_search_foot_boxes">';0<u&&(e+='<li role="navigation"><a class="tipue_search_foot_box" accesskey="b" id="'+(u-d.show)+"_"+w+'">'+tipuesearch_string_6+"</a></li>");2>=n?(g=p,p>d.footerPages&&(g=d.footerPages),b=0):(g=n+d.footerPages-1,g>p&&(g=p),b=n-1);for(;b<g;b++)e=b==n?e+('<li class="current" role="navigation">'+
+(b+1)+"</li>"):e+('<li role="navigation"><a class="tipue_search_foot_box" id="'+b*d.show+"_"+w+'">'+(b+1)+"</a></li>");n+1!=p&&(e+='<li role="navigation"><a class="tipue_search_foot_box" accesskey="m" id="'+(u+d.show)+"_"+w+'">'+tipuesearch_string_7+"</a></li>");e+="</ul></div>"}}else e+='<div id="tipue_search_error">'+tipuesearch_string_8+"</div>"}else e=k?e+('<div id="tipue_search_error">'+tipuesearch_string_8+" "+tipuesearch_string_9+"</div>"):1==d.minimumLength?e+('<div id="tipue_search_error">'+
+tipuesearch_string_11+"</div>"):e+('<div id="tipue_search_error">'+tipuesearch_string_12+" "+d.minimumLength+" "+tipuesearch_string_13+"</div>");l("#tipue_search_content").hide().html(e).slideDown(200);l("#tipue_search_replaced").click(function(){x(0,!1)});l(".tipue_search_related_btn").click(function(){l("#tipue_search_input").val(l(this).attr("id"));x(0,!0)});l(".tipue_search_image_zoom").click(function(){l("#tipue_search_image_modal").fadeIn(300);l("#tipue_search_zoom_img").attr("src",this.src);
+var a=l(this).attr("data-url");l("#tipue_search_zoom_url").attr("href",a);a=this.alt+'<div class="tipue_search_zoom_options"><a href="'+this.src+'" target="_blank">'+tipuesearch_string_15+'</a>&nbsp; <a href="'+a+'">'+tipuesearch_string_16+"</a></div>";l("#tipue_search_zoom_text").html(a)});l(".tipue_search_image_close").click(function(){l("#tipue_search_image_modal").fadeOut(300)});l(".tipue_search_foot_box").click(function(){var a=l(this).attr("id").split("_");x(parseInt(a[0]),a[1])})}var A=0,y=
+"";d.newWindow&&(y=' target="_blank"');z("q")&&(l("#tipue_search_input").val(z("q")),x(0,!0));l(this).keyup(function(d){"13"==d.keyCode&&x(0,!0)})})}})(jQuery);

+ 75 - 0
custom-theme/templates/404.html

@@ -0,0 +1,75 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8">
+    <title>Page Not Found &ndash; {{ SITENAME }}</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <style>
+    * {
+        line-height: 1.2;
+        margin: 0;
+    }
+
+    html {
+        color: #888;
+        display: table;
+        font-family: sans-serif;
+        height: 100%;
+        text-align: center;
+        width: 100%;
+    }
+
+    body {
+        display: table-cell;
+        vertical-align: middle;
+        margin: 2em auto;
+    }
+
+    h1 {
+        color: #555;
+        font-size: 2em;
+        font-weight: 400;
+    }
+
+    p {
+        margin: 0 auto;
+        width: 280px;
+    }
+
+    a {
+        text-decoration: none;
+        color: white;
+        background-color: black;
+        padding: 0.5rem;
+        border-radius: 0.5rem;
+    }
+
+    a:hover {
+        color: black;
+        background-color: darkgray;
+    }
+
+    @media only screen and (max-width: 280px) {
+        body,
+        p {
+            width: 95%;
+        }
+
+        h1 {
+            font-size: 1.5em;
+            margin: 0 0 0.3em;
+        }
+    }
+    </style>
+</head>
+
+<body>
+    <h1>Page Not Found</h1>
+    <p>Sorry, but the page you were trying to view does not exist.</p>
+    <br>
+    <p><a href="{{ SITEURL }}">Click here to go back to {{ SITETITLE }}</a></p>
+</body>
+
+</html>
+<!-- IE needs 512+ bytes: https://blogs.msdn.microsoft.com/ieinternals/2010/08/18/friendly-http-error-pages/ -->

+ 37 - 0
custom-theme/templates/archives.html

@@ -0,0 +1,37 @@
+{% extends "base.html" %}
+
+{% block title %}
+    Archives &ndash; {{ SITENAME }}
+{% endblock title %}
+
+{% block header %}
+    <div class="container">
+        <div class="row">
+            <div class="col-8">
+                <h3 id="Archives in {{ SITENAME }}" style="color: orange;">Archives in {{ SITENAME }}</h3>
+            </div>
+            <div class="col-4 small" style="margin-top: 0.5rem;">
+                {% if ADD_THIS_ID and (page_name or page or article) %}
+                    <div class="text-right mb-2 small" style="height: 26px">
+                        <div class="addthis_inline_share_toolbox"></div>
+                    </div>
+                {% endif %}
+            </div>
+        </div>
+    </div>
+{% endblock header %}
+
+{% block add_this %}
+{# remove ADD_THIS in content, move to above header #}
+{% endblock add_this %}
+
+{% block content %}
+    <div>
+        <dl>
+            {% for article in dates %}
+                <dt>{{ article.locale_date }}</dt>
+                <dd><a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></dd>
+            {% endfor %}
+        </dl>
+    </div>
+{% endblock content %}

+ 214 - 0
custom-theme/templates/article.html

@@ -0,0 +1,214 @@
+{% extends "base.html" %}
+
+{% block meta %}
+    <meta name="author" content="{{ article.author.name }}" />
+    <meta name="description" content="{{ article.summary|striptags|escape }}" />
+    <meta name="keywords" content="{{ article.tags|join(', ')|escape }}">
+    {% include "include/og_article.html" %}
+{% endblock meta%}
+
+{% block title %}
+    {{ article.title|striptags|escape }} &ndash; {{ SITENAME }}
+{% endblock title %}
+
+{% block header %}
+	<div class="container">
+		<h3 id="{{ article.slug }}">{{ article.title }}</h3>
+		<p style="font-size:larger;">{{ article.summary }}</p>
+        <div class="row mx-auto mt-3">
+            <div class="col-xs-12 col-sm-12 col-md-6 text-left" style="padding: 0">
+                <a href="{{ SITEURL }}/{{ article.author.url }}" class="card-link">{{ article.author }}</a>
+                <span class="card-link text-success">
+                    <span class="post-date" title="Post date">{{ article.locale_date }}</span>
+                    <span class="text-info modified-date" title="Updated date">
+                        {% if article.modified %}
+                            {{ article.locale_modified }}
+                        {% else %}
+                            {{ article.locale_date }}
+                        {% endif %}
+                    </span>
+                </span>
+                {% if article.stats %}
+                    <span class="card-link text-secondary" title="~{{ article.stats['wc'] }} words">{{ article.stats['read_mins'] }} mins</span>
+                {% elif article.readtime %}
+                    <span class="card-link text-secondary" title="Read time">{{ article.readtime }}</span>
+                {% endif %}
+            </div>
+            <div class="col-xs-12 col-sm-12 col-md-6 text-right" style="padding: 0">
+                <a class="badge badge-success" href="{{ SITEURL }}/{{ article.category.url }}">{{ article.category|lower }}</a>
+                {% for tag in article.tags %}
+                    <a class="badge badge-info" href="{{ SITEURL }}/{{ tag.url }}">{{ tag|lower }}</a>
+                {% endfor %}
+            </div>
+        </div>
+	</div>
+{% endblock header %}
+
+{% block content %}
+    <!-- 2 columns layout -->
+    {% if article.toc == 'show' %}
+        <div class="row">
+            <div class="col-xs-12 col-sm-12 col-md-10">
+                {% block add_this %}
+                {# remove ADD_THIS in content, move to inner column #}
+                {% endblock add_this %}
+
+                <!-- Sharing -->
+                {% if ADD_THIS_ID and (page_name or page or article) %}
+                    <div class="text-right mb-2 small" style="height: 26px">
+                        <div class="addthis_inline_share_toolbox"></div>
+                    </div>
+                {% endif %}
+
+                <!-- Article -->
+                {{ article.content }}
+
+                <!-- Neighbors -->
+                {% if article.prev_article or article.next_article %}
+                    <br>
+                    <b>Read more:</b><br>
+                    {% include "include/neighbors.html" %}
+                {% endif %}
+
+                <!-- Google Adsense -->
+                {% if GOOGLE_ADSENSE and GOOGLE_ADSENSE.ads.sidebar %}
+                    <br>
+                    <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+                    <!-- ad-sidebar -->
+                    <ins class="adsbygoogle"
+                         style="display:block"
+                         data-ad-client="{{ GOOGLE_ADSENSE.id }}"
+                         data-ad-slot="{{ GOOGLE_ADSENSE.ads.sidebar }}"
+                         data-ad-format="auto"
+                         data-full-width-responsive="true"></ins>
+                    <script>
+                         (adsbygoogle = window.adsbygoogle || []).push({});
+                    </script>
+                {% endif %}
+            </div>
+
+            <!-- Sidebar -->
+            <div class="col-md-2 d-none d-md-block small">
+                <div class="sticky-top">
+                    <!-- ToC -->
+                    <nav id="toc" data-toggle="toc" ></nav>
+
+                    <!-- Share post -->
+                    {% if SHARE_POST and article.share_post and article.status != 'draft' %}
+                    <hr>
+                    <div id="post-share-links">
+                        <p>Share on:</p>
+                        <a class="mx-auto" href="{{article.share_post['twitter']}}" target="_blank" title="Share on Twitter">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                                <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm6.066 9.645c.183 4.04-2.83 8.544-8.164 8.544-1.622 0-3.131-.476-4.402-1.291 1.524.18 3.045-.244 4.252-1.189-1.256-.023-2.317-.854-2.684-1.995.451.086.895.061 1.298-.049-1.381-.278-2.335-1.522-2.304-2.853.388.215.83.344 1.301.359-1.279-.855-1.641-2.544-.889-3.835 1.416 1.738 3.533 2.881 5.92 3.001-.419-1.796.944-3.527 2.799-3.527.825 0 1.572.349 2.096.907.654-.128 1.27-.368 1.824-.697-.215.671-.67 1.233-1.263 1.589.581-.07 1.135-.224 1.649-.453-.384.578-.87 1.084-1.433 1.489z" fill="currentColor"></path>
+                            </svg>
+                        </a>
+                        <a class="mx-auto" href="{{article.share_post['facebook']}}" target="_blank" title="Share on Facebook">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                                <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm3 8h-1.35c-.538 0-.65.221-.65.778v1.222h2l-.209 2h-1.791v7h-3v-7h-2v-2h2v-2.308c0-1.769.931-2.692 3.029-2.692h1.971v3z" fill="currentColor"></path>
+                            </svg>
+                        </a>
+                        <a class="mx-auto" href="{{article.share_post['linkedin']}}" target="_blank" title="Share on LinkedIn">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                                <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-2 16h-2v-6h2v6zm-1-6.891c-.607 0-1.1-.496-1.1-1.109 0-.612.492-1.109 1.1-1.109s1.1.497 1.1 1.109c0 .613-.493 1.109-1.1 1.109zm8 6.891h-1.998v-2.861c0-1.881-2.002-1.722-2.002 0v2.861h-2v-6h2v1.093c.872-1.616 4-1.736 4 1.548v3.359z" fill="currentColor"></path>
+                            </svg>
+                        </a>
+                    </div>
+                    {% endif %}
+
+                    <!-- Google Adsense -->
+                    {% if GOOGLE_ADSENSE and GOOGLE_ADSENSE.ads.sidebar %}
+                        <br>
+                        <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+                        <!-- ad-sidebar -->
+                        <ins class="adsbygoogle"
+                             style="display:block"
+                             data-ad-client="{{ GOOGLE_ADSENSE.id }}"
+                             data-ad-slot="{{ GOOGLE_ADSENSE.ads.sidebar }}"
+                             data-ad-format="auto"
+                             data-full-width-responsive="true"></ins>
+                        <script>
+                             (adsbygoogle = window.adsbygoogle || []).push({});
+                        </script>
+                    {% endif %}
+                </div>
+            </div>
+        </div>
+    {% else %}
+    <!-- single column layout -->
+        <!-- Sharing -->
+        {% if ADD_THIS_ID and (page_name or page or article) %}
+            <div class="text-right mb-2 small" style="height: 26px">
+                <div class="addthis_inline_share_toolbox"></div>
+            </div>
+        {% endif %}
+
+        <!-- Share post -->
+        {% if SHARE_POST and article.share_post and article.status != 'draft' %}
+        <div id="post-share-links" class="text-right mb-2">
+            Share on: 
+            <a href="{{article.share_post['twitter']}}" target="_blank" title="Share on Twitter">
+                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                    <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm6.066 9.645c.183 4.04-2.83 8.544-8.164 8.544-1.622 0-3.131-.476-4.402-1.291 1.524.18 3.045-.244 4.252-1.189-1.256-.023-2.317-.854-2.684-1.995.451.086.895.061 1.298-.049-1.381-.278-2.335-1.522-2.304-2.853.388.215.83.344 1.301.359-1.279-.855-1.641-2.544-.889-3.835 1.416 1.738 3.533 2.881 5.92 3.001-.419-1.796.944-3.527 2.799-3.527.825 0 1.572.349 2.096.907.654-.128 1.27-.368 1.824-.697-.215.671-.67 1.233-1.263 1.589.581-.07 1.135-.224 1.649-.453-.384.578-.87 1.084-1.433 1.489z" fill="currentColor"></path>
+                </svg>
+            </a>
+            <a href="{{article.share_post['facebook']}}" target="_blank" title="Share on Facebook">
+                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                    <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm3 8h-1.35c-.538 0-.65.221-.65.778v1.222h2l-.209 2h-1.791v7h-3v-7h-2v-2h2v-2.308c0-1.769.931-2.692 3.029-2.692h1.971v3z" fill="currentColor"></path>
+                </svg>
+            </a>
+            <a href="{{article.share_post['linkedin']}}" target="_blank" title="Share on LinkedIn">
+                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                    <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-2 16h-2v-6h2v6zm-1-6.891c-.607 0-1.1-.496-1.1-1.109 0-.612.492-1.109 1.1-1.109s1.1.497 1.1 1.109c0 .613-.493 1.109-1.1 1.109zm8 6.891h-1.998v-2.861c0-1.881-2.002-1.722-2.002 0v2.861h-2v-6h2v1.093c.872-1.616 4-1.736 4 1.548v3.359z" fill="currentColor"></path>
+                </svg>
+            </a>
+        </div>
+        {% endif %}
+
+        <!-- Article -->
+        <div>
+            {{ article.content }}
+        </div>
+
+        <!-- Neighbors -->
+        {% if article.prev_article or article.next_article %}
+            <br>
+            <b>Read more:</b><br>
+            {% include "include/neighbors.html" %}
+        {% endif %}
+
+        <!-- Google Adsense -->
+        {% if GOOGLE_ADSENSE and GOOGLE_ADSENSE.ads.article %}
+            <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+            <!-- ad-home -->
+            <ins class="adsbygoogle"
+                 style="display:block"
+                 data-ad-client="{{ GOOGLE_ADSENSE.id }}"
+                 data-ad-slot="{{ GOOGLE_ADSENSE.ads.article }}"
+                 data-ad-format="auto"
+                 data-full-width-responsive="true"></ins>
+            <script>
+                 (adsbygoogle = window.adsbygoogle || []).push({});
+            </script>
+        {% endif %}
+    {% endif %}
+
+    <!-- Releated posts -->
+    {% if article.related_posts %}
+        <hr>
+        <div>
+            <h5>Related posts:</h5>
+            <ul>
+            {% for related_post in article.related_posts %}
+                <li><a href="{{ SITEURL }}/{{ related_post.url }}">{{ related_post.title }}</a></li>
+            {% endfor %}
+            </ul>
+        </div>
+    {% endif %}
+
+    <!-- Comments -->
+    {% if DISQUS_SITENAME %}
+        <hr>
+        {% include "include/disqus.html" %}
+    {% endif %}
+{% endblock content %}

+ 359 - 0
custom-theme/templates/base.html

@@ -0,0 +1,359 @@
+{% if 'jinja2.ext.i18n' not in JINJA_ENVIRONMENT.extensions and 'jinja2.ext.i18n' not in JINJA_EXTENSIONS %}
+    {% macro _(msg) %}
+        {{ msg % kwargs }}
+    {% endmacro %}
+{% endif %}
+
+<!DOCTYPE html>
+<html lang="{% block html_lang %}{{ DEFAULT_LANG }}{% endblock html_lang %}">
+
+<!-- Head -->
+<head>
+    {% block head %}
+
+        <!-- Required metadata tags -->
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+        <meta name="HandheldFriendly" content="True" />
+        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
+
+        <!-- Default metadata -->
+        {% block meta %}
+            <meta name="author" content="{{ AUTHOR }}" />
+            <meta name="description" content="{{ SITEDESCRIPTION }}" />
+        {% endblock %}
+
+        <!-- Site Claim -->
+        {% if CLAIM_GOOGLE %}
+            {% include 'includes/claim_google.html' with context %}
+        {% endif %}
+
+        {% if CLAIM_BING %}
+            {% include 'includes/claim_bing.html' with context %}
+        {% endif %}
+
+        <!-- Title -->
+        <title>
+            {% block title %}
+                {{ SITETITLE }}
+            {% endblock title %}
+        </title>
+        
+        <!-- Icon -->
+        <link rel="shortcut icon" href="{{ SITEURL }}/favicon.ico" type="image/x-icon">
+        <link rel="icon" href="{{ SITEURL }}/favicon.ico" type="image/x-icon">
+
+        <!-- Search engine -->
+        {% if page in hidden_pages %}
+            <meta name="robots" content="noindex, nofollow" />
+        {% else %}
+            <meta name="robots" content="{{ ROBOTS }}" />
+        {% endif %}
+
+        <!-- Feeds -->
+        {% if FEED_ALL_ATOM %}
+            <link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_ATOM_URL %}{{ FEED_ALL_ATOM_URL }}{% else %}{{ FEED_ALL_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Full Atom Feed" />
+        {% endif %}
+
+        {% if FEED_ALL_RSS %}
+            <link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_RSS_URL %}{{ FEED_ALL_RSS_URL }}{% else %}{{ FEED_ALL_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Full RSS Feed" />
+        {% endif %}
+
+        {% if FEED_ATOM %}
+            <link href="{{ FEED_DOMAIN }}/{%if FEED_ATOM_URL %}{{ FEED_ATOM_URL }}{% else %}{{ FEED_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Atom Feed" />
+        {% endif %}
+
+        {% if FEED_RSS %}
+            <link href="{{ FEED_DOMAIN }}/{% if FEED_RSS_URL %}{{ FEED_RSS_URL }}{% else %}{{ FEED_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} RSS Feed" />
+        {% endif %}
+
+        {% if CATEGORY_FEED_ATOM and category %}
+            <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_ATOM_URL %}{{ CATEGORY_FEED_ATOM_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_ATOM.format(slug=category.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Categories Atom Feed" />
+        {% endif %}
+
+        {% if CATEGORY_FEED_RSS and category %}
+            <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_RSS_URL %}{{ CATEGORY_FEED_RSS_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_RSS.format(slug=category.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Categories RSS Feed" />
+        {% endif %}
+
+        {% if TAG_FEED_ATOM and tag %}
+            <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_ATOM_URL %}{{ TAG_FEED_ATOM_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_ATOM.format(slug=tag.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Tags Atom Feed" />
+        {% endif %}
+
+        {% if TAG_FEED_RSS and tag %}
+            <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_RSS_URL %}{{ TAG_FEED_RSS_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_RSS.format(slug=tag.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Tags RSS Feed" />
+        {% endif %}
+
+        <!-- Styles -->
+        <!--
+        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/4.3.1/css/bootstrap.min.css">
+        -->
+        <link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/bootstrap/bootstrap.min.css">
+        <!--
+        <link rel="stylesheet" href="https://cdn.rawgit.com/afeld/bootstrap-toc/v1.0.1/dist/bootstrap-toc.min.css">
+        -->
+        {% if article and article.toc == 'show' %}
+            <link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/extra/bootstrap-toc.min.css">
+        {% endif %}
+        <link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/pygment/friendly.min.css">
+        <!--
+        <link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/extra/admonition.min.css">
+        -->
+        {% if page_name == 'search' %}
+            <link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/tipuesearch/tipuesearch.min.css">
+        {% endif %}
+        <link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/style.css">
+
+        <!-- Google Analytics -->
+        {% if GOOGLE_ANALYTICS %}
+            {% include "include/ga.html" %}
+        {% endif %}
+
+        <!-- Google Global Site Tag -->
+        {% if GOOGLE_SITE_TAG %}
+            {% include "include/gtag.html" %}
+        {% endif %}
+
+        <!-- Google Tag Manager -->
+        {% if GOOGLE_TAG_MANAGER %}
+            {% include "include/gtm.html" %}
+        {% endif %}
+
+        <!-- Google Adsense -->
+        {% if GOOGLE_ADSENSE %}
+            <script data-ad-client="{{ GOOGLE_ADSENSE.id }}" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+        {% endif %}
+
+        <!-- Heap Analytic -->
+        {% if HEAP_ANALYTICS %}
+            {% include "include/ha.html" %}
+        {% endif %}
+
+        <!-- Piwik Tracking -->
+        {% if PIWIK_SITE_ID and PIWIK_URL %}
+            {% include "include/piwik.html" %}
+        {% endif %}
+
+        <!-- Matomo Tracking -->
+        {% if MATOMO_SITENAME %}
+            {% include "include/matomo.html" %}
+        {% endif %}
+
+    {% endblock head %}
+</head>
+
+<!-- Body -->
+<body class="d-flex flex-column" data-spy="scroll" data-target="#toc" data-offset="0" style="position: relative;">
+    <!-- Top anchor -->
+    <a href="#" id="backToTop" style="display: none; z-index: 1;" title="Back to top"><span></span></a>
+
+    <!-- Google tag manager -->
+    {% if GOOGLE_TAG_MANAGER %}
+        {% include "include/gtm_noscript.html" %}
+    {% endif %}
+
+    <!-- Navigation -->
+    <nav class="flex-shrink-0 navbar navbar-expand-md navbar-expand-lg navbar-dark bg-dark text-light shadow-sm">
+        <!-- Logo -->
+        <a class="navbar-brand" href="{{ SITEURL }}">{{ SITETITLE }}</a>
+
+        <!-- Collapse button -->
+        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarMenu" aria-controls="navbarMenu" aria-expanded="false" aria-label="Toggle navigation">
+            <span class="navbar-toggler-icon small"></span>
+        </button>
+
+        <!-- Collapsible content -->
+        <div class="collapse navbar-collapse" id="navbarMenu">
+
+            <!-- i18n subsites -->
+            {% if extra_siteurls %}
+            <div class="dropdown">
+                <button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
+                    <svg class="nav-icon" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
+                        <path d="M12.87 15.07l-2.54-2.51l.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v2h11.17C11.5 7.92 10.44 9.75 9 11.35C8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5l3.11 3.11l.76-2.04M18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12m-2.62 7l1.62-4.33L19.12 17h-3.24z" fill="#626262"/>
+                    </svg>
+                </button>
+                <div class="dropdown-menu">
+                    {% for lang, url in lang_siteurls.items() %}
+                    <a class="dropdown-item {% if lang == DEFAULT_LANG %}active{% endif %}" href="{{ url }}/">{{ lang }}</a>
+                    {% endfor %}
+                </div>
+            </div>
+            {% endif %}
+
+            <!-- Page links -->
+            <ul class="navbar-nav mr-auto text-center">
+                <li class="nav-item {% if page_name == 'index' %} active {% endif %}">                           
+                    <a class="nav-link" href="{{ SITEURL }}">
+                        <svg class="nav-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24">
+                            <path d="M21 13v10h-6v-6h-6v6h-6v-10h-3l12-12 12 12h-3zm-1-5.907v-5.093h-3v2.093l3 3z" fill="currentColor"></path>
+                        </svg>
+                        Home <span class="sr-only">(current)</span>
+                    </a>
+                </li>
+                <li class="nav-item {% if page_name == 'categories' %} active {% endif %}">
+                    <a class="nav-link" href="{{ SITEURL }}/categories.html">
+                        <svg class="nav-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24">
+                            <path d="M16 6h-8v-6h8v6zm-8 12h-8v6h8v-6zm16 0h-8v6h8v-6zm-11-7v-3h-2v3h-8v5h2v-3h14v3h2v-5h-8z" fill="currentColor"></path>
+                        </svg>
+                        Categories
+                    </a>
+                </li>
+                <li class="nav-item {% if page_name == 'tags' %} active {% endif %}">
+                    <a class="nav-link" href="{{ SITEURL }}/tags.html">
+                        <svg class="nav-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24">
+                            <path d="M10.605 0h-10.605v10.609l13.391 13.391 10.609-10.604-13.395-13.396zm-4.191 6.414c-.781.781-2.046.781-2.829.001-.781-.783-.781-2.048 0-2.829.782-.782 2.048-.781 2.829-.001.782.782.781 2.047 0 2.829z" fill="currentColor"></path>
+                        </svg>
+                        Tags
+                    </a>
+                </li>
+                <li class="nav-item {% if page_name == 'archives' %} active {% endif %}">
+                    <a class="nav-link" href="{{ SITEURL }}/archives.html">
+                        <svg class="nav-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24">
+                            <path d="M1.8 9l-.8-4h22l-.8 4h-2.029l.39-2h-17.122l.414 2h-2.053zm18.575-6l.604-2h-17.979l.688 2h16.687zm3.625 8l-2 13h-20l-2-13h24zm-8 4c0-.552-.447-1-1-1h-6c-.553 0-1 .448-1 1s.447 1 1 1h6c.553 0 1-.448 1-1z" fill="currentColor"></path>
+                        </svg>
+                        Archives
+                    </a>
+                </li>
+                <li class="nav-item {% if page and 'about' in page.title|lower %} active {% endif %}">
+                    <a class="nav-link" href="{{ SITEURL }}/pages/about.html">
+                        <svg class="nav-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24">
+                            <path d="M20.822 18.096c-3.439-.794-6.64-1.49-5.09-4.418 4.72-8.912 1.251-13.678-3.732-13.678-5.082 0-8.464 4.949-3.732 13.678 1.597 2.945-1.725 3.641-5.09 4.418-3.073.71-3.188 2.236-3.178 4.904l.004 1h23.99l.004-.969c.012-2.688-.092-4.222-3.176-4.935z" fill="currentColor"></path>
+                        </svg>
+                        About
+                    </a>
+                </li>
+            </ul>
+
+            {% if page_name != 'search' %}
+            <!-- Search form -->
+            <form class="form-inline text-center" action="{{ SITEURL }}/search.html">
+                <input class="form-control w-100 bg-dark text-light text-center border-0 p-2" type="text" name="q" pattern=".{3,}" title="At least 3 characters" required="" placeholder="Type here to search" aria-label="Search">
+            </form>
+            {% endif %}
+
+            <!-- Social links -->
+            <ul class="navbar-nav text-center">
+                <li class="nav-item">
+                    <a class="nav-link" href="{{ SOCIAL.facebook }}">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                            <title>Facebook</title>
+                            <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm3 8h-1.35c-.538 0-.65.221-.65.778v1.222h2l-.209 2h-1.791v7h-3v-7h-2v-2h2v-2.308c0-1.769.931-2.692 3.029-2.692h1.971v3z" fill="currentColor"></path>
+                        </svg>
+                    </a>
+                </li>
+                <li class="nav-item">
+                    <a class="nav-link" href="{{ SOCIAL.github }}">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                            <title>Github</title>
+                            <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" fill="currentColor"></path>
+                        </svg>
+                    </a>
+                </li>
+                <li class="nav-item">
+                    <a class="nav-link" href="{{ SOCIAL.linkedin }}">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                            <title>Linkedin</title>
+                            <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-2 16h-2v-6h2v6zm-1-6.891c-.607 0-1.1-.496-1.1-1.109 0-.612.492-1.109 1.1-1.109s1.1.497 1.1 1.109c0 .613-.493 1.109-1.1 1.109zm8 6.891h-1.998v-2.861c0-1.881-2.002-1.722-2.002 0v2.861h-2v-6h2v1.093c.872-1.616 4-1.736 4 1.548v3.359z" fill="currentColor"></path>
+                        </svg>
+                    </a>
+                </li>
+                <li class="nav-item">
+                    <a class="nav-link" href="{{ SOCIAL.twitter }}">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                            <title>Twitter</title>
+                            <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm6.066 9.645c.183 4.04-2.83 8.544-8.164 8.544-1.622 0-3.131-.476-4.402-1.291 1.524.18 3.045-.244 4.252-1.189-1.256-.023-2.317-.854-2.684-1.995.451.086.895.061 1.298-.049-1.381-.278-2.335-1.522-2.304-2.853.388.215.83.344 1.301.359-1.279-.855-1.641-2.544-.889-3.835 1.416 1.738 3.533 2.881 5.92 3.001-.419-1.796.944-3.527 2.799-3.527.825 0 1.572.349 2.096.907.654-.128 1.27-.368 1.824-.697-.215.671-.67 1.233-1.263 1.589.581-.07 1.135-.224 1.649-.453-.384.578-.87 1.084-1.433 1.489z" fill="currentColor"></path>
+                        </svg>
+                    </a>
+                </li>
+            </ul>
+        </div>
+    </nav>
+
+    <!-- Full page -->
+    <div class="flex-shrink-0 flex-grow-1">
+    {% block page %}
+
+        <!-- Header -->
+        <header class="bg-dark text-light shadow-sm pt-3 pb-2">
+            {% block header %}{% endblock header %}
+        </header>
+
+        <!-- Main -->
+        <main class="py-3">
+            {% block main %}
+                <div class="container">
+                    <!-- Sharing -->
+                    {% block add_this %}
+                    {% if ADD_THIS_ID and (page_name or page or article) %}
+                        <div class="text-right mb-2 small" style="height: 26px">
+                            <div class="addthis_inline_share_toolbox"></div>
+                        </div>
+                    {% endif %}
+                    {% endblock add_this %}
+
+                    <!-- Content -->
+                    {% block content %}
+                    {% endblock content %}
+                </div>
+            {% endblock main %}
+        </main>
+
+    {% endblock page %}
+    </div>
+
+    <!-- Footer -->
+    <footer class="flex-shrink-0 bg-dark text-light small py-1">
+        <div class="container text-center">
+            &copy; {{ COPYRIGHT_YEAR }} <a href="{{ SITEURL}}">{{ SITENAME }}</a> by <a href="{{ SITEURL }}/pages/about.html">{{ AUTHOR }}</a>. Powered by <a href="http://getpelican.com">Pelican</a>, <a href="http://python.org">Python</a>, <a href="https://getbootstrap.com">Bootstrap 4</a><br>
+            <!-- Do not remove below license sentence -->
+            License: <a href="https://spdx.org/licenses/CC-BY-4.0.html">CC-BY-4.0</a>, based on <a href="https://github.com/vuquangtrong/simplify-theme">Simplify Bootstrap Theme</a>
+        </div>
+    </footer>
+
+    <!-- Scripts -->
+    <!--
+    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
+    -->
+    <script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/jquery/jquery-3.4.1.min.js"></script>
+    <!--
+    <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/4.3.1/bootstrap.min.js"></script>
+    -->
+    <script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/bootstrap/bootstrap.min.js"></script>
+    <!--
+    <script src="https://cdn.rawgit.com/afeld/bootstrap-toc/v1.0.1/dist/bootstrap-toc.min.js"></script>
+    -->
+    {% if article and article.toc == 'show' %}
+        <script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/extra/bootstrap-toc.min.js"></script>
+    {% endif %}
+    {% if page_name == 'search' %}
+        <script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/tipuesearch/tipuesearch.min.js"></script>
+        <script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/tipuesearch/tipuesearch.cfg.js"></script>
+        <script src="{{ SITEURL }}//tipuesearch_content.js"></script>
+        <script>
+            $(document).ready(function() {
+                 $('#tipue_search_input').tipuesearch();
+            });
+        </script>
+    {% endif %}
+    <script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/style.js"></script>
+
+    <!-- Sharing -->
+    {% if ADD_THIS_ID and (page_name or page or article) %}
+        <script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid={{ ADD_THIS_ID }}"></script>
+    {% endif %}
+
+    <!-- JSON LD -->
+    {% block jsonld %}
+        {% if article %}
+            {% include "include/jsonld_article.html" %}
+        {% else %}
+            {% include "include/jsonld.html" %}
+        {% endif %}
+    {% endblock jsonld %}
+
+    <!-- Disqus count -->
+    {% block disqus_count %}
+    {% endblock disqus_count %}
+</body>
+
+</html>

+ 78 - 0
custom-theme/templates/categories.html

@@ -0,0 +1,78 @@
+{% extends "index.html" %}
+
+{% block title %}
+    Categories &ndash; {{ SITENAME }}
+{% endblock title %}
+
+{% block header %}
+    <div class="container">
+        <div class="row">
+            <div class="col-8">
+                <h3 id="Categories in {{ SITENAME }}" style="color: orange;">Categories in {{ SITENAME }}</h3>
+            </div>
+            <div class="col-4 small" style="margin-top: 0.5rem;">
+                {% if ADD_THIS_ID and (page_name or page or article) %}
+                    <div class="text-right mb-2 small" style="height: 26px">
+                        <div class="addthis_inline_share_toolbox"></div>
+                    </div>
+                {% endif %}
+            </div>
+        </div>
+    </div>
+{% endblock header %}
+
+{% block add_this %}
+{# remove ADD_THIS in content, move to above header #}
+{% endblock add_this %}
+
+{% block content %}
+    <!--
+	<div class="text-center">
+		{% for category, articles in categories|sort %}
+			<a class="btn btn-success btn-sm" href="{{ SITEURL }}/{{ category.url }}">
+			  {{ category|lower }}  <span class="badge badge-warning" style="font-size: small;">{{ articles|count }}</span>
+			</a>
+		{% endfor %}
+	</div>
+    -->
+
+    <!-- Accordion -->
+    <div id="accordionList" class="accordion shadow">
+        {% for category, articles in categories|sort %}
+            <!-- Accordion items -->
+            <div class="card">
+                <div id="heading_{{ category|lower }}" class="card-header bg-white shadow-sm border-0">
+                    <h2 class="mb-0">
+                        <button type="button" data-toggle="collapse" data-target="#collapse{{ category|lower }}" aria-expanded="false" aria-controls="collapse{{ category|lower }}" class="btn btn-link text-dark font-weight-bold collapsible-link collapsed">
+                            {{ category|lower }}  <span class="badge badge-warning" style="font-size: small;">{{ articles|count }}</span>
+                        </button>
+                    </h2>
+                </div>
+                <!-- Item list -->
+                <div id="collapse{{ category|lower }}" aria-labelledby="heading_{{ category|lower }}" data-parent="#accordionList" class="collapse" style="background-color: whitesmoke">
+                    {% for article in articles %}
+                    <div class="card-body border-bottom">
+                        <a  class="m-0" href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a><br>
+                        <span class="small">by <a href="{{ SITEURL }}/{{ article.author.url }}" style="color: darkblue;">{{ article.author }}</a>, post on <span class="text-success">{{ article.locale_date }}</span></span>
+                    </div>
+                    {% endfor %}
+                </div>
+            </div>
+        {% endfor %}
+    </div>
+    
+    <!-- Google Adsense -->
+    {% if GOOGLE_ADSENSE and GOOGLE_ADSENSE.ads.page %}
+        <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+        <!-- ad-home -->
+        <ins class="adsbygoogle"
+             style="display:block"
+             data-ad-client="{{ GOOGLE_ADSENSE.id }}"
+             data-ad-slot="{{ GOOGLE_ADSENSE.ads.page }}"
+             data-ad-format="auto"
+             data-full-width-responsive="true"></ins>
+        <script>
+             (adsbygoogle = window.adsbygoogle || []).push({});
+        </script>
+    {% endif %}
+{% endblock content %}

+ 1 - 0
custom-theme/templates/include/claim_bing.html

@@ -0,0 +1 @@
+<meta name="msvalidate.01" content="{{ CLAIM_BING }}" />

+ 1 - 0
custom-theme/templates/include/claim_google.html

@@ -0,0 +1 @@
+<meta name="google-site-verification" content="{{ CLAIM_GOOGLE }}" />

+ 10 - 0
custom-theme/templates/include/disqus.html

@@ -0,0 +1,10 @@
+<div id="disqus_thread"></div>
+<script type="text/javascript">
+    var disqus_shortname = '{{ DISQUS_SITENAME }}';
+    (function() {
+        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
+        dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
+        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
+    })();
+</script>
+<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>

+ 1 - 0
custom-theme/templates/include/disqus_count.html

@@ -0,0 +1 @@
+<script id="dsq-count-scr" src="//{{ DISQUS_SITENAME }}.disqus.com/count.js" async="async"></script>

+ 11 - 0
custom-theme/templates/include/ga.html

@@ -0,0 +1,11 @@
+<script>
+(function(i, s, o, g, r, a, m) { i['GoogleAnalyticsObject'] = r;
+    i[r] = i[r] || function() {
+        (i[r].q = i[r].q || []).push(arguments) }, i[r].l = 1 * new Date();
+    a = s.createElement(o), m = s.getElementsByTagName(o)[0];
+    a.async = 1;
+    a.src = g;
+    m.parentNode.insertBefore(a, m) })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
+ga('create', '{{ GOOGLE_ANALYTICS }}', 'auto');
+ga('send', 'pageview');
+</script>

+ 7 - 0
custom-theme/templates/include/gtag.html

@@ -0,0 +1,7 @@
+<script async src="https://www.googletagmanager.com/gtag/js?id={{ GOOGLE_SITE_TAG }}"></script>
+<script>
+	window.dataLayer = window.dataLayer || [];
+	function gtag() { dataLayer.push(arguments); }
+	gtag('js', new Date());
+	gtag('config', '{{ GOOGLE_SITE_TAG }}');
+</script>

+ 12 - 0
custom-theme/templates/include/gtm.html

@@ -0,0 +1,12 @@
+<script>
+(function(w, d, s, l, i) {
+    w[l] = w[l] || [];
+    w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
+    var f = d.getElementsByTagName(s)[0],
+        j = d.createElement(s),
+        dl = l != 'dataLayer' ? '&l=' + l : '';
+    j.async = true;
+    j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
+    f.parentNode.insertBefore(j, f);
+})(window, document, 'script', 'dataLayer', '{{ GOOGLE_TAG_MANAGER }}');
+</script>

+ 3 - 0
custom-theme/templates/include/gtm_noscript.html

@@ -0,0 +1,3 @@
+<noscript>
+    <iframe src="https://www.googletagmanager.com/ns.html?id={{ GOOGLE_TAG_MANAGER }}" height="0" width="0" style="display:none;visibility:hidden"></iframe>
+</noscript>

+ 4 - 0
custom-theme/templates/include/ha.html

@@ -0,0 +1,4 @@
+<script type="text/javascript">
+    window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","resetIdentity","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
+      heap.load("{{ HEAP_ANALYTICS }}");
+</script>

+ 10 - 0
custom-theme/templates/include/jsonld.html

@@ -0,0 +1,10 @@
+<script type="application/ld+json">
+{
+    "@context": "http://schema.org",
+    "@type": "Blog",
+    "name": " {{ SITENAME }} ",
+    "url": "{{ SITEURL }}",
+    "image": "{{ SITEURL }}/{{ SITELOGO }}",
+    "description": "{{ SITEDESCRIPTION }}"
+}
+</script>

+ 23 - 0
custom-theme/templates/include/jsonld_article.html

@@ -0,0 +1,23 @@
+{% if SITELOGO %}
+    {% set default_cover = SITEURL + '/' + SITELOGO %}
+{% else %}
+    {% set default_cover = SITEURL + '/' + 'favicon.ico' %}
+{% endif %}
+<script type="application/ld+json">
+{
+    "@context": "http://schema.org",
+    "@type": "BlogPosting",
+    "name": "{{ article.title|striptags }}",
+    "headline": "{{ article.title|striptags }}",
+    "datePublished": "{{ article.date }}",
+    "dateModified": "{{ article.modified }}",
+    "author": {
+        "@type": "Person",
+        "name": "{{ article.author.name }}",
+        "url": "{{ SITEURL }}/{{ article.author.url }}"
+    },
+    "image": "{{ article.metadata.get('cover', default_cover) }}",
+    "url": "{{ SITEURL }}/{{ article.url }}",
+    "description": "{{ article.summary|striptags }}"
+}
+</script>

+ 19 - 0
custom-theme/templates/include/matomo.html

@@ -0,0 +1,19 @@
+<script type="text/javascript">
+var _paq = window._paq || [];
+/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+_paq.push(['trackPageView']);
+_paq.push(['enableLinkTracking']);
+(function() {
+    var u = "https://{{ MATOMO_SITENAME }}.matomo.cloud/";
+    _paq.push(['setTrackerUrl', u + 'matomo.php']);
+    _paq.push(['setSiteId', '1']);
+    var d = document,
+        g = d.createElement('script'),
+        s = d.getElementsByTagName('script')[0];
+    g.type = 'text/javascript';
+    g.async = true;
+    g.defer = true;
+    g.src = '//cdn.matomo.cloud/{{ MATOMO_SITENAME }}.matomo.cloud/matomo.js';
+    s.parentNode.insertBefore(g, s);
+})();
+</script>

+ 12 - 0
custom-theme/templates/include/neighbors.html

@@ -0,0 +1,12 @@
+<div class="pagination">
+    {% if article.prev_article %}
+    <a class="{% if article.next_article %}w-50{% else %}w-100{% endif %}" href="{{ SITEURL }}/{{ article.prev_article.url }}">
+        {% if article.next_article %}&ll; {% endif %}{{ article.prev_article.title }}
+    </a>
+    {% endif %}
+    {% if article.next_article %}
+    <a class="{% if article.prev_article %}w-50{% else %}w-100{% endif %} {% if article.prev_article %}text-right{% endif %}" href="{{ SITEURL }}/{{ article.next_article.url }}">
+        {{ article.next_article.title }}{% if article.prev_article %} &gg;{% endif %}
+    </a>
+    {% endif %}
+</div>

+ 12 - 0
custom-theme/templates/include/og.html

@@ -0,0 +1,12 @@
+{% if OG_LOCALE %}
+	{% set default_locale = OG_LOCALE %}
+{% else %}
+	{% set default_locale = 'en_US' %}
+{% endif %}
+<meta property="og:site_name" content="{{ SITENAME }}" />
+<meta property="og:type" content="blog" />
+<meta property="og:title" content="{{ SITENAME }}" />
+<meta property="og:description" content="{{ SITEDESCRIPTION }}" />
+<meta property="og:locale" content="{{ default_locale }}" />
+<meta property="og:url" content="{{ SITEURL }}" />
+<meta property="og:image" content="{{ SITEURL }}/{{ SITELOGO }}">

+ 23 - 0
custom-theme/templates/include/og_article.html

@@ -0,0 +1,23 @@
+{% if OG_LOCALE %}
+	{% set default_locale = OG_LOCALE %}
+{% else %}
+	{% set default_locale = 'en_US' %}
+{% endif %}
+<meta property="og:site_name" content="{{ SITENAME }}" />
+<meta property="og:title" content="{{ article.title|striptags|escape }}" />
+<meta property="og:description" content="{{ article.summary|striptags|escape }}" />
+<meta property="og:locale" content="{{ article.metadata.get('og_locale', default_locale) }}" />
+<meta property="og:url" content="{{ SITEURL }}/{{ article.url }}" />
+<meta property="og:type" content="article" />
+<meta property="article:published_time" content="{{ article.date }}" />
+<meta property="article:modified_time" content="{{ article.modified }}" />
+<meta property="article:author" content="{{ SITEURL }}/{{ article.author.url }}">
+<meta property="article:section" content="{{ article.category.name }}" />
+{% for tag in article.tags %}
+	<meta property="article:tag" content="{{ tag.name|escape }}" />
+{% endfor %}
+{% if 'cover' in article.metadata %}
+	<meta property="og:image" content="{{ SITEURL }}/{{ ARTICLE_PRIMARY_PATH }}/{{ article.category|lower }}/{{ article.metadata['cover'] }}">
+{% else %}
+	<meta property="og:image" content="{{ SITEURL }}/{{ SITELOGO }}">
+{% endif %}

+ 12 - 0
custom-theme/templates/include/pagination.html

@@ -0,0 +1,12 @@
+<div class="pagination px-2">
+    {% if articles_page.has_next() %}
+    <a class="{% if articles_page.has_previous() %}w-50{% else %}w-100{% endif %}" href="{{ SITEURL }}/{{ articles_next_page.url }}">
+        &ll; Older Posts
+    </a>
+    {% endif %}
+    {% if articles_page.has_previous() %}
+    <a class="{% if articles_page.has_next() %}w-50{% else %}w-100{% endif %} text-right" href="{{ SITEURL }}/{{ articles_previous_page.url }}">
+        Newer Posts &gg;
+    </a>
+    {% endif %}
+</div>

+ 17 - 0
custom-theme/templates/include/piwik.html

@@ -0,0 +1,17 @@
+{% if PIWIK_SITE_ID and PIWIK_URL %}
+    {% if PIWIK_SSL_URL is not defined %}
+        {% set PIWIK_SSL_URL = PIWIK_URL %}
+    {% endif %}
+    <script type="text/javascript">
+        var _paq = _paq || [];
+        _paq.push(["trackPageView"]);
+        _paq.push(["enableLinkTracking"]);
+        (function() {
+            var u=(("https:" == document.location.protocol) ? "https://{{ PIWIK_SSL_URL }}/" : "http://{{ PIWIK_URL }}/");
+            _paq.push(["setTrackerUrl", u+"piwik.php"]);
+            _paq.push(["setSiteId", "{{ PIWIK_SITE_ID }}"]);
+            var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
+            g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
+        })();
+    </script>
+{% endif %}

+ 73 - 0
custom-theme/templates/index.html

@@ -0,0 +1,73 @@
+{% extends "base.html" %}
+
+{% block meta %}
+    <meta name="author" content="{{ AUTHOR }}" />
+    <meta name="description" content="{{ SITEDESCRIPTION }}" />
+    {% include "include/og.html" %}
+{% endblock %}
+
+{% block header %}
+    <div class="container">
+        <h1 id="{{ SITENAME }}">{{ SITENAME }}</h1>
+        <p style="font-size: larger; color: orange;">{{ SITEDESCRIPTION }}</p>
+    </div>
+{% endblock header %}
+
+{% block content %}
+    <!-- List of article -->
+    {% for article in articles_page.object_list %}
+        <div class="card mb-2 shadow-sm">
+            <div class="card-body">
+                <h5 class="card-title" style="margin-bottom: 0;">
+                    <a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a>
+                </h5>
+                <span class="small">by <a href="{{ SITEURL }}/{{ article.author.url }}">{{ article.author }}</a>, post on <span class="text-success">{{ article.locale_date }}</span></span>
+                <p>{{ article.summary }}</p>
+                <div class="flex-row mx-auto mt-3 small">
+                    <div class="float-left">
+                        {% if article.stats %}
+                            <span class="card-link text-secondary" title="~{{ article.stats['wc'] }} words">Read in {{ article.stats['read_mins'] }} mins</span>
+                        {% elif article.readtime %}
+                            <span class="card-link text-secondary" title="Read time">Read in {{ article.readtime }}</span>
+                        {% endif %}
+                        {% if DISQUS_SITENAME %}
+                            <span class="card-link"><a href="{{ SITEURL }}/{{ article.url }}#disqus_thread"></a></span>
+                        {% endif %}
+                    </div>
+                    <div class=" float-right">
+                        <a class="badge badge-success" href="{{ SITEURL }}/{{ article.category.url }}">{{ article.category|lower }}</a>
+                        {% for tag in article.tags %}
+                            <a class="badge badge-info" href="{{ SITEURL }}/{{ tag.url }}">{{ tag|lower }}</a>
+                        {% endfor %}
+                    </div>
+                </div>
+            </div>
+        </div>
+    {% endfor %}
+
+    <!-- Pagination -->
+    {% if DEFAULT_PAGINATION %}
+        {% include "include/pagination.html" %}
+    {% endif %}
+
+    <!-- Google Adsense -->
+    {% if GOOGLE_ADSENSE and GOOGLE_ADSENSE.ads.home %}
+        <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+        <!-- ad-home -->
+        <ins class="adsbygoogle"
+             style="display:block"
+             data-ad-client="{{ GOOGLE_ADSENSE.id }}"
+             data-ad-slot="{{ GOOGLE_ADSENSE.ads.home }}"
+             data-ad-format="auto"
+             data-full-width-responsive="true"></ins>
+        <script>
+             (adsbygoogle = window.adsbygoogle || []).push({});
+        </script>
+    {% endif %}
+{% endblock content %}
+
+{% block disqus_count %}
+    {% if DISQUS_SITENAME %}
+        {% include "include/disqus_count.html" %}
+    {% endif %}
+{% endblock disqus_count %}

+ 39 - 0
custom-theme/templates/page.html

@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+
+{% if page.lang %}
+    {% block html_lang %}{{ page.lang }}{% endblock html_lang %}
+{% endif %}
+
+{% block title %}
+    {{ page.title }} &ndash; {{ SITENAME }}
+{% endblock title %}
+
+{% block header %}
+    <div class="container">
+        <div class="row">
+            <div class="col-8">
+                <h3 id="{{ page.title }}" style="color: orange;">{{ page.title }}</h3>
+                {% if page.modified %}
+                    <p class="text-light">Last updated: {{ page.locale_modified }}</p>
+                {% else %}
+                    <p class="text-light">Post on: {{ page.locale_date }}</p>
+                {% endif %}
+            </div>
+            <div class="col-4 small" style="margin-top: 0.5rem;">
+                {% if ADD_THIS_ID and (page_name or page or article) %}
+                    <div class="text-right mb-2 small" style="height: 26px">
+                        <div class="addthis_inline_share_toolbox"></div>
+                    </div>
+                {% endif %}
+            </div>
+        </div>
+    </div>
+{% endblock header %}
+
+{% block add_this %}
+{# remove ADD_THIS in content, move to above header #}
+{% endblock add_this %}
+
+{% block content %}
+    {{ page.content }}
+{% endblock content %}

+ 61 - 0
custom-theme/templates/search.html

@@ -0,0 +1,61 @@
+{% extends "index.html" %}
+
+{% block title %}
+    Search &ndash; {{ SITENAME }}
+{% endblock title %}
+
+{% block header %}
+    <div class="container">
+        <div class="row">
+            <div class="col-8">
+                <h3 id="Search in {{ SITENAME }}" style="color: orange;">Search in {{ SITENAME }}</h3>
+            </div>
+            <div class="col-4 small" style="margin-top: 0.5rem;">
+                {% if ADD_THIS_ID and (page_name or page or article) %}
+                    <div class="text-right mb-2 small" style="height: 26px">
+                        <div class="addthis_inline_share_toolbox"></div>
+                    </div>
+                {% endif %}
+            </div>
+        </div>
+    </div>
+{% endblock header %}
+
+{% block add_this %}
+{# remove ADD_THIS in content, move to above header #}
+{% endblock add_this %}
+
+{% block content %}
+    <!-- Tipue Search -->
+    <form>
+        <div class="tipue_search_group">
+            <input type="text" name="q" id="tipue_search_input" pattern=".{3,}" title="At least 3 characters" required>
+            <button type="submit" class="tipue_search_button">
+                <div class="tipue_search_icon">&#9906;</div>
+            </button>
+        </div>
+    </form>
+
+    <div id="tipue_search_content"></div>
+
+    <!-- Google Adsense -->
+    {% if GOOGLE_ADSENSE and GOOGLE_ADSENSE.ads.page %}
+        <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+        <!-- ad-home -->
+        <ins class="adsbygoogle"
+             style="display:block"
+             data-ad-client="{{ GOOGLE_ADSENSE.id }}"
+             data-ad-slot="{{ GOOGLE_ADSENSE.ads.page }}"
+             data-ad-format="auto"
+             data-full-width-responsive="true"></ins>
+        <script>
+             (adsbygoogle = window.adsbygoogle || []).push({});
+        </script>
+    {% endif %}
+
+    <!-- Google Search -->
+    {% if GOOGLE_CSE_ID %}
+        <script async src="https://cse.google.com/cse.js?cx=007986648373531383257:hnbvizg2lks"></script>
+        <div class="gcse-search"></div>
+    {% endif %} 
+{% endblock content %}

+ 92 - 0
custom-theme/templates/tags.html

@@ -0,0 +1,92 @@
+{% extends "index.html" %}
+
+{% block title %}
+    Tags &ndash; {{ SITENAME }}
+{% endblock title %}
+
+{% block header %}
+    <div class="container">
+        <div class="row">
+            <div class="col-8">
+                <h3 id="Tags in {{ SITENAME }}" style="color: orange;">Tags in {{ SITENAME }}</h3>
+            </div>
+            <div class="col-4 small" style="margin-top: 0.5rem;">
+                {% if ADD_THIS_ID and (page_name or page or article) %}
+                    <div class="text-right mb-2 small" style="height: 26px">
+                        <div class="addthis_inline_share_toolbox"></div>
+                    </div>
+                {% endif %}
+            </div>
+        </div>
+    </div>
+{% endblock header %}
+
+{% block add_this %}
+{# remove ADD_THIS in content, move to above header #}
+{% endblock add_this %}
+
+{% block content %}
+    <!--    
+	<div class="text-center">
+		{% for tag, articles in tags|sort %}
+			<a class="btn btn-info btn-sm" href="{{ SITEURL }}/{{ tag.url }}">
+			  {{ tag|lower }}  <span class="badge badge-light" style="font-size: small;">{{ articles|count }}</span>
+			</a>
+		{% endfor %}
+	</div>
+    -->
+    
+    <!-- Tags cloud -->
+    <ul class="tagcloud">
+        {% if tag_cloud %}
+            {% for tag in tag_cloud %}
+                <li class="tag-{{ tag.1 }}">
+                    <a href="{{ SITEURL }}/{{ tag.0.url }}">{{ tag.0 }}</a>
+                    {% if TAG_CLOUD_BADGE %}
+                        <sup><span class="badge badge-info">{{ tag.2 }}</span></sup>
+                    {% endif %}
+                </li>
+            {% endfor %}
+        {% endif %}
+    </ul>
+
+    <!-- Accordion -->
+    <div id="accordionList" class="accordion shadow">
+        {% for tag, articles in tags|sort %}
+            <!-- Accordion items -->
+            <div class="card">
+                <div id="heading_{{ tag|lower }}" class="card-header bg-white shadow-sm border-0">
+                    <h2 class="mb-0">
+                        <button type="button" data-toggle="collapse" data-target="#collapse{{ tag|lower }}" aria-expanded="false" aria-controls="collapse{{ tag|lower }}" class="btn btn-link text-dark font-weight-bold collapsible-link collapsed">
+                            {{ tag|lower }}  <span class="badge badge-warning" style="font-size: small;">{{ articles|count }}</span>
+                        </button>
+                    </h2>
+                </div>
+                <!-- Item list -->
+                <div id="collapse{{ tag|lower }}" aria-labelledby="heading_{{ tag|lower }}" data-parent="#accordionList" class="collapse" style="background-color: whitesmoke">
+                    {% for article in articles %}
+                    <div class="card-body border-bottom">
+                        <a  class="m-0" href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a><br>
+                        <span class="small">by <a href="{{ SITEURL }}/{{ article.author.url }}" style="color: darkblue;">{{ article.author }}</a>, post on <span class="text-success">{{ article.locale_date }}</span></span>
+                    </div>
+                    {% endfor %}
+                </div>
+            </div>
+        {% endfor %}
+    </div>
+
+    <!-- Google Adsense -->
+    {% if GOOGLE_ADSENSE and GOOGLE_ADSENSE.ads.page %}
+        <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+        <!-- ad-home -->
+        <ins class="adsbygoogle"
+             style="display:block"
+             data-ad-client="{{ GOOGLE_ADSENSE.id }}"
+             data-ad-slot="{{ GOOGLE_ADSENSE.ads.page }}"
+             data-ad-format="auto"
+             data-full-width-responsive="true"></ins>
+        <script>
+             (adsbygoogle = window.adsbygoogle || []).push({});
+        </script>
+    {% endif %}
+{% endblock content %}

+ 1 - 1
pelicanconf.py

@@ -30,7 +30,7 @@ DATE_FORMATS = {
 
 # Build settings
 PATH = 'content'
-THEME = 'simplify-theme'
+THEME = 'custom-theme'
 
 ARTICLE_PATHS = [
 	'blog'

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác