Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: grunt

  • Grunt Can’t Build Sass on High Sierra

    Grunt Can’t Build Sass on High Sierra

    Working on a site, I went to run my grunt command to compile sass, I got an error.

    Running "sass:dist" (sass) task
    /usr/local/Cellar/ruby/2.4.2_1/lib/ruby/2.4.0/rubygems.rb:271:in `find_spec_for_exe': can't find gem sass (>= 0.a) (Gem::GemNotFoundException)
        from /usr/local/Cellar/ruby/2.4.2_1/lib/ruby/2.4.0/rubygems.rb:299:in `activate_bin_path'
        from /usr/local/bin/sass:22:in `<main>'
    Warning: Exited with error code 1 Use --force to continue.

    No good, right? And googling around for that didn't help me at all until I drilled down and realized the sass error was a Ruby error.

    Upgrade Ruby

    First, install Homebrew. I know there are many other ways to handle installs on Macs, but Homebrew has been my go-to for a few years. It makes my life easier.

    Once Homebrew is installed run the following command: brew install rbenv ruby-build

    If this gives you an error, like missing xcrun, then run this: xcode-select --install

    Once you have rbenv installed, it's time to upgrade ruby:

    rbenv install 2.4.2
    rbenv global 2.4.2

    Awesome! But grunt still doesn't work. And this is because Sass isn't installed.

    Install Sass

    This should be easy, right? sudo gem install -n /usr/local/bin sass and off you go. The problem is you may get this error:

    ERROR:  While executing gem ... (TypeError)
        no implicit conversion of nil into String

    Not so helpful. The magic here is going backwards to go forward. Update your gems first: sudo gem update --system and then run the installer for sass.

    Why Did This Happen?

    The short answer is that Mac changed versions and everything got out of sync. I'm not a system code expert so I can't explain it better than that.

    How you fix these things is by understanding how to logically step backwards through the errors. Most of the time, we see it as "Grunt says Sass is broken!" and the trick here is to ask yourself "What runs Sass?" and the answer is "Ruby." So instead of looking up "Why can't I run sass on grunt?" we look up "Ruby can't compile SCSS on Mac High Sierra" because that's the ultimate answer.

    Walking backwards is the secret sauce for all solutions with software, I feel. Why can't Grunt run Sass? Because Ruby can't compile? Why can't Ruby compile SCSS? Let's reinstall Sass! Oh wait, that has an error. Okay, let's upgrade Ruby. Oh that has an error too? Let's solve that.

    It's not fun, unless you're me and think snarling at a laptop in the conference room of your friends' office is cheerful.

  • JSON to Markdown

    JSON to Markdown

    Now that I understand how Hugo and JSON work separately and together, it’s time to figure out the next question.

    Can I generate Markdown files based on the contents of a JSON?

    My JSON File

    I started with an SQL DB where my photos have lived for a long time. I exported the albums table to a JSON file (yes, phpMyAdmin can do that), cleaned it up by removing the cruft I didn’t need, and ended up with something like this:

    [
     {
        "categories": "Adventures",
        "tags": "Index",
        "folder": "foobar",
        "title": "Foobar and Baz",
        "desc": "The adventures of Foobar and Baz.",
        "date": "2006-03-24 19:46:40"
      },
      {
        "categories": "Vacations",
        "tags": "Index",
        "folder": "botbob",
        "title": "Bot and Bob",
        "desc": "Bot and Bob's vacation photos",
        "date": "2006-03-24 11:51:04"
      }
    ]
    

    By the way, I’m not going to address how to actually make the gallery with images here. Yet. The eventual idea I have here is to run this with WordPress doing that, but since I was messing around with this anyway, I figured I’d reuse what I had.

    The end goal here, remember, is to export the JSON file from WordPress (list all top level categories, let’s say) and have Hugo generate a page for each one. That’s all. But WordPress has so much data, I decided to start with the smaller, simpler stuff.

    Let’s move on.

    Create a Markdown Page from JSON

    Thankfully someone else has already tossed this idea around. I started with reading Dynamic Pages with Hugo

    My idea is: Import any JSON or CSV from any local file or URL and make the JSON or CSV content available in a shortcode or directly in the layout files.

    That was very close to what I wanted, but it would result in me having to make a page for each item. I don’t want that. I want a script to make the .md file for me.

    So I stepped back and stopped asking “How do I make a Hugo page from JSON?” and I asked “How do I make a separate file for each entry in a .json file?”

    Sidebar: My wife was trying to convert the Hebrew year (3595) into all the possible other calendars and asked me to help her with the math. I asked her “What Julian year is that?” She said it BCE so it didn’t work like that, but that was 167. I Googled “What is 167 BCE in the Chinese calendar?” Boom. WikiPedia’s page for 167 BC lists them all. As I pointed out, the trick to these things is not converting it all yourself, but getting from ‘weird’ to ‘Base 10.’ Once you’re at the default (the lowest common denominator), it’s allot easier to figure out other people’s weird.

    This is related to my task at hand. Weird is being specific. Weird is caring what system I’m using. The root of my issue is this: I want to make a Markdown file for every entry in JSON.

    I use Mustache. And, yes, someone already had this idea. He was using mustache-render in Grunt, which I’m already familiar with, but I made a few changes.

    1. I changed the templates folder to my Hugo Archetypes folder. This is my source, my style.
    2. I changed the data folder to my Hugo Data folder.
    3. The output went to (you got this one, right?) the Hugo Content folder.

    This should work, right?

    Mustache Render

    My Gruntfile has this:

        mustache_render: {
          all: {
            options: {
              directory: "partials"
            },
            files: [
              {
                data: "../data/parents.json",
                template: "../archetypes/gallery.mustache",
                dest: "../content/gallery.md"
              }
            ]
          }
    

    And my gallery.md file is like this:

    ---
    title: {{title}}
    author: Me
    layout: default
    permalink: /{{folder}}/
    categories: {{categories}}
    tags: {{tags}}
    ---
    
    {{title}}
    

    Except that doesn’t work. If I changed {{title}} to {{0.title}} then it showed Foo and Bar’s adventure information. Obviously the render was only going to show each entry individually. Now. This could work in a variety of situations, just not mine. Alternatively, I can wrap the output in this: {{#0}} ... {{/0}}

    But what I want is ‘for each key in json, make a file…’ and since I can put the JSON output right into the gruntfile (data: { greeting: "Hello", target: "world" }) then in theory I want to generate this:

    files: [
      {data: OUTPUT FROM KEY ,
       dest: KEY ID,
    ]
    

    Okay so how do I tell Grunt to read from a JSON and for each key, do a thing? First I use grunt.file.readJSON:

    pkg: grunt.file.readJSON('../data/parents.json'),
    
        mustache_render: {
            [...]
                files: [{
                    template: '../archetypes/gallery.mustache',
                    data: '<%= pkg.1 %>',
                    dest: '../content/<%= pkg.1.id %>-foo.md'
                }]
          }
        }
    

    And this will output item (Bob’s vacations). So stage one is complete. Now I want the 1 in pkg.1 to be iterative or I want to pass a variable to the mustache file and change {{#0}} ... {{/0}} based on its value. Obviously if I had one JSON file for each ‘post’ I wanted to make, this would be easy.

    Multiple Markdown Files from One JSON

    I have no idea.

    Seriously. I spent a few hours on this, lying in bed trying to feel less cold-and-flu-ish. At this point, I don’t really care what I use to do it, but the bones is this: Take one JSON file and split each object into it’s own file.

    Can’t figure that out yet. But hey, there’s my 2016 project!

    FYI: If you reply with ‘try project X!’ without a code example of how to do it, I’ll probably delete your comment. I’ve seen ‘Try handlebars!’ or ‘Try Assemble’ but my issue here is no one has an example of how to do it, and I work best by example. I need that Hello World.

    I am looking at Handlebars and Assemble, by the way, but at 900+ words, it’s time to call a pause on the adventure.