I personally prefer using data structures as html as long as I can, then rendering the html to a string at the last moment. This has the advantage of being able to use the entire programming language on the html-y data.
In Clojure there are a bunch of tools for doing this. One is hiccup, it's for server side html rendering. You can define a function that returns a Clojure datastructure like so:
There are also tools for doing this in clojurescript. My favorite here is called Reagent (http://reagent-project.github.io/). It's a minimal wrapper for react.js that appeals to me because I can focus on my code since there's less to know compared to Om.
I've always though of HTML as a way to hide the idea that it the markup is just an s-expression shared over a network. Indeed, Roy Fielding's work on ReST leverages the default paradigm of distributed computing using immutable data-structures in the first place.
"I've always though of HTML as a way to hide the idea that it the markup is just an s-expression"
This is a historical issue with HTML. It's supposed to be "markup". The original idea was that HTML documents would be mostly text with some tagging. Since it was just "markup", markers that triggered formatting operations, it wasn't considered necessary that a strict tree structure be enforced. HTML5 still tolerates and parses such constructs as "Plain <b>Bold <i>Bold italic </b>Italic </i> Plain". This may be a holdover from the way things worked in UNIX nroff/troff, an early markup language.
XHTML requires that the tags balance, which seems to put a lot of people off. I thought at one time that XHTML would replace HTML, but that didn't happen.
In retrospect, browsers were made too lenient. It probably would have been better if, after detecting an error, browsers put a red band across the page with an error message, then continued to display using default fonts and colors. Then we could have avoided years of struggling with browser incompatibilities due to non-uniform handling of errors.
(I'm currently trying to figure out why BeautifulSoup 4, the Python library, creates a broken parse tree and crashes for documents which contain "<head><head> ... </head></head>". "kroger.com" has that. You'd think that the web pages of the Fortune 100 would be better.)
So much simpler to parse, so much less room for ambiguity.
No <b><i>mismatched</b></i> closing parens. No <p>optional close tags. No difference between compulsory close tags <script></script> or <img /> self closing tags.
But without a specialized editor, SGML is nicer to write.
SGML is nice for humans. S-exprs are nice for programs.
Easier to parse, but it would be close to impossible for humans to edit the real-world pages. Try turning any bootstrap template with their 10+ nested levels of tags into the syntax you propose, and then try moving things around in the editor, finding the right spot to append an element when all you see is something like )))))))), that would be crazy hard to do without errors. To make that work we would first need some kind of function syntax, so that deep nested blocks can be simplified.
Parent mentioned "specialized editor". What he meant was emacs + ParEdit, which alleviates these problems. With ParEdit, you don't navigate around and edit sequences of characters - you edit nodes in a tree - where each set of parens in the text represents a node and the individual identifiers are the leaves. It's awkward to use at first because you need to supress your usual text-editing habits, but the productivity gain once you're familiar with it is worth the training.
Besides, Lisp has the tooling for collapsing deeply nested structures into flatter ones if you need to, because one can use nested defines inside a function and later just call by name if needed. It just means the stuff that would've been more deeply nested will be defined earlier than it's container. Most of the time this is usually what you want anyway, because you're going to be reusing a lot of the structure elsewhere in the document - DRY becomes a lot simpler.
A lot of people get their start with HTML by just opening it up with .... whatever ... and fiddling with it. These people are not Lisp programmers, not by a long shot.
HTML is nice in part because it's pretty easy and accessible for people who are not programmers by training.
In a vacuum, they might be the same, although like someone else mentioned, with parens, you eventually get the dreaded ))))))) somewhere.
It's not in a vacuum though: there are tons of tools and tutorials and colleagues and other things dealing with HTML as it is, and tons of people used to how it currently is.
The original question, "how would sexprs make a better markup language", was in a vacuum. At least that's how I took it, and for good reason. A discussion whose pivotal argument is "well, that's how we do things now" is neither interesting nor (after the first few times your idealism is stomped on) is it illuminating.
In my experience, I've not found this to be true. When writing lisp, I find that very quickly the parens just disappear. Even when I first started writing it. And balancing tags in *ML languages is not something I've ever found "easier". Both require a specialized editors for "power users" to be more productive.
All pages would be about 1/2 the size the are now. Think of the gagillions of moogaboots we'd have saved over the years! These migibits could have been used to promote world peace or even disseminating your grandmother's unsurpassed oatmeal cookie recipe! You pick!
"I personally prefer using data structures as html as long as I can, then rendering the html to a string at the last moment."
I'd go so far as to say that is the correct way to do it and anybody doing anything else is doing it wrong. Anything other than "immediately parse all incoming data to internal structures" and "serialize internal structures at the last possible moment" is just crazy insane to deal with, and unfortunately, when it comes to the web, "crazy insane" immediately leads to "insecure".
While I agree in part, I often find that page html isn't much like a proper data structure at all: it's littered with tons of presentational fluff like wrapper divs.
I find that HTML is usually more tightly coupled with the CSS than the associated logic (which is done with more traditional data structures). for this reason I find views written in programming languages can feel like a clunky abstraction over HTML, rather than a simplification of it.
Ah, yes, I should have gone into this. Somehow, hand a person an HTML data structure and suddenly they forget they're in a programming language. I'm not being sarcastic in the slightest, I see this all the time, I wish I had a name for it. (See also Ruby-style DSLs that somehow encourage you to forget you're actually still in Ruby, for instance.)
Anyhow, the solution to "repetitive HTML" is the exact same as the solution to "repetitive code", because it is repetitive code: Factor it.
Get used to this approach and honestly, the only thing that a conventional template is better at is large blocks of static HTML tags; otherwise, a "powerful, rich, awesome, wonderful" template language that everyone goes gaga over is just an inner-platform effect problem mistaken for virtue.
I'm also generally underwhelmed by the "'dumb' designer has to be able to edit it"... I'm sure someone, somewhere has that use case (I mean, don't bother replying, really, I believe you have this use case), but it seems to me an awful lot of people plan for that use case but it never actually manifests. I'm not convinced it's the common case.
I'm not sure I can speak for jerf, but I think the important part is to put off all that presentational fluff to the last minute, as part of your serialization.
People use 'hiccup syntax' to mean the [:h2 "okay"] style of datastructures. Hiccup is actually the name of the (first?) clojure library that parses
[:p.tall "hi"]
into:
<p class="tall">hi</p>
.
Reagent is a clojurescript library that lets one write a Single Page App as clojure datastructures. Most of what reagent does is take a function that returns 'hiccup syntax' and turns it into a react.js component. One can also create components using Reagent by hooking into the :component-did-mount events.
In Clojure there are a bunch of tools for doing this. One is hiccup, it's for server side html rendering. You can define a function that returns a Clojure datastructure like so:
Then: and: There are also tools for doing this in clojurescript. My favorite here is called Reagent (http://reagent-project.github.io/). It's a minimal wrapper for react.js that appeals to me because I can focus on my code since there's less to know compared to Om.