Blog post: Experimenting with GitHub Pages and JavaScript and Putting Everything to Use

Jonas Brømsø - Jan 29 '20 - - Dev Community

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/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

I created a Gemfile

$ cat Gemfile
# frozen_string_literal: true

source 'https://rubygems.org'

# gemspec
gem "github-pages", group: :jekyll_plugins
Enter fullscreen mode Exit fullscreen mode

I installed Jekyll and bundler

$ gem install jekyll bundler
Enter fullscreen mode Exit fullscreen mode

And now I can run the site locally.

$ bundle exec jekyll serve
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

I could select the <li> tags and sum them up. Do note the topmost line in the JavaScript file is:

var total_tils = 0;
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .