A long time ago I blogged about GitHub Pages and getting started with setting up a webpage.
The static webpages are nice and they can help you make your project or documentation look good, but for a long time I wanted to take this a bit further.
First I wrote two prototypes:
- One extending a GitHub Pages set up with JavaScript serving data from a local resource
- Another one serving data from a remote resource
Both worked fine, but I wanted to extend this beyond the prototype stage. And I would LOVE to go crazy in a cool looking, super interactive solution, but I have to be honest:
- I am not an experienced frontend developer
- I am no web designer
- And am by no means there yet, with my web and JavaScript skills
I feel over this nice article on Mozilla Developer Network (MDN) and I got an idea, something I could, something pretty basic I could do with my collection of "Today I Learned" notes. I could add some JavaScript to make it more interesting.
But there was and still is a lot of hurdles to get over to get to something working, so lets start at the beginning. GitHub Pages use Jekyll which is a static site generator written in Ruby. You can add themes to make it stand out and you can customize the layout using CSS (Sass) and by changing the HTML templates.
When wanting to play around with these themes what I have normally done was to clone the specific theme, like:
There a plenty of other themes to choose from and with customization, you are not stuck with the standard layout, which is a HUGE help if you like me, is not a web designer.
In the past I have made use of GitHub Pages and Jekyll for many of my projects and repositories, but mostly I have been in a situation where I had to commit, push and wait for me to see the changes applied - and this is not particularly gratifying. It can work for layout, but for coding, I must admit I would prefer something more coding environment like.
So when I started playing around extending the project with JavaScript, I would have to solve the problem on how to get feedback faster from my changes. I have previously used different hacks where I would render the relevant HTML and CSS in a browser based on files, but the changes where small and pretty basic. This did require some more and adoption of some new tools.
First, I need Jekyll running locally on MacOS and I wanted to get in a situation where I could simply do (lifted from: "Jekyll: Quickstart"):
$ bundle exec jekyll serve
$ open http://localhost:4000/
And then all the editing so I could see the result of my work and get feedback, prior to commiting and pushing...
Luckily I was able to locate good resources from the GitHub help pages, guiding me to get this working:
So this was basically the steps I took.
I am using rbenv
, so I have a local Ruby installation for the project.
$ rbenv local 2.6.3
I created a Gemfile
$ cat Gemfile
# frozen_string_literal: true
source 'https://rubygems.org'
# gemspec
gem "github-pages", group: :jekyll_plugins
I installed Jekyll and bundler
$ gem install jekyll bundler
And now I can run the site locally.
$ bundle exec jekyll serve
Pointing my favorite browser to: http://localhost:4000/
Next up was getting my head around the actual problem.
When we have is a HTML rendered from a Markdown file. We can control the CSS and do some extent the HTML. But as you can see from the HTML skeleton.
<div id="content-wrapper">
<div class="inner clearfix">
<section id="main-content">
{{ content }}
</section>
Our main content is simply wrapped, so we are not able to control the translation from Markdown and the handling of the HTML layout for this part. We can apply CSS and make it look different, but we cannot control the data originating from the Markdown.
I searched for different approaches and with different words trying to find out how I could wrap a section indicating start and end of a part of the data and the closest I got was a jQuery solution, .wrapInner()
.
Unable to find a construct with exactly the capabilities I needed I ended up using a combination of document.querySelectorAll()
and element.querySelectorAll()
.
Luckily I was able to identify all of the necessary elements relying on the <h3>
tag.
document.querySelectorAll('h3').forEach(element => {
count_tils(element);
});
Feeding the selected elements to my counter function:
function count_tils(element) {
var sibling;
if (sibling = element.nextElementSibling) {
var list = sibling.querySelectorAll('li');
if (list.length > 0) {
var descriptor = 'tils';
if (list.length == 1) {
descriptor = 'til';
}
var text_content = element.textContent + ' (' + list.length + ' ' + descriptor + ')';
element.textContent = text_content;
total_tils += list.length;
}
}
}
I could select the <li>
tags and sum them up. Do note the topmost line in the JavaScript file is:
var total_tils = 0;
As you can see the elements are added to the existing header (<h3>
), by concatenating the count and a helpful string.
Now that I have the count I decided to do some more and I added it to the sidebar, which was carrying some text about the content on the page. This is together with a count of the categories,
The element for the sidebar was created using createElement
and added using appendChild
, which I found out how to do from a StackOverflow post.
var category_count = 0;
const count = document.createElement('p');
count.textContent = 'A collection of ' + total_tils + ' tils in total, split on ' + category_count + ' categories';
var sidebar = document.getElementById('sidebar');
sidebar.appendChild(count);
The implementation can be seen at: http://jonasbn.github.io/til/ and the JavaScript file, from where all of the above snippets come is available here.
It is quite a learning curve getting your head around all of the APIs, but as soon as you discover something and are able to add it to you tool box you can move on to new problems. The toughest issue is actually the nagging feeling whether you are using the right API or something more right is out there. The Mozilla Developer Network (MDN) is awesome as a resource, check it ouf if you are not familiar with it.
This concludes this post. If ANYBODY has any tips on how to approach this using web APIs I am very open to getting some more insights. Suggestions on how to improve the implementation made for my TIL collection are also MOST welcome, I always enjoy a good challenge and appreciate a pull request.
Top comments (3)
I can see some people are bookmarking this post, which makes me very happy. Well it might just to put it in the reading list, which is perfectly okay, I do that myself.
Anyway if you bookmarked it because you wanted to hack on my suggestions, please let me know what you are hacking on and how you are extending the capabilities of your GitHub Pages.
And if you are running into issues or have questions please reach out. I am no expert, but I am up for a challenge and the learning experience is always worth the effort invested.
Looks very nice could grow to smt like github
awesome list
Thanks for the nice comment
That would be... awesome - pun intended :-)
As I write in my TIL collection, my inspiration came from Josh Branchaud's collection - I have no idea on when and where this started, but I really like the format, since it is time consuming writing everything up as blog posts. I do sometimes promote certain TILs as blog post to fill on my blogging schedule.
I like Scott Hanselmans description of how you run into an issue, google it and your own notes pop up as a result.