Conditional Directives (Part 1)
Conditional directives are are probably going to be one of the trickier parts of this new show notes format.
These are required to emulate the state control that Cantabile has that allows notes to change when switching states:
In the new show notes this functionality will be done with conditional directives: !if
, !else
, !elseif
and !endif
.
For example:
!if state == "Intro"
Text to display when state is "Intro"
!else if state == "Outro"
Text to display when state is "Outro"
!else
Text to display for all other states.
!endif
Warning: tech geekery incoming…
The tricky part is that I don’t want the entire document to be reprocessed and recreated from scratch when a state changes. Instead, it needs to update the existing content hiding and showing parts as required.
eg: the above would probably end up something like this with JavaScript to toggle the display:none
style on each branch depending on the conditions.
<div><p>Text to display when state is "Intro"</p></div>
<div style="display:none"><p>Text to display when state is "Outro"</p></div>
<div style="display:none"><p>Text to display for all other states.</p></div>
But, it gets trickier because conditional blocks might be used just for styling:
!if state == "Intro"
!color red
!else
!color blue
!endif
Some Text
which would result in one paragraph “Some Text” and Javascript to update the color style to either red
or blue
. ie: this
<div style="color:red"><p>Some Text</p></div>
or this:
<div style="color:blue"><p>Some Text</p></div>
Then there’s nested conditional directives and mixes of style + text changes etc…
Building an Abstract Syntax Tree (kindof)
Anyway, I figured the first step in all this is converting the flat list of if/else/endif/endif directives into a tree of conditional blocks. This will be used both to insert the appropriate divs around conditional sections and also to generate the Javascript to update it on the fly.
The first pass over the input text (the bit I wrote this morning) splits the file into sections of markdown text interleaved with directives giving a flat array of things like this:
apples
!if condition
pears
!elseif otherCondition
watermelon
!if nestedCondition
strawberries
!else
blueberries
!endif
!else
bananas
!endif
The second pass converts the conditional directives into a hierarchy:
[
"apples",
{
"if": "condition",
"trueBlock": [
"pears"
],
"falseBlock": [
{
"if": "otherCondition",
"trueBlock": [
"watermelon",
{
"if": "nestedCondition",
"trueBlock": [
"strawberries"
],
"falseBlock": [
"blueberries"
]
}
],
"falseBlock": [
"bananas"
]
}
]
}
]
Notice how the !elseif
directive gets converted to a nested !if
block reducing everything to simpler if/else conditions.
The next step will be to do some control flow analysis over this tree to work out which sections might be shown/hidden and which styles can change and which are fixed.