1window.Blog = { 2 init() { 3 this.initLightbox(); 4 this.initSyntaxHighlighter(); 5 this.addAnchorLinks(); 6 this.renderGithubCards(); 7 8 document.querySelectorAll('p.image video').forEach(v => { 9 v.addEventListener('click', () => { v.paused ? v.play() : v.pause() }); 10 }); 11 }, 12 13 addAnchorLinks() { 14 document.querySelectorAll('body.show article > .body :is(h1, h2, h3, h4, h5, h6)').forEach(heading => { 15 let anchor = heading.previousElementSibling; 16 17 if (anchor && anchor.tagName == 'P' && anchor.id) { 18 let link = document.createElement('a'); 19 link.className = 'anchor-link'; 20 link.href = `#${encodeURIComponent(anchor.id)}`; 21 link.innerText = '#'; 22 heading.prepend(link); 23 } 24 }); 25 }, 26 27 initLightbox() { 28 // TODO: check alt/title on lightbox images 29 30 document.querySelectorAll('#page_body a:has(img)').forEach(a => { 31 let img = a.querySelector('img'); 32 a.setAttribute('data-pswp-src', img.src); 33 34 if (img.complete) { 35 a.setAttribute('data-pswp-width', img.naturalWidth); 36 a.setAttribute('data-pswp-height', img.naturalHeight); 37 } else { 38 img.addEventListener('load', () => { 39 a.setAttribute('data-pswp-width', img.naturalWidth); 40 a.setAttribute('data-pswp-height', img.naturalHeight); 41 }); 42 } 43 }); 44 45 let lightbox = new PhotoSwipeLightbox({ 46 gallery: '#page_body', 47 children: 'a:has(img):not(.nolightbox):not(.github-card)', 48 pswpModule: () => import('/javascripts/photoswipe/photoswipe.esm.min.js'), 49 showAnimationDuration: 200, 50 hideAnimationDuration: 200 51 }); 52 53 lightbox.init(); 54 }, 55 56 initSyntaxHighlighter() { 57 SyntaxHighlighter.defaults['gutter'] = false; 58 SyntaxHighlighter.defaults['toolbar'] = false; 59 SyntaxHighlighter.defaults['smart-tabs'] = false; 60 SyntaxHighlighter.defaults['class-name'] = 'highlighter'; 61 62 SyntaxHighlighter.autoloader( 63 ['js', '/javascripts/highlighter/shBrushJScript.js'], 64 ['ts', '/javascripts/highlighter/shBrushTypeScript.js'], 65 ['css', '/javascripts/highlighter/shBrushCss.js'], 66 ['ruby', '/javascripts/highlighter/shBrushRuby.js'], 67 ['objc', '/javascripts/highlighter/shBrushObjC.js'], 68 ['bash', '/javascripts/highlighter/shBrushBash.js'], 69 ['html', '/javascripts/highlighter/shBrushXml.js'], 70 ['swift', '/javascripts/highlighter/shBrushSwift.js'] 71 ); 72 73 SyntaxHighlighter.all(); 74 }, 75 76 renderGithubCards() { 77 document.querySelectorAll('.github-card').forEach(a => { 78 let url = a.href.replace('github.com/', 'api.github.com/repos/'); 79 fetch(url) 80 .then(response => { 81 if (response.ok) { 82 return response.json(); 83 } else { 84 throw new Error('Something went wrong'); 85 } 86 }) 87 .then(json => { 88 a.querySelector('p.description').innerText = json.description; 89 90 let stats = document.createElement('p'); 91 stats.className = 'stats'; 92 stats.innerHTML = ( 93 '<img src="/images/github-star.png" class="star"> <span>' + json.stargazers_count + '</span> ' + 94 '<img src="/images/github-watch.png" class="watch"> <span>' + json.subscribers_count + '</span> ' + 95 '<img src="/images/github-fork.png" class="fork"> <span>' + json.forks_count + '</span> ' + 96 '<span class="lang-dot ' + json.language.toLowerCase() + '"></span> ' + 97 '<span class="language">' + json.language + '</span>' 98 ); 99 a.append(stats); 100 }) 101 .catch(err => { 102 console.log(err); 103 }); 104 }); 105 } 106};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.