Spoiler: I created my own configuration language maml.dev
Here will be a list of all markup languages/configuration languages I found on the internet, and things I don't like about them.
YAML
- - 1 - 2 - - 3 - 4YAML 1.2 is better than YAML 1.0. But still, the YAML specification is monstrous, and I don't get how people trying to implement it are not going insane. YAML contains too many features.
XML
<?xml version="1.0" encoding="UTF-8"?> <catalog xmlns="http://ex.com/catalog" xmlns:cat="http://ex.com/catalog" xmlns:old="http://ex.com/oldcatalog"> <item id="0042"> <name>R&D Handbook</name> <notes priority="1 2 3">n/a</notes> </item> </catalog>The era of XML is in the past. I remember the hype around XML, how it was thought to be a universal format, and people created a lot of stuff around it. But now it's dead.
JSON
{"name": "John", "age": 30, "car": null}JSON is nice and JSON won. It's a universal, data-interchange format for the Web and applications. This is why I based my MAML on top of JSON. I fixed things that were a little bit annoying for me inside JSON.
TOML
[[servers.web]] name = "frontend" ip = "192.168.1.10" [[servers]] region = "eu-central" [[servers.web]] name = "backend" ip = "192.168.1.11"I don't get why the [table] is more readable, and I don't understand [[array of tables]] out of order. And the lack of null.
JSON5
{ lineBreaks: 'Look, Mom! \ No \\n\'s!', hexadecimal: 0xdecaf, a: +.8675309, b: +8675309., }Too many unnecessary features. Object key-value pairs are still unordered. No distinction between integers and floats.
HJSON
{ Hjson: a string RegEx: \s+ md: ''' First line. Second line. This line is indented by two spaces. ''' }Unquoted strings and three different types of comments. Multi-line strings with significant indentation.
JSONH
{ // use #, // or /**/ comments keys: without quotes, isn\'t: { that: cool? # yes } }JSONH is same as HJSON but different.
RJSON
{ shopping-list: [ milk butter /* don't forget the beer */ beer ] a\ space : t\:em item\ with\ spaces }Strings without quotes, but only if they don't contain spaces or commas. No specification.
JSONC
{ /* This is a multi-line comment that spans multiple lines */ "name": "Jane Doe", "age": 25, }There are so many implementations and differences in implementations of JSON with comments. For example, this one has trailing commas. Still allows duplicate keys, still no integers, unordered key-value objects.
HCL
service "aws_ami" "ubuntu" { most_recent = true instance_type = var.instance_type != "" ? var.instance_type : "t3.micro" }I don't like nesting with service "http" "web_proxy" or ability to specify service multiple times in different parts of the file.
Pkl
class Bird { name: String hidden taxonomy: Taxonomy } pigeon: Bird = new { name = "Common wood pigeon" taxonomy { species = "Columba palumbus" } }This is not a markup language. This is a full-blown programming language. I honestly would just use TypeScript instead of this one.
RON
GameConfig( // optional struct name window_size: (800, 600), key_bindings: { "up": Up, "down": Down, "left": Left, "right": Right, }, )Very Rust-centric.
EDN
#:demo{:id #uuid "de305d54-75b4-431b-adb2-eb6b9e546014" :ts #inst "2025-11-04T09:00:00Z" :nums [1 2 3 4/2 5.5M] :set #{:a :b :c} :rx #"[A-Z]+" :q #queue ["x" "y"] :tag #user{:name "Zed"}}I guess Clojure developers love it. I'm not one of them.
HOCON
include required("foo.conf") a : [ 1, 2 ] [ 3, 4 ] data-center-east = ${data-center-generic} { name = "east" } { foo include : 42 }Too many features. Is it some sort of programming language? And it looks like it's very focused on just one project.
NestedText
default repository: home report style: tree compact format: {repo}: {size:{fmt}}. Last back up: {last_create:ddd, MMM DD}. date format: D MMMM YYYY size format: .2bYAML variant with only strings. But I need booleans!
KDL
author "Alex Monad" [email protected] active=#true scripts { message """ hello world """ }KDL is much closer to XML with properties on nodes. But I like JSON-like data structures. They are easier to understand. Also, I don't like significant indentation on multi-line strings.
SDLang
// Trailing semicolons are optional prop true; anotherprod on; author "Peter Parker" this-is.1_valid$Tag-Name renderer:options "invisible" physics:options "nocollide" title \ "Some title"They do have true and false. Why adding on and off? By default, integers are 32 bits long. Suffix 10L is needed for 64-bits.
CUE
import "math" piPlusOne: math.Pi + 1 "quoted field names": { "four^four": math.Pow(4, 4) }I would just use TypeScript instead of this programming language. Too many features; the specification is too big.
Dhall
let makeUser = \(user : Text) -> let home = "/home/${user}" let privateKey = "${home}/.ssh/id_ed25519" let publicKey = "${privateKey}.pub" in { home, privateKey, publicKey } {- Add another user to this list -} in [ makeUser "bill" , makeUser "jane" ]Again, it is a programming language. So I guess only one implementation of Dhall exists?
Jsonnet
local my_function(x, y=10) = x + y; { person1: { name: "Alice", welcome: "Hello " + self.name + "!", }, person2: self.person1 { name: "Bob" }, len: [ std.length('hello'), std.length([1, 2, 3]), ] }Well, this is some sort of programming language with dynamic types. But there are so many good programming languages, so I don't know why this one needs to be used.
Nickel
let conf = { name = "NiCl", version = "0.0.1$", description = "My cool app!" } in let SemanticVersion = fun label value => let pattern = "^\\d{1,2}\\.\\d{1,2}(\\.\\d{1,2})?$" in if std.string.is_match pattern value then value else let msg = "invalid version number" in std.contract.blame_with_message msg label in let AppSchema = { name | String, version | SemanticVersion, description | String, } in conf | AppSchemaNice programming language. Not a markup language.
Starlark
def fizz_buzz(n): """Print Fizz Buzz numbers from 1 to n.""" for i in range(1, n + 1): s = "" if i % 3 == 0: s += "Fizz" if i % 5 == 0: s += "Buzz" print(s if s else i) fizz_buzz(20)Starlark is a programming language. Good lack porting/reimplementing Starlark in another programming language.
UCG
let tuple = { inner = { field = "value", }, list = [1, 2] + [3], "quoted field" = "quoted value", };This is just an implementation of a language. Not portable to other languages.
UCL
.include "${CURDIR}/path.conf" .macro_name(param={key=value}) "something"; section "blah" "foo" { key = value; }Okay. An implementation of a configuration language. No specification. No other implementations.
Confetti
probe-device eth0 eth1 user * { login anonymous password "${ENV:ANONPASS}" machine 167.89.14.1 proxy { try-ports 582 583 584 } }Nice logo! But other than that, I found it difficult to understand what's going on in this example. What about escaping in strings?
HUML
website:: ports:: 80, 443 enabled: true factor: 3.14 props:: mime_type: "text/html", encoding: "gzip" tags:: - "markup" - "webpage" - "schema"Nice idea to make YAML less worse. But it's still a YAML, with the same problems and significant indentation.
MAML
{ project: "MAML" tags: [ "minimal" "readable" ] # A simple nested object spec: { version: 1 author: "Anton Medvedev" } # Array of objects examples: [ { name: "JSON", born: 2001 } { name: "MAML", born: 2025 } ] notes: """ This is a multiline raw strings. Keeps formatting as-is. """ }So, I decided to create a specification for my own language. And I wanted a distinctive name, not JSON something. I wanted a nice name and a strict specification. All languages have trade-offs. MAML as well.
.png)
  
