Please note: This site is in an active redesign. Some things might be a little off 🧐

EH

code-examples

Owning my code blocks

A week ago, I wrote about how I added the ability to post code snippets to my site instead of GitHub Gists. This was the first part of a couple of things I wanted to improve about how my site handles the display of code.

Today, I ported my code that handles the highlighting and display of my code snippets to apply to code blocks within articles that I write on my site. What's the difference, you ask? Code Snippets are long segments of code that are either an entire code file or a large segment of a code file. Code Blocks are short pieces that are displayed inside of articles that are meant as tutorials or coding tips.

Regardless of if you are viewing a full code file or a short code block in a tutorial, you always want code to look the same. Syntax highlighting, monospaced and containing line numbers. I also tagged all the articles that had code blocks with a code-examples tag. This allows you to see a stream of all the articles that have code blocks.

I'm pretty excited to have rolled this out. The way it works is when I am writing a blog post in markdown, I can use the same syntax as GitHub supports (three backticks and the language name)

Here is an example:

  1. ```javascript
  2. Then you can write code examples in here and they will get syntax highlighting... wait, is this code-block-inception?
  3. ```

It's nice to be able to write a regular article and then quickly and easily add code examples using a familiar markdown syntax.

The other thing I'm thinking about is about CodePen style code collections, where you can have multiple code files and also display what they look like. In the IndieWeb, we've already determined a collection is just a post that contains child posts. So I could have a post with the title of the "CodePen" and a description, then within the code collection, include child posts that are all Code Snippets.

That would be the first step, the second step would then be recognizing code collections and not only displaying the source code but allowing the person viewing it to "view it live". I read up today about how websites like CodePen do it and it seems pretty simple, mostly just involving injecting the source code into an iframe. But that's another adventure for another day.

Using Certbot with Nginx

I use to be able to use a --nginx command with Certbot to add https to my domains on my server. That plugin doesn't work correctly anymore and I always forget the command. So this is really a reminder for myself:

  1. sudo certbot --authenticator standalone --installer nginx --pre-hook "service nginx stop" --post-hook "service nginx start"

If you are searching around for ways to get Certbot to work with your Nginx, I hope this helped you, because it sure is handy to remind me.

Thinking through hooks versus event callbacks

I have tried to keep my website's functionality pretty separate and clean, but there are definitely some areas I want to clean up.

First is my "routing" modules that create and respond to the individual url calls.

Second is my Micropub handling code. Currently, my Micropub code is just a big mess of changes and adaptions. I've prefer to have separate areas for the attribute processing, file saving, and webmention sending.

For both of these things I essential want a way to be able to write a new module and have it interact with my primary software by saying "Hey, I have a new route" or "Hey, I want to do something after a Micropub request is finished". From my experience there are two ways to do that.

First is what I'll call the "hook" method. That is where you add the module to a specific folder that the software looks for new add-ons. The module has a specific file name like module.js and inside it, it will have pre-specified function names like hook_after_micropub. Then the software will call that function in all the modules that have it. This method is used in Drupal 7 as well as is kind of how Apple's delegate methods work.

Second is what I'll call the "event" method. This is where a new module would import an event hub and you would register your functions to respond to different events. For example you might put

  1. event.register('after_micropub', sendWebmentions).

I can't decide which way I like better. What pros and cons have you found when working with systems like the two above? Or are you familiar with a third way I haven't mentioned?

Create a new mysql database and user

I have found myself installing a lot of open source projects lately that are based on the PHP-Mysql stack. For each project, I generally want to create a new mysql database and user. Every time I install a new project I end up googling around the internet looking for the instructions again, so this is more for me than you, but you are welcome to use these notes as well.

The instructions come from debuntu.org.

First I need to log into mysql's CLI:

  1. mysql -u root -p

Then, I need to create the database named 'db1':

  1. create database db1;

Next, we make a user called 'user1' with password 'pass1':

  1. grant usage on *.* to user1@localhost identified by 'pass1';

Finally, we grant privileges to our 'user1':

  1. grant all privileges on db1.* to user1@localhost;

Voila! Now, you have a new user with their own database in MySQL.

using git hooks for sanity

At my current job, we have two different build processes in grunt. The first is my development build which allows for easier debugging and the second is the production build that strips out code that isn't desired for the production servers. Unfortunately sometimes the development build runs just fine but the production build breaks. This leads to the potential mistake where I build something new using the development build but forget to check the production build before pushing my code into the shared git repo.

Nevertheless! I have a solution I've implemented and am documenting here for both myself and others.

I've added a pre-push git hook that runs a production build before pushing any branch to the server. What this means is I can continue to develop and commit as normal but when I try to push the code if it will break the production build it will break before the push allowing me to troubleshoot the issue, fix it and then do my push.

I've set this up in 2 ways, first I add a bash script called pre-push to (gitRepoDirectory)/.git/hooks. There is actually a big collection of potential hooks that you can choose from.

For me the script looks like this:

  1. !/bin/bash
  2. (npmProjectDirectory)/node_modules/grunt/bin/grunt --gruntfile (npmProjectDirectory)/Gruntfile.js build:prod

This works great using git on the command line. But seriously, who enjoys git cli? I use this great app called Git Tower. Unfortunately Git Tower can't find the node executable and thus it can't run my production build. This is an easy fix as detailed on their support page. After adding the environment.plist file from their support page, it works great!

No more accidentally breaking builds!

Installing Ruby/Jekyll on macOS

I got a new laptop and as with any new laptop it is a mixture of joy and frustration. The joy is that you get to start from scratch and get rid of all the cruft that has built up on your machine. The downfall is all the little things that you forget about how you set up your machine before.

One of those snags I ran into today was reinstalling Jekyll (and by relation, Ruby). It's tricky because macOS comes preinstalled with Ruby 2.0.0 which makes you think you are all set but there are a ton of complications with it so it's better to just install your own copy of Ruby on your machine.

One of the issues was that when I tried to install Jekyll with my system Ruby, it provided the following error:

  1. ERROR: While executing gem ... (Gem::FilePermissionError). You don't have write permissions for the /Library/Ruby/Gems/2.0.0 directory

It wasn't any easier when I tried to install it using sudo. Thus, I googled and after some frustration searching I found the solution.

I'm documenting it here on my website so that I (and hopefully others) can find it easy in the future.

First you need to install Xcode.

Then, Install the Xcode Command Line Tools

  1. xcode-select --install

Open Xcode or run the following code and agree to the terms

  1. sudo xcodebuild -license

Install Homebrew

  1. /usr/bin/ruby -e "$(curl -fsSL [https://raw.githubusercontent.com/Homebrew/install/master/install](https://raw.githubusercontent.com/Homebrew/install/master/install))"

Install Ruby

  1. brew install ruby

Install Jekyll

  1. sudo gem install jekyll

Verify Jekyll

  1. jekyll -v

VICTORY!

Learning Adapt, Part One: Introduction to the Adapt Framework

This is the first part of a series of tutorials on developing plugins for the Adapt Framework. In this part, we are going to take a look at a general overview of the Adapt Framework, how to set it up and how it all comes together.

Adapt is made up of two products: The Adapt Framework and the Adapt Authoring Tool. The Adapt Framework is a JSON-based, component framework for building responsive html courses. The Adapt Authoring Tool is a Node.js based tool for building Adapt Framework courses through a visual interface. For more information reference the Adapt Docs.

The Adapt Framework is made up of plugins that work together and fit into 4 different categories:

  • Components: These are small widgets that allow the user to engage with the material they are learning. Examples include: Text, Images, Multiple Choice Questions, etc.
  • Extensions: These add additional functionality outside of the core functionality that is provided through the Adapt Framework. This functionality are things like: Adding a course score, Assessments, Google Analytics, Using Local Browser Storage
  • Themes: This allows you to define a custom set of css or LESS styles. It also allows you to add custom assets, fonts, javascript and handlebar templates to define how your components feel and behave.
  • Menus: A menu plugin defines how a user can navigate through the course. These include: The traditional box menu, a single-page course with no menu, a carousel-style menu, even making different menus for different content sections.

Getting Started

Before you can develop plugins for use with the Adapt Framework or the Adapt Authoring Tool, you need to install the Adapt CLI. You'll need Node.js/NPM already installed.

  1. npm install adapt-cli -git

Once that Adapt CLI is installed, we can create our first course in our current directory:

  1. adapt create course "Test Course"

You'll need to confirm the type (course), the course name, and the git branch. Then your adapt course will be created.

After the course is finished creating, you can enter the directory:

  1. cd "Test Course"

To build the course, use:

  1. grunt build

To view the course, use:

  1. grunt server

Anytime you make changes to the course, you'll need to rebuild and re-run the server.

You'll see the default course theme with the box menu.

While we won't be creating any new plugins in this lesson, when you want to change the theme or the menu used for this course, you can do so with the following command:

  1. grunt build --theme=adapt-new-theme --menu=adapt-new-menu

The Anatomy of an Adapt Course

Within the adapt course source files Test Build/src/, the folders that we care about are:

  • components: Contains all adapt components for our course.
  • course: Contains all course configuration and content within JSON files.
  • extensions: Contains all adapt extensions for our course.
  • menu: Contains the adapt menu for our course.
  • theme: Contains the adapt theme for our course.

In future lessons, we'll deal with the components, extensions, menu, and theme folders in future lessons. For this lesson, we'll limit our focus to the course folder.

Config

Within the course folder, you'll find a config.json file for course-wide settings. While you won't need to edit many of the settings in here for developing plugins.

Languages

The folders inside of course folder are language-specific data for your course. For example, yours will probably contain a en folder for the english data and assets.

Course data

The course data file is a JSON file that allows you to define the title (the browser document title), the displayTitle (used in certain menus), as well as course-wide global content such as description, body, _buttons titles. There is also a _globals section for global strings that can be referenced from plugins such as a theme template file. In fact, all of the course.json is available as root level properties in the template file.

Content Objects

The content objects section is made up of page items and menu items. Menu itesm will take you to a sub-menu for further navigation. Page items will direct you to an article (which will be further defined in the next section).

Page Item

  1. {
  2. "_id":"co-05",
  3. "_parentId":"course",
  4. "_type":"page",
  5. "_classes":"",
  6. "title":"Demo page",
  7. "body":"This page should contain a working Adapt page will all core bundled components and plugins working.",
  8. "graphic": {
  9. "alt": "alt text",
  10. "src": "course/en/images/origami-menu-one.jpg"
  11. },
  12. "linkText":"View"
  13. }
  1. {
  2. "_id":"co-10",
  3. "_parentId":"course",
  4. "_type":"menu",
  5. "_classes":"",
  6. "title":"Demo menu",
  7. "body":"This menu item contains a sub-menu",
  8. "graphic": {
  9. "alt": "alt text",
  10. "src": "course/en/images/origami-menu-one.jpg"
  11. },
  12. "linkText":"Go to submenu"
  13. }

Content Object Attributes

  • _id The _id attribute of a content object will always start with the letters 'co' and a dash. It will be followed by a 2 digit number. The number should go from small to large based on the order that you want for the menu items.
  • _parentId is going to be course if you want it to be the root level of the menu or the _id of the menu content object that you want this object to be nested under.
  • _type will be either page or menu
  • title, body, graphic all are self documenting.
  • linkText contains the text for the link/button of the menu item.

Articles

An article is a grouping of related blocks. You are able to give the article a title and body text as well as add classes to the article to allow for changes in the theme depending on what article you are displaying.

You will define article items within the article.json file.

Article Item

  1. {
  2. "_id":"a-50",
  3. "_parentId":"co-25",
  4. "_type":"article",
  5. "_classes":"",
  6. "title":"Article first title",
  7. "body":"Body text for article"
  8. }

Article Attributes

  • _id The _id attribute of an article will always start with the letter 'a' and a dash. It will be followed by a 2 digit number. The number should go from small to large based on the order that you want for the article items.
  • _parentId The _parentId will be the _id of the Content Object that you wish do have the article displayed under.
  • _type will be article
  • _classes will be a string of css classes seperated by a space just like if you were adding them in a class="" html attribute
  • title, body will appear at the top of the article before any blocks are displayed.

Blocks

a note on layout and blocks: Blocks are at the center of Adapt Course Navigation. By default, blocks are arranged in what is called the Deep Scroll layout. This means that each block is arranged stacked below the last one creating a long scrollable page. You can also mark an article's blocks as having Block Slider functionality, which means for that article, the blocks will become carousel-like in that you see one block at a time, and that the other blocks are offscreen either to the right or to the left, ready to be scrolled onscreen at the right time. Finally, you can make the entire page into the Block Slider layout, where you can transition to the left or right and journey through a horizontal lesson rather than a vertical lesson.

You will define block items within the blocks.json file.

Block Item

  1. {
  2. "_id":"b-150",
  3. "_parentId":"a-50",
  4. "_type":"block",
  5. "_classes":"",
  6. "title":"Title of first block",
  7. "body":"Body text for block"
  8. }

Article Attributes

  • _id The _id attribute of an block will always start with the letter 'b' and a dash. It will be followed by a 3 digit number. The number should go from small to large based on the order that you want for the block items. Often times you can find a way to associate the block number with it's parent number.
  • _parentId The _parentId will be the _id of the Article that you wish do have the block displayed within.
  • _type will be block
  • _classes will be a string of css classes seperated by a space just like if you were adding them in a class="" html attribute
  • title, body will appear at the top of the block before any components are displayed.

Components

A component is an individualized piece of functionality. You can have 1-2 components in a block. If you have 1 component it be be full-size or half-size. If you have 2 components in the same block, they both must be half-size. If a component is half-size you define whether it is the left component or the right component. As per standard responsive design rules, when the block is displayed on a mobile device, it stacks the components on top of each other, the left component on the top of the right component.

Components are the baseline of Adapt. They can be as simple as a text section or as complex as a mini-quiz or a game (like we developed for Google, GG-04). You'll noice that a component is considered a plugin, but an article and a block are not. That is because to really change the behavior of an article or a block you need to use an extension or a theme.

Component Item

Here is a basic component JSON:

  1. {
  2. "_id":"c-200",
  3. "_parentId":"b-150",
  4. "_type":"component",
  5. "_component":"text",
  6. "_classes":"",
  7. "_layout":"left",
  8. "title":"Title of our very first component",
  9. "body":"Whoo - if we get this rendering we've made the big time"
  10. }

Component Attributes

  • _id The _id attribute of a component will always start with the letter 'c' and a dash. It will be followed by a 3 digit number. The number should go from small to large based on the order that you want for the component items. Often times you can find a way to associate the component number with it's parent number.
  • _parentId The _parentId will be the _id of the Block that you wish do have the block displayed within.
  • _type will be component
  • _component will be the type of component that this JSON represents.
  • _layout will either be left, right, or full.
  • _classes will be a string of css classes seperated by a space just like if you were adding them in a class="" html attribute
  • title, body will appear at the top of the component.

The Complexity of Component JSON

Okay, now forget everything you just learned about component JSON! Well not the whole thing, but it's definitely a bit trickier.

The component attributes above are actually the base attributes, however every custom component actually has it's own attributes added and defined, so depending on what component is listed in the _component attribute, you'll want to add or remove new attributes. Because of this, when developing a component plugin authors are supposed to include an example.json file. This file is for you to be able to look at it and understand what attributes you have to add for this component to work. To further explain this, I have included links to some different component's example.json files:

From Here On...

So now you have a basic understanding of how the Adapt Framework builds courses. This is needed so that you can create components, extensions, themes and menus that are good citizens within the adapt community. The next lesson will be on Building a Custom Component.