[DevLog] Building Show Notes 2

Sounds like you may have just about earned your weekend! :wink:

Have a good one.

On Sunday I hope to return to the media server and try out the latest update.

1 Like

Thanks @Derek.

Re the media server, would you mind checking that after updating to the new version your existing setup works as before. It should but if not let me know what broke and I’ll try to streamline it.

1 Like

Thrilling to see this being added Brad! One tip (from experience): if you’re trying to implement some logic, you might be starting to get into problems fast. Also get a lot of questions (but what if I want this logic, or combined, or …).
In a few projects I have been using Liquid. It’s supported for .NET with Fluid.Core, but there are also LiquidJS. It’s high performant parsing of text combined with data you provide. Could be an option too if you are looking for a way to add logic. Just a suggestion. :slight_smile:

Thanks :slight_smile:

Not sure I follow? What sort of logic problems?

None of this is .NET - all Javascript

Not really sure how I’d use this in this project. Looks similar to a templating engine (moe-js)I once wrote.

Whitespace Directive (line wrapping control)

The !white-space directive let’s you control line wrapping:

Watch video

eg: white-space normal

vs: white-space pre-line (pre-line = “pre-formatted lines”)

3 Likes

Push/Pop Directives (save/restore styling state)

The !push and !pop directives let you save and restore the current display style:

Watch Video

eg:

1 Like

Message Directives

In the push/pop video above you might have noticed the little error boxes when you have unbalanced push/pop directives. I’ve also made a set of these message boxes available as utility directives for showing errors, warnings, etc…

1 Like

Loving all this functionality.

I’m curious. When you pop, do all the styles get cleared or does it just set properties to previous values? Looking at your example where the middle section has the bg colour set but the style being restored doesn’t set the bg colour.

That kind of embedding of the browser window into Cantabile is exactly what I was looking for - the controller bar is visible, the metronome bar is visible, but there is enhanced capability on the notes screen. One feature I use frequently is switching from seeing notes to seeing the setlist grid during performance via hot key, so perhaps add that to your “Later” list. Re getting separate notes to bandmembers, if media server remains a separate tool it is quite easy to do that and I already tried it with my band (I use one channel for videos, one for lyrics, one for messages).

It restores the styles to how they were when the !push was done.

At the point of the !push the background color wasn’t set. When the pop happens, the background is restored to unset.

Yep. This is still a way off, but definite possibility.

If just did a quick test with this - the set list grid definitely can appear “over” the web browser in the background so swapping between the two views works fine. The only problem right now that I’ll need to fix is the short cut keys get intercepted by the browser. ie: at the moment, pressing Ctrl+G shows the browser’s find box instead of switching to the set list but I’m sure (hopefully) there’s a way around this.

Yes, but at the moment, you’re limited to PDF files. The idea is this would deliver these formatted and state controlled notes to different viewers.

Brad

Quick update… nothing to show!

I’m currently investigating Markdown processor alternatives and considering writing one so I can properly integrate these show notes directives.

Phew! I just came dangerously close to writing a markdown parser. I’ll take that route if I need to, but this might work…

I really wanted to get this directives much more tightly integrated with the Markdown processor because it removes a lot of weird behaviour.

After looking at a number of existing Markdown engines I think I’m going to switch to commonmark.js. Although it’s not directly extensible, its code base is reasonable easy to follow so I’ve created a fork of the project and will modify it to do what I need.

What’s the difference?

  • In all the examples above, the directives were preprocessed and everything between them was treated as separate markdown documents. This produces some unexpected behaviour because the pre-processing has no concept of what’s going on in the surrounding markdown.
  • With this new approach, the processing of directives is tightly integrated with the rest of the markdown processing - it behaves much more predictably and provides a lot more context information for the directive processing.

The only downside: Commonmark doesn’t have all the formatting features of some other libraries. Most notably it doesn’t support tables, but I can live with that at least for now.

See below for some screen shots of my modified version showing some basic style directives working.

Note:

  • directives look the same as before but they also work much more sensibly in blockquotes (ie: they can be used after lines starting with !)
  • Styles get restored automatically after leaving nested blocks
  • directives are correctly ignored inside code blocks
  • The first screenshot shows the final result
  • The second screenshot shows the html
  • The third screenshot shows the Abstract Syntax Tree of the parsed document - note how the directives are fully integrated into the document tree.

Next job is to move all the existing directives from the old system to this new approach.

Screen Shots

1 Like

Well, I think this decides it. I was worried about getting !if / !else / !elseif / !endif directives working with this approach because unlike most of the other directives they’re a multi-line construct.

It took some experimentation, but I think I’ve got it working so that a construct like this:

!if state == "A"
!if view == "primary"
Primary
!endif
State A
!elseif state == "B"
State B
!else
State C
!endif

Produces an abstract syntax tree like this:

<document xmlns="http://commonmark.org/xml/1.0">
  <conditional>
    <conditional_branch expression="state == &quot;A&quot;">
      <conditional>
        <conditional_branch expression="view == &quot;primary&quot;">
          <paragraph>
            <text>Primary</text>
          </paragraph>
        </conditional_branch>
      </conditional>
      <paragraph>
        <text>State A</text>
      </paragraph>
    </conditional_branch>
    <conditional_branch expression="state == &quot;B&quot;">
      <paragraph>
        <text>State B</text>
      </paragraph>
    </conditional_branch>
    <conditional_branch expression="">
      <paragraph>
        <text>State C</text>
      </paragraph>
    </conditional_branch>
  </conditional>
</document>

That’s everything required for the HTML rendering side of things to produce the required scripting code to update these elements in realtime.

Nice! I’m feeling optimistic about this…

1 Like

If you’re not technically minded, you might be wondering what I’m going on about with all this, but I’m including it for those who are interested and because writing it down helps me clarify my own thinking about it (and might be handy to refer back to later)

There’s lots of moving parts here but much of this is much lower level that you’ll ever have to deal with - there is a bigger picture I’m thinking about and it should all come together eventually.

Also, at this experimentation/proof of concept stage it’s pretty typical for there to be false starts, rethinking and changes of direction.

Bear with me! :slight_smile:

7 Likes