This site’s code now contains game spoilers
This post demonstrates CSS that won’t render in an RSS feeds or older browsers.
I have made one1 post about Baba Is You and so obviously I banged up a quick and dirty lexer for my website’s syntax highlighter and
If you are unfamiliar, Baba Is You is a block-pushing puzzle game where the rules that dictate interactions between blocks exist as text within the levels themselves that be rearranged to change them. Watching the trailer for the game will get this across better than I am able to explain it. I have not finished it but it’s a great little game and I would encourage anyone to check it out and discover all the incredible little things it does with this concept and I am looking forward to seeing what lies in store for me.
And I decided, because I could (because
The end result is that I can type something like this in the Markdown that posts are written in:3
```baba
rose is red
violet is blue
flag is win
baba is you
```
And it will render thusly:
rose is red
violet is blue
flag is win
baba is you
And you should be able to hightlight the text above and then copy and paste it somewhere else and have it remain legible.
I build this site using Jekyll, which uses Rouge for code parsing and syntax highlighting. All I needed to do was add a new lexer:
Jekyll::Hooks.register :site, :pre_render do |site|
require "rouge"
module Rouge
class Token
module Tokens
token :Noun, "noun" do
token :Rose, "noun rose fourletter"
token :Violet, "noun violet longword"
token :Flag, "noun flag fourletter"
token :Baba, "noun baba fourletter"
end
token :Oper, "oper" do
token :Is, "oper is"
end
token :Prop, "prop" do
token :Red, "prop red"
token :Blue, "prop blue fourletter"
token :Win, "prop win"
token :You, "prop you"
end
end
end
module Lexers
class Lua < RegexLexer
title "Baba"
desc "Baba Is You (https://www.hempuli.com/baba/)"
tag 'baba'
state :root do
[Noun, Oper, Prop].each do |group|
group.constants.each do |word|
rule Regexp.new(word.id2name.downcase), group.const_get(word)
end
end
rule %r/\s+/, Text::Whitespace
end
end
end
end
end
This parses over the text looking for matching tokens and then assigns them a set of classes (noun, rose, fourletter, etc.) that will be used by some even more hacky
figure:has(> pre > code.language-baba) {
display: inline-block;
margin: 0;
vertical-align: middle;
}
pre:has(> code.language-baba), div.language-baba.highlighter-rouge pre {
display: inline-block;
margin: 0;
background-color: #080808;
border-radius: 6px;
padding: 6px;
border: 0;
}
code.language-baba, div.language-baba code {
background-color: #080808;
border-radius: 6px;
hyphens: none;
display: inline-block;
text-transform: uppercase;
.w { font-size: 0; }
.noun, .oper, .prop {
font-weight: bold;
white-space: initial;
height: 24px;
width: 24px;
align-content: center;
font-size: 9px;
text-align: center;
line-height: 0.9;
font-family: "Comic Sans MS", "Comic Sans", "Comic Mono", "Chalkboard SE", "Comic Neue", sans-serif;
background-size: cover;
image-rendering: pixelated;
display: inline-block;
overflow-y: hidden;
}
.noun { color: #D9396A; }
.noun.rose {
background-image: url(/styles/baba/text/rose.webp);
color: transparent;
}
.noun.violet {
background-image: url(/styles/baba/text/violet.webp);
color: transparent;
}
.noun.flag {
background-image: url(/styles/baba/text/flag.webp);
color: transparent;
}
.noun.baba {
background-image: url(/styles/baba/text/baba.webp);
color: transparent;
}
.oper { color: white; }
.oper.is {
background-image: url(/styles/baba/text/is.webp);
color: transparent;
font-size: 15px;
}
.prop { background-color: #D9396A; color: #080808; border-radius: 6px; }
.prop.red {
background-image: url(/styles/baba/text/red.webp);
background-color: transparent;
color: transparent;
border-radius: 0;
}
.prop.blue {
background-image: url(/styles/baba/text/blue.webp);
background-color: transparent;
color: transparent;
border-radius: 0;
}
.prop.win {
background-image: url(/styles/baba/text/win.webp);
background-color: transparent;
color: transparent;
border-radius: 0;
}
.prop.you {
background-image: url(/styles/baba/text/you.webp);
background-color: transparent;
color: transparent;
border-radius: 0;
}
.fourletter { font-size: 13px !important; }
.longword { font-size: 10px !important; }
}
I am applying some styling to the underlying text to try and make it line up with the images (which you can see when highlighting it), though some of this like setting the text and background colour is then hidden by the more specific element styling that sets images for each token. It’s a bit pointless but it pleases me that, even if it’s invisible, there is styling there to make everything look more like the game elements aside from the images pulled from the game.
I’ve cut the example here down to only the words used in the poem, but the version in my actual code doesn’t have the full lexicon of the game either, just a few more words that I wanted to use on the site. A large part of the experience of playing Baba Is You is slowly discovering all the ways it plays with its rules. Loading up a level and seeing a new word and chewing on it, thinking through all the implications it could have, is a wonderful experience that evokes a strange mix of whimsy and dread as one realises the possibility space that has just been opened up. As such I have not looked up a word list to fill out my lexer more fully (and it would probably be tediously long anyway) and there is one word in particular defined in the
