Portfolio: University Edition

GitHub Repo:

Twin-Ewan.github.io

Truly, a long time overdue. I've been wanting to try to update my site with my university and personal projects and even more importantly to be mobile friendly. I had failed a few times previously but I finally saw success with a small trial run with the minecraft stats datafixer site and with the good timing of this module it all provided the perfect excuse - and importantly the time - to finally act upon it.

function Load()
{
    CreateHeader();
    GenerateNavbar();
    CreateRepoText();
}

function GetLocation()
{
    let filepath = window.location.pathname;
    filepath = filepath.split("/");

    // Checks if its has a single / (I.e is home)
    if(filepath.length - 2) 
    {
        let folder = filepath[filepath.length - 2] // Removes everything but the last folder
        folder = folder.split("%");

        // Reconstrusts the UTF8 back into characters
        let recontrusted = folder[0];
        for(let i = 1; i < folder.length; i++)
        {
            let CharCode = parseInt(folder[1].substring(0, 2));
            recontrusted += String.fromCharCode(`0x${CharCode}`) + folder[i].substring(2, folder[i].length);
        }
        return recontrusted;
    } 
    else return "Home"; 
}


function CreateHeader()
{
    const Header = document.getElementsByTagName("head")[0];

    Header.innerHTML += '<link rel="icon" type="image/x-icon" href="/icon.ico"></link>';
    Header.innerHTML += '<link rel="stylesheet" type="text/css" href="/styles.css">';

    Header.innerHTML += '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
    Header.innerHTML += `<title> Portfolio - ${GetLocation()} </title>`;
}

class Section {
    constructor(header, entries) {
        this.header = header;
        this.entries = entries;
    }
}

class Entry {    
    // My beautiful son overloading, dead
    constructor(display, link) {
        if(!link)
        {
            this.display = display;
            this.link = display;
        }
        else
        {
            this.display = display;
            this.link = link;
        }
    }
}

function GenerateNavbar()
{
    const Sidebar = document.getElementById("sidebar");

    const GenLinks = [new Entry("Home", ""), new Entry("Highlights"), new Entry("About Me"), new Entry("Personal Projects", "Personal")];
    const General = new Section("General", GenLinks);

    const EduLinks = [new Entry("Year 4"), new Entry("Year 3"), new Entry("HND"), new Entry("HNC"), new Entry("Highschool")]
    const Education = new Section("Education", EduLinks);

    const sidebar = [General, Education];
    const Location = GetLocation();
    sidebar.forEach(section => {
        
        Sidebar.innerHTML += `<h5>${section.header}</h5>`;

        section.entries.forEach(entry => {
            if(entry.display == "Home") // Im evil so making a specific thing instead of being smart
            { 
                Sidebar.innerHTML += `<a href='/'>${entry.display}</a>`; 
            }
            else
            {
                Sidebar.innerHTML += `<a href='/${entry.link}/'>${entry.display}</a>`; 
            }

            if(Location == entry.link) Sidebar.lastElementChild.id = "current";
        });
    });
}

function CreateRepoText()
{
    const Link = document.querySelectorAll(".repo");

    Link.forEach(element => {
        element.innerHTML = "<p>GitHub Repo:</p>" + element.innerHTML;
    });
}
Load();

This time I wanted to make everything a lot more modular: do away with the copy and pasted sections and create a script - because no PHP as GitHub pages is static - to as automatically as possible setup the boilerplate things for me to leave the webpages to the bare minimum setup required to make them, and of course to avoid me forgetting to update every page when changing something.

Originally I did this by using a script that automatically generated everything for me: The sidebars were generated using two classes: Entry which had a display and a link field, though if there was no link was specified it would default to using the display as such and Sections which contained all the entries for that section and a header. I did had to carve out a specific exception for the main page as I couldn't think of another way of doing it.

I added a check to disable the link to the page that you're already on when initially creating it using GetLocation() function which gets the filepath, then grabs the last directory and reconstructs the unicode character code into its character - I.e %20 into [Space] - then all gets combined back together to then to be finally used to compare it to the link used to create that sidebar button.

I also made the favicon, style, viewport and the title automatically be added on load, for the title reusing the same GetLocation(). and as well made the "GitHub Repo: [Repo Link]" text at the top of each project automatically gets "GitHub Repo:" prepends to the links. All in the name to make things easier.

After showing off my good work to my dear friends I was quickly informed that it was not "good work" and was an abomination: Requiring javascript for basic UI elements for such important things as navigation is awful for indexing for spiders and search engines meaning they won't be able to access any sub pages and are left stranded on the main page, let alone the people who have javascript disabled. And secondly due to the javascript taking a moment to run it leaves those with javascript enabled temporarily without the content and flashbangs them for a split second with the default theming.

So after that, we talked for a while to try and work out what would work the best for me and we ended up landing on static site generator, specifically Astro, due to my friend hearing many good things about it and with OrnitheMC using it as well.

So instead of having everything created using that javascript I can instead pick and choose what components I want and import them wherever needed, and with the ability to pass variables for extra versatility to all get generated once built so that the user is none the wiser and I still get the benefit of not having to repeat boilerplate code.