[meta] { [title] Sona, a markup language [subtitle] Yes, another one. [author] Vince Mutolo [date] // TODO } [section] { [title] Feature survey Sona has very few features. The goal is to do as much as possible with as little syntax as we can. In many places we succeed, and in others we'll punt the problem to another layer. [section] { [title] Consistent syntax [example] { [label] syntax-parts The below example demonstrates Sona's two types of syntax: labels and text. [code] { [lang] sona \raw#{ [title] Birds aren't real, a treatise }# } } Everything in Sona is one of two objects: [definitions] { [item] { [term] label [def] { provides metadata about a subsequent block. In [ref]{syntax-parts}, the text [code]{title} is a [em]{label}. It specifies that the contents of its [em]{scope} are labeled as a title. It's up to some other layer to figure out what to do with that information. } } [item] { [term] text [def] { provides the actual content of a Sona document. If labels are metadata, text is the data itself. In [ref]{syntax-parts}, the text [code]{Birds aren't real, a treatise} is a text object. Text doesn't always have to show up in a rendered document. Sona doesn't have to produce rendered documents at all. It can, for example, be used for config files. In that case, a text object is likely to be interpreted as the value corresponding to a certain key (which is likely a label). } } } } [section] { [title] Simple data model and output Because Sona has so few data types, the abstract syntax tree can be compactly represented in JSON. Labels become keys in objects, and the values are (mixed) arrays of either text blocks or other label objects. [example] { This Sona document: \sona#{ [A] { T minus [SI]{123 [u]{ms}}. [B] b } [C] c }# is converted to the following JSON: \json#{ [ {"A": [ "T minus ", {"SI": ["123 ", {"u": ["ms"]}]}, {}, {"B": ["b"]} ]}, {}, {"C": "c"} ] }# } } [section] { [title] Macros Sona allows users to define macros that take in arbitrary text and emit a valid Sona document. For example, if we know that we'll be writing out lots of JSON code, we may want to define a macro to save space. A hypothetical JSON macro would be used as follows: \sona##{ \json#{ {"a": "b"} }# }## and would expand to a syntax tree equivalent to the following Sona document: \sona##{ [code] { [lang] json \raw#{ {"a": "b"} }# } }## } } [section] { [title] Why not one of the existing formats [ordered] { [item] Markdown isn't powerful enough. I want to be able to have callouts and "warnings" and "notes" all throughout an article. With Markdown, these blocks need to be written in raw HTML, which is annoying because Markdown is disabled in those blocks. And writing HTML is generally annoying. [item] HTML is annoying. See above. [item] LaTeX is a mish-mosh of ideas organically thrown together over decades. I love LaTeX, and TeX's output is second to none, but it's not the format I want for content authorship. } } [section] { [title] Use cases [section] { [title] Configuration files Imagine we need to create a configuration file for some video game. The game needs to know how many tries the player gets, the score needed to win, and some starting position. In TOML, that config looks like: \toml#{ [config] max_tries = 30 max_score = 100.0 [config.waypoint] x = 10 y = -3 }# In Sona, we might write something like the following: \sona#{ [config] { [num_tries] 30 [max_score] 100.0 [waypoint] { [x] 10 [y] -3 } } }# TOML is already a great configuration format, and Sona makes different trade-offs. TOML doesn't need braces because it's completely whitespace- dependent. This results in a cleaner look. Sona needs the braces to help differentiate between paragraph breaks and scope changes for other use cases. Still, subjectively I think Sona more cleanly expresses the hierarchical relationship between [code]{waypoint} and its parent [code]{config}. It's somewhat well known that TOML doesn't handle nesting well. This is a small example, but already it's a little awkward to write [code]{config.waypoint}. Last, because Sona was built first and foremost for prose, including long-form text in a config works perfectly well in Sona, but is much more awkward in other formats. Imagine we wanted to write a longer message that the player might find on a scroll in a treasure chest. It might be nice to include that paragraph-long message alongside the config. In Sona: \sona#{ [config] { [num_tries] 30 [max_score] 100.0 [message] { Here's a longer message that the player might see. It can span multiple lines. Even multiple paragraphs. } [waypoint] { [x] 10 [y] -3 } } } In TOML: \toml#{ [config] max_tries = 30 max_score = 100.0 message = """ Here's a longer message that the player might see. It can span multiple lines. Even multiple paragraphs.""" [config.waypoint] x = 10 y = -3 }# TOML does okay here (especially compared to JSON), but it's still awkward. Then again, this is a fairly rare requirement for config languages, and it's only presented because Sona performs well. } }