posts.html 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/2.1.0/showdown.min.js" integrity="sha512-LhccdVNGe2QMEfI3x4DVV3ckMRe36TfydKss6mJpdHjNFiV07dFpS2xzeZedptKZrwxfICJpez09iNioiSZ3hA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  2. <div class="ts-grid mobile:is-stacked">
  3. <div class="column is-4-wide">
  4. <!-- Post List -->
  5. <div class="ts-box">
  6. <div class="ts-content">
  7. <div class="ts-header is-heavy">Recent Posts</div>
  8. <div id="posts_list" class="ts-list has-top-spaced-small">
  9. </div>
  10. </div>
  11. </div>
  12. </div>
  13. <div class="column is-12-wide">
  14. <div id="posts_contents">
  15. <!-- Post Contents -->
  16. </div>
  17. </div>
  18. </div>
  19. <script>
  20. var postList = [];
  21. var currentPost = 0;
  22. /*
  23. Rendering for Posts
  24. */
  25. //Load a markdown file from URL and render it to target element
  26. function loadMarkdownToHTML(markdownURL, targetElement){
  27. fetch(markdownURL).then( r => r.text() ).then( text =>{
  28. var converter = new showdown.Converter();
  29. let targetHTML = converter.makeHtml(text);
  30. let processedEle = $(targetHTML);
  31. //Wrap images in a div with class ts-image
  32. processedEle.find("img").each(function() {
  33. let imgSrc = $(this).attr("src");
  34. console.log(imgSrc);
  35. $(this).wrap(`<div class="ts-image is-rounded"></div>`);
  36. $(this).attr("src", imgSrc);
  37. });
  38. processedEle.find("h1, h2, h3, h4, h5, h6, p").each(function() {
  39. $(this).addClass("ts-text");
  40. });
  41. // Add preload="none" to all video and audio elements
  42. processedEle.find("video, audio").each(function() {
  43. $(this).attr("preload", "none");
  44. });
  45. $(targetElement).html(processedEle);
  46. });
  47. }
  48. function initPosts(){
  49. $("#posts_list").html(`<a href="#!"><span class="ts-icon is-spinning is-circle-notch-icon"></span> Loading</a>`);
  50. $("#posts_contents").html(`
  51. <div class="ui active dimmer" id="loadingDimmer">
  52. <div class="ui text loader">Loading post contents</div>
  53. </div>
  54. `);
  55. loadValue("site-posts", function(data){
  56. $("#posts_list").html("");
  57. $("#posts_contents").html(``);
  58. try{
  59. postList = JSON.parse(decodeURIComponent(atob(data)));
  60. console.log(postList);
  61. // Sort posts by timestamp from latest to oldest
  62. postList.sort((a, b) => {
  63. let timestampA = parseInt(a.split("_")[0]);
  64. let timestampB = parseInt(b.split("_")[0]);
  65. return timestampB - timestampA;
  66. });
  67. let lastPostMonth = "";
  68. for (let i = 0; i < postList.length; i++) {
  69. let post = postList[i];
  70. let thisPostMonth = new Date(parseInt(post.split("_")[0]) * 1000).toLocaleString(undefined, { month: 'long' });
  71. let thisPostYear = new Date(parseInt(post.split("_")[0]) * 1000).getFullYear();
  72. console.log(post, thisPostMonth, thisPostYear);
  73. if (thisPostMonth != lastPostMonth) {
  74. appendMonthDividerToIndex(thisPostMonth + " " + thisPostYear);
  75. lastPostMonth = thisPostMonth;
  76. }
  77. renderIndex(post, i);
  78. }
  79. if (postList.length == 0){
  80. $("#posts_list").html(`No posts found`);
  81. $("#posts_contents").html(`No posts found`);
  82. }else{
  83. //Render the first post
  84. renderPost(postList[0]);
  85. }
  86. }catch(ex){
  87. console.log(ex);
  88. $("#posts_list").html(`No posts found`);
  89. $("#posts_contents").html(`No posts found`);
  90. }
  91. })
  92. }
  93. function loadPost(element){
  94. let postID = $(element).attr("postid");
  95. let filename = postList[postID];
  96. console.log(filename);
  97. $("#posts_contents").html(`
  98. <div class="ts-text is-center-aligned">Loading Post</div>
  99. `);
  100. renderPost(filename);
  101. //Scroll to the top of the page
  102. $("html, body").animate({ scrollTop: 0 }, "slow");
  103. }
  104. //Render the side menu index
  105. function renderIndex(filename, index){
  106. //Remove the timestamp
  107. let postTitle = filename.split("_");
  108. let timeStamp = postTitle.shift();
  109. postTitle = postTitle.join("_");
  110. //Pop the file extension
  111. postTitle = postTitle.split(".");
  112. postTitle.pop();
  113. postTitle = postTitle.join(".");
  114. //Create a wrapper element
  115. $("#posts_list").append(`
  116. <a href="#!" postid="${index}" onclick="loadPost(this);" class="ts-text is-link is-undecorated item">${postTitle}</a>
  117. `);
  118. }
  119. function appendMonthDividerToIndex(month){
  120. $("#posts_list").append(`
  121. <div class="ts-text is-header has-top-spaced-small">${month}</div>
  122. `);
  123. }
  124. //Render post
  125. function renderPost(filename){
  126. //Remove the timestamp
  127. let postTitle = filename.split("_");
  128. let timeStamp = postTitle.shift();
  129. postTitle = postTitle.join("_");
  130. //Pop the file extension
  131. postTitle = postTitle.split(".");
  132. postTitle.pop();
  133. postTitle = postTitle.join(".");
  134. var postTime = new Date(parseInt(timeStamp) * 1000).toLocaleDateString("en-US")
  135. //Create a wrapper element
  136. $("#posts_contents").html(`
  137. <div class="ts-box site-post" post_id="${timeStamp}">
  138. <div class="ts-content is-padded">
  139. <div class="ts-header is-heavy">${postTitle}</div>
  140. <div class="ts-text is-description has-top-spaced-small">
  141. ${postTime}
  142. </div>
  143. <div class="ts-divider has-top-spaced-small has-bottom-spaced-small"></div>
  144. <div class="ts-text postContent"></div>
  145. </div>
  146. </div>
  147. `);
  148. let targetElement = $(`.site-post[post_id='${timeStamp}']`).find(".postContent");
  149. loadMarkdownToHTML("/site/posts/" + filename,targetElement);
  150. }
  151. initPosts();
  152. </script>