|  |  |  |  | --- | 
					
						
							|  |  |  |  | layout: default | 
					
						
							|  |  |  |  | --- | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <small><time class="date dt-published" datetime="{{ page.date | date_to_xmlschema }}">{{ page.date | date: "%-d %B %Y" }}</time> - 字数统计:{% if page.layout == "encrypt" %}God Knows {% else %}{{ page.content | strip_html | strip_newlines | remove: " " | size }} - 阅读大约需要{{ page.content | strip_html | strip_newlines | remove: "" | size | divided_by: 350 | plus: 1 }}分钟{% endif %} - Hits: <span id="{{ page.url }}" class="visitors">Loading...</span></small> | 
					
						
							|  |  |  |  | <h1 class="p-name">{{ page.title }}</h1> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <p class="view">by <a class="p-author h-card" href="//github.com/{{ page.author | default: "Mabbs" }}">{{ page.author | default: site.author }}</a></p> | 
					
						
							|  |  |  |  | <div id="outdate" style="display:none;"> | 
					
						
							|  |  |  |  |   <hr /><p> | 
					
						
							|  |  |  |  |   这是一篇创建于 <span id="outime"></span> 天前的文章,其中的信息可能已经有所发展或是发生改变。 | 
					
						
							|  |  |  |  |   </p> | 
					
						
							|  |  |  |  | </div> | 
					
						
							|  |  |  |  | <script> | 
					
						
							|  |  |  |  |   daysold = Math.floor((new Date().getTime() - new Date("{{ page.date | date_to_rfc822 }}").getTime()) / (24 * 60 * 60 * 1000)); | 
					
						
							|  |  |  |  |   if (daysold > 90) { | 
					
						
							|  |  |  |  |     document.getElementById("outdate").style.display = "block"; | 
					
						
							|  |  |  |  |     document.getElementById("outime").innerHTML = daysold; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | </script> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <hr /> | 
					
						
							|  |  |  |  | {% if page.layout != "encrypt" %} | 
					
						
							|  |  |  |  | <b>AI摘要</b> | 
					
						
							|  |  |  |  | <p id="ai-output">{% assign ai_cache = site.data.ai-cache[page.url] %}{% if ai_cache %}{{ ai_cache }}{% else %}正在生成中……{% endif %}</p> | 
					
						
							|  |  |  |  | {% unless ai_cache %} | 
					
						
							|  |  |  |  | <!--[if IE]>
 | 
					
						
							|  |  |  |  |   <script>document.getElementById("ai-output").innerHTML="这个文章的AI摘要还没有缓存……IE看不了哦~";</script> | 
					
						
							|  |  |  |  | <![endif]--> | 
					
						
							|  |  |  |  | <!--[if !IE]> --> | 
					
						
							|  |  |  |  | <script> | 
					
						
							|  |  |  |  |   async function sha(str) { | 
					
						
							|  |  |  |  |     const encoder = new TextEncoder(); | 
					
						
							|  |  |  |  |     const data = encoder.encode(str); | 
					
						
							|  |  |  |  |     const hashBuffer = await crypto.subtle.digest("SHA-256", data); | 
					
						
							|  |  |  |  |     const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array | 
					
						
							|  |  |  |  |     const hashHex = hashArray | 
					
						
							|  |  |  |  |       .map((b) => b.toString(16).padStart(2, "0")) | 
					
						
							|  |  |  |  |       .join(""); // convert bytes to hex string | 
					
						
							|  |  |  |  |     return hashHex; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   async function ai_gen(){ | 
					
						
							|  |  |  |  |     var postContent = "文章标题:" + {{ page.title | jsonify }} + ";文章内容:" + {{ page.content | strip_html | strip_newlines | jsonify }}; | 
					
						
							|  |  |  |  |     var postContentSign = await sha(postContent); | 
					
						
							|  |  |  |  |     var outputContainer = document.getElementById("ai-output"); | 
					
						
							|  |  |  |  |     $.get(BlogAPI + "/is_uploaded?id={{ page.url }}&sign=" + postContentSign, function (data) { | 
					
						
							|  |  |  |  |       if (data == "yes") { | 
					
						
							|  |  |  |  |         $.get(BlogAPI + "/get_summary?id={{ page.url }}&sign=" + postContentSign, function (data2) { | 
					
						
							|  |  |  |  |           outputContainer.textContent = data2; | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  |       } else { | 
					
						
							|  |  |  |  |         $.post(BlogAPI + "/upload_blog?id={{ page.url }}", postContent, function (data) { | 
					
						
							|  |  |  |  |           $.get(BlogAPI + "/get_summary?id={{ page.url }}&sign=" + postContentSign); | 
					
						
							|  |  |  |  |           const evSource = new EventSource(BlogAPI + "/summary?id={{ page.url }}"); | 
					
						
							|  |  |  |  |           outputContainer.textContent = ""; | 
					
						
							|  |  |  |  |           evSource.onmessage = (event) => { | 
					
						
							|  |  |  |  |             if (event.data == "[DONE]") { | 
					
						
							|  |  |  |  |               evSource.close(); | 
					
						
							|  |  |  |  |               return; | 
					
						
							|  |  |  |  |             } else { | 
					
						
							|  |  |  |  |               const data = JSON.parse(event.data); | 
					
						
							|  |  |  |  |               outputContainer.textContent += data.response; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   ai_gen(); | 
					
						
							|  |  |  |  | </script> | 
					
						
							|  |  |  |  | <!-- <![endif]--> | 
					
						
							|  |  |  |  | {% endunless %} | 
					
						
							|  |  |  |  | <hr /> | 
					
						
							|  |  |  |  | {% endif %} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | {% if page.layout != "encrypt" %} | 
					
						
							|  |  |  |  | {% include toc.html html=content sanitize=true h_max=3 %} | 
					
						
							|  |  |  |  | <hr /> | 
					
						
							|  |  |  |  | {% endif %} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | {% if page.layout == "encrypt" %} {{content}} {% else %} <main class="post-content e-content" role="main">{% capture a_post_content %}{% include anchor_headings.html html=content beforeHeading=true anchorBody="<svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>" %}{% endcapture %}{{ a_post_content | replace: '<br />', '</p><p>' }}</main> {% endif %} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | {% if page.tags %} | 
					
						
							|  |  |  |  | <small style="display: block">tags: {% for tag in page.tags %}<a rel="category tag" class="p-category" href="/search.html?keyword={{ tag | url_encode | replace: '+', '%20' }}"><em>{{ tag }}</em></a>{% unless forloop.last %} - {% endunless %}{% endfor %} <span style="float: right;"><a href="{% if site.github %}{{ site.github.repository_url }}{% else %}https://gitlab.com/mayx/mayx.gitlab.io{% endif %}/tree/master/{{ page.path }}">查看原始文件</a></span></small> | 
					
						
							|  |  |  |  | {% endif %} | 
					
						
							|  |  |  |  | {% if page.layout != "encrypt" %} | 
					
						
							|  |  |  |  | <h4 style="border-bottom: 1px solid #e5e5e5;margin: 2em 0 5px;">推荐文章</h4> | 
					
						
							|  |  |  |  | <p id="suggest-container">Loading...</p> | 
					
						
							|  |  |  |  | <script> | 
					
						
							|  |  |  |  | var suggest = $("#suggest-container"); | 
					
						
							|  |  |  |  | $.get(BlogAPI + "/suggest?id={{ page.url }}&update=" + lastUpdated.valueOf(), function (data) { | 
					
						
							|  |  |  |  |   if (data.length) { | 
					
						
							|  |  |  |  |     getSearchJSON(function (search) { | 
					
						
							|  |  |  |  |       suggest.empty(); | 
					
						
							|  |  |  |  |       var searchMap = {}; | 
					
						
							|  |  |  |  |       for (var i = 0; i < search.length; i++) { | 
					
						
							|  |  |  |  |         searchMap[search[i].url] = search[i]; | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |        | 
					
						
							|  |  |  |  |       var tooltip = $('<div class="content-tooltip"></div>').appendTo('body').hide(); | 
					
						
							|  |  |  |  |       for (var j = 0; j < data.length; j++) { | 
					
						
							|  |  |  |  |         var item = searchMap[data[j].id]; | 
					
						
							|  |  |  |  |         if (item) { | 
					
						
							|  |  |  |  |           var link = $('<a href="' + item.url + '">' + item.title + '</a>'); | 
					
						
							|  |  |  |  |           var contentPreview = item.content.substring(0, 100); | 
					
						
							|  |  |  |  |           if (item.content.length > 100) { | 
					
						
							|  |  |  |  |                 contentPreview += "……"; | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |           link.hover( | 
					
						
							|  |  |  |  |             function(e) { | 
					
						
							|  |  |  |  |               tooltip.text($(this).data('content')) | 
					
						
							|  |  |  |  |                 .css({ | 
					
						
							|  |  |  |  |                   top: e.pageY + 10, | 
					
						
							|  |  |  |  |                   left: e.pageX + 10 | 
					
						
							|  |  |  |  |                 }) | 
					
						
							|  |  |  |  |                 .show(); | 
					
						
							|  |  |  |  |             }, | 
					
						
							|  |  |  |  |             function() { | 
					
						
							|  |  |  |  |               tooltip.hide(); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           ).mousemove(function(e) { | 
					
						
							|  |  |  |  |             tooltip.css({ | 
					
						
							|  |  |  |  |               top: e.pageY + 10, | 
					
						
							|  |  |  |  |               left: e.pageX + 10 | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |           }).data('content', contentPreview);  | 
					
						
							|  |  |  |  |            | 
					
						
							|  |  |  |  |           suggest.append(link); | 
					
						
							|  |  |  |  |           suggest.append(' - ' + item.date + '<br />'); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } else { | 
					
						
							|  |  |  |  |     suggest.html("暂无推荐文章……"); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | </script> | 
					
						
							|  |  |  |  | {% endif %} | 
					
						
							|  |  |  |  | <br /> | 
					
						
							|  |  |  |  | <div class="pagination"> | 
					
						
							|  |  |  |  |   {% if page.previous.url %} | 
					
						
							|  |  |  |  |   <span class="prev"> | 
					
						
							|  |  |  |  |     <a href="{{ page.previous.url | relative_url }}"> | 
					
						
							|  |  |  |  |       上一篇:{{ page.previous.title }} | 
					
						
							|  |  |  |  |     </a> | 
					
						
							|  |  |  |  |   </span> | 
					
						
							|  |  |  |  |   {% endif %} | 
					
						
							|  |  |  |  |   <br /> | 
					
						
							|  |  |  |  |   {% if page.next.url %} | 
					
						
							|  |  |  |  |   <span class="next"> | 
					
						
							|  |  |  |  |     <a href="{{ page.next.url | relative_url }}"> | 
					
						
							|  |  |  |  |       下一篇:{{ page.next.title }} | 
					
						
							|  |  |  |  |     </a> | 
					
						
							|  |  |  |  |   </span> | 
					
						
							|  |  |  |  |   {% endif %} | 
					
						
							|  |  |  |  | </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <!--[if !IE]> --> | 
					
						
							|  |  |  |  | <link rel="stylesheet" href="/assets/css/gitalk.css"> | 
					
						
							|  |  |  |  | <script src="/assets/js/gitalk.min.js"></script> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <div id="gitalk-container"></div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <script> | 
					
						
							|  |  |  |  |   var gitalk = new Gitalk({ | 
					
						
							|  |  |  |  |     clientID: '36557aec4c3cb04f7ac6', | 
					
						
							|  |  |  |  |     clientSecret: 'ac32993299751cb5a9ba81cf2b171cca65879cdb', | 
					
						
							|  |  |  |  |     repo: 'mabbs.github.io', | 
					
						
							|  |  |  |  |     owner: 'Mabbs', | 
					
						
							|  |  |  |  |     admin: ['Mabbs'], | 
					
						
							|  |  |  |  |     id: '{{ page.id }}',      // Ensure uniqueness and length less than 50 | 
					
						
							|  |  |  |  |     distractionFreeMode: false,  // Facebook-like distraction free mode | 
					
						
							|  |  |  |  |     proxy: "https://cors-anywhere.mayx.eu.org/?https://github.com/login/oauth/access_token" | 
					
						
							|  |  |  |  |   }) | 
					
						
							|  |  |  |  |   gitalk.render('gitalk-container') | 
					
						
							|  |  |  |  | </script> | 
					
						
							|  |  |  |  | <!-- <![endif]--> |