About a decade ago now, I was writing a group chat system of the Slack/Discord variety, and I was pondering how I'd like to support markup. I wanted to do something more powerful than just the regular "bold/emphasis/strikeout/links/etc." set, as the users of this group-chat were the type who would enjoy adding animations and other "effects" to their text, especially on top of their custom emoticons/stickers. (Don't fret, this wasn't team-productivity software ;)
What I ended up doing was extending the backend with support for parsing messages using a "command language"—essentially Tcl. The "everything is a string" feature of Tcl-like languages was essential, because I wanted these "commands" to be arbitrarily composable, and both the input and output were required to be strings (i.e. HTML), so commands couldn't pass data-structures to one-another; they had to accept strings, and emit strings.
The user was not allowed to enter arbitrary HTML in their message (this was filtered out as a pre-filtering step), but any Tcl command was allowed to take HTML-strings as input and emit HTML-strings as output, and the string that was eventually generated, HTML and all, was treated as the user's actual message. Many of the implemented commands would parse the input HTML-string into an AST, tweak it somehow, and then re-emit it as a string.
An example of such a command would be something like:
And then [spoiler the protagonist died [rotate 5 [big :ohno:]]]
...where 'rotate' and 'big' layer together CSS effects (combining CSS classes with a bit of custom element style to parameterize it, with each rewriting the HTML AST structure of the previous to ensure the CSS effects "stack" correctly); and 'spoiler' is just a CSS class with pseudo-selector behaviors.
Another example would be:
[type oh nooo[sfx fall]oooooooo]
...which would use a CSS class+JS trigger to display the message one character at a time the first time it became viewport-visible... and embed a hidden <audio> element at the top of the message body, that would get triggered as the typing progressed to it. Sort of like the dialogue event-scripting in a video game.
And, of course, just like an IRC bot, you could rely on the backend being Turing complete, in ways like:
# generate random numbers
[roll 1d6]
# set a countdown timer on a user,
# resetting it whenever the user talks
[deadmanswitch 5mins I'm slacking off again!]
# get the backend to (use a job queue to)
# fetch a resource, plop it into its own download folder,
# and then post a link to the retrieved copy
[dl http://example.com]
# same, but also create a BitTorrent torrent for
# the file, register it with a BT tracker on
# the backend, and then emit the URL of the torrent file
[torrent [dl http://example.com]]
---
At this point, I don't really think there's much room for a new group chat system; but this one feature was really cool to me, and I always wish I had seen it implemented in some bigger product.
What I ended up doing was extending the backend with support for parsing messages using a "command language"—essentially Tcl. The "everything is a string" feature of Tcl-like languages was essential, because I wanted these "commands" to be arbitrarily composable, and both the input and output were required to be strings (i.e. HTML), so commands couldn't pass data-structures to one-another; they had to accept strings, and emit strings.
The user was not allowed to enter arbitrary HTML in their message (this was filtered out as a pre-filtering step), but any Tcl command was allowed to take HTML-strings as input and emit HTML-strings as output, and the string that was eventually generated, HTML and all, was treated as the user's actual message. Many of the implemented commands would parse the input HTML-string into an AST, tweak it somehow, and then re-emit it as a string.
An example of such a command would be something like:
...where 'rotate' and 'big' layer together CSS effects (combining CSS classes with a bit of custom element style to parameterize it, with each rewriting the HTML AST structure of the previous to ensure the CSS effects "stack" correctly); and 'spoiler' is just a CSS class with pseudo-selector behaviors.Another example would be:
...which would use a CSS class+JS trigger to display the message one character at a time the first time it became viewport-visible... and embed a hidden <audio> element at the top of the message body, that would get triggered as the typing progressed to it. Sort of like the dialogue event-scripting in a video game.And, of course, just like an IRC bot, you could rely on the backend being Turing complete, in ways like:
---At this point, I don't really think there's much room for a new group chat system; but this one feature was really cool to me, and I always wish I had seen it implemented in some bigger product.