Custom Ghost theme for my blog, based on Casper https://www.geber.ga
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

post.hbs 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. {{!< default}}
  2. {{!-- The tag above means: insert everything in this file
  3. into the {body} of the default.hbs template --}}
  4. <header class="site-header outer">
  5. <div class="inner">
  6. {{> "site-nav"}}
  7. </div>
  8. </header>
  9. {{!-- Everything inside the #post tags pulls data from the post --}}
  10. {{#post}}
  11. <main id="site-main" class="site-main outer">
  12. <div class="inner">
  13. <article class="post-full {{post_class}} {{#unless feature_image}}no-image{{/unless}}">
  14. <header class="post-full-header">
  15. <section class="post-full-meta">
  16. <time class="post-full-meta-date" datetime="{{date format="YYYY-MM-DD"}}">{{date format="D MMMM YYYY"}}</time>
  17. {{#primary_tag}}
  18. <span class="date-divider">/</span> <a href="{{url}}">{{name}}</a>
  19. {{/primary_tag}}
  20. </section>
  21. <h1 class="post-full-title">{{title}}</h1>
  22. </header>
  23. {{#if feature_image}}
  24. <figure class="post-full-image">
  25. {{!-- This is a responsive image, it loads different sizes depending on device
  26. https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}}
  27. <img
  28. srcset="{{img_url feature_image size="s"}} 300w,
  29. {{img_url feature_image size="m"}} 600w,
  30. {{img_url feature_image size="l"}} 1000w,
  31. {{img_url feature_image size="xl"}} 2000w"
  32. sizes="(max-width: 800px) 400px,
  33. (max-width: 1170px) 700px,
  34. 1400px"
  35. src="{{img_url feature_image size="xl"}}"
  36. alt="{{title}}"
  37. />
  38. </figure>
  39. {{/if}}
  40. <section class="post-full-content">
  41. <div class="post-content">
  42. {{content}}
  43. </div>
  44. </section>
  45. {{!-- Email subscribe form at the bottom of the page --}}
  46. {{#if @labs.subscribers}}
  47. <section class="subscribe-form">
  48. <h3 class="subscribe-form-title">Subscribe to {{@site.title}}</h3>
  49. <p>Get the latest posts delivered right to your inbox</p>
  50. {{subscribe_form placeholder="youremail@example.com"}}
  51. </section>
  52. {{/if}}
  53. <footer class="post-full-footer">
  54. {{!-- There are two options for how we display the byline/author-info.
  55. If the post has more than one author, we load a specific template
  56. from includes/byline-multiple.hbs, otherwise, we just use the
  57. default byline. --}}
  58. {{#has author="count:>1"}}
  59. {{> "byline-multiple"}}
  60. {{else}}
  61. {{> "byline-single"}}
  62. {{/has}}
  63. </footer>
  64. {{!-- Isso (hardcoded) --}}
  65. <script data-isso="https://isso.geber.ga/" src="https://isso.geber.ga/js/embed.min.js"></script>
  66. <section id="isso-thread"></section>
  67. </article>
  68. </div>
  69. </main>
  70. <aside class="read-next outer">
  71. <div class="inner">
  72. <div class="read-next-feed">
  73. {{#if primary_tag}}
  74. {{#get "posts" filter="tags:{{primary_tag.slug}}+id:-{{id}}" limit="3" as |related_posts|}}
  75. {{#if related_posts}}
  76. <article class="read-next-card"
  77. {{#if ../primary_tag.feature_image}}
  78. style="background-image: url({{img_url ../primary_tag.feature_image size="m"}})"
  79. {{else}}
  80. {{#if @site.cover_image}}
  81. style="background-image: url({{img_url @site.cover_image size="m"}})"{{/if}}
  82. {{/if}}
  83. >
  84. <header class="read-next-card-header">
  85. <small class="read-next-card-header-sitetitle">&mdash; {{@site.title}} &mdash;</small>
  86. {{#../primary_tag}}
  87. <h3 class="read-next-card-header-title"><a href="{{url}}">{{name}}</a></h3>
  88. {{/../primary_tag}}
  89. </header>
  90. <div class="read-next-divider">{{> "icons/infinity"}}</div>
  91. <div class="read-next-card-content">
  92. <ul>
  93. {{#foreach related_posts}}
  94. <li><a href="{{url}}">{{title}}</a></li>
  95. {{/foreach}}
  96. </ul>
  97. </div>
  98. <footer class="read-next-card-footer">
  99. <a href="{{#../primary_tag}}{{url}}{{/../primary_tag}}">{{plural meta.pagination.total empty='No posts' singular='% post' plural='See all % posts'}} →</a>
  100. </footer>
  101. </article>
  102. {{/if}}
  103. {{/get}}
  104. {{/if}}
  105. {{!-- If there's a next post, display it using the same markup included from - partials/post-card.hbs --}}
  106. {{#next_post}}
  107. {{> "post-card"}}
  108. {{/next_post}}
  109. {{!-- If there's a previous post, display it using the same markup included from - partials/post-card.hbs --}}
  110. {{#prev_post}}
  111. {{> "post-card"}}
  112. {{/prev_post}}
  113. </div>
  114. </div>
  115. </aside>
  116. {{!-- Floating header which appears on-scroll, included from includes/floating-header.hbs --}}
  117. {{> floating-header}}
  118. {{/post}}
  119. {{!-- The #contentFor helper here will send everything inside it up to the matching #block helper found in default.hbs --}}
  120. {{#contentFor "scripts"}}
  121. <script>
  122. // NOTE: Scroll performance is poor in Safari
  123. // - this appears to be due to the events firing much more slowly in Safari.
  124. // Dropping the scroll event and using only a raf loop results in smoother
  125. // scrolling but continuous processing even when not scrolling
  126. $(document).ready(function () {
  127. // Start fitVids
  128. var $postContent = $(".post-full-content");
  129. $postContent.fitVids();
  130. // End fitVids
  131. var progressBar = document.querySelector('#reading-progress');
  132. var header = document.querySelector('.floating-header');
  133. var title = document.querySelector('.post-full-title');
  134. var lastScrollY = window.scrollY;
  135. var lastWindowHeight = window.innerHeight;
  136. var lastDocumentHeight = $(document).height();
  137. var ticking = false;
  138. function onScroll() {
  139. lastScrollY = window.scrollY;
  140. requestTick();
  141. }
  142. function onResize() {
  143. lastWindowHeight = window.innerHeight;
  144. lastDocumentHeight = $(document).height();
  145. requestTick();
  146. }
  147. function requestTick() {
  148. if (!ticking) {
  149. requestAnimationFrame(update);
  150. }
  151. ticking = true;
  152. }
  153. function update() {
  154. var trigger = title.getBoundingClientRect().top + window.scrollY;
  155. var triggerOffset = title.offsetHeight + 35;
  156. var progressMax = lastDocumentHeight - lastWindowHeight;
  157. // show/hide floating header
  158. if (lastScrollY >= trigger + triggerOffset) {
  159. header.classList.add('floating-active');
  160. } else {
  161. header.classList.remove('floating-active');
  162. }
  163. progressBar.setAttribute('max', progressMax);
  164. progressBar.setAttribute('value', lastScrollY);
  165. ticking = false;
  166. }
  167. window.addEventListener('scroll', onScroll, {passive: true});
  168. window.addEventListener('resize', onResize, false);
  169. update();
  170. });
  171. </script>
  172. {{/contentFor}}