I understand the desire for it but I think this design creates problems of understandability and affordness, concentrating the syntax as much as it is done here. ('Affordness' meaning the language ability to show the programmer exactly what can be constructed.)
For example, this piece of code is very short and packs a lot of functionality:
But unless you know it by hand. The constructs @pn(...), *3, the codes 8 1, 2 4 ... or M 5 10 Q 5 5 8 1. Are not remotely obvious or intuitive. And it is not obvious what M and Q means? And what can I as programmer write instead?
I realize that some of these problems comes from SVG however they are problems none the less.
M (MoveTo) and Q (Quadratic Bézier Curve) are part of the svg spec. They’re drawing commands.
I’d agree that pn seems a little obtuse, but I guess I can see what it’s doing.
Having worked with svg a lot (we build something sort of in the cad space) I can definitely see the desire for something less terse when you’re defining svgs. We end up generating svg fragments using react, for the most part, which works fairly well.
Yes. Those codes are from the SVG spec as is the space vs. comma syntax.
But it is really good way to program? Or is something that is done as a compromise between being able to program by hand, and have a format for drawing programs to save their files in without them being silly big.
Well, like it or not that stuff is a) here to stay and b) familiar for people working with this tooling. Personally I find that graphics part pretty easy to read.
For comparison here's a sample of a graphics stream from a PDF:
Q
9469 1441 m
9549 1433 l
9549 1433 9549 1483 9469 1441 c
S
q
In this context Q means push/save the graphics state and q is pop, but again, it's all very similar.
You will save space and make the language suitable as a format for computer programs to work directly with (saving in, sending to printer etc.). However compared to a binary version, this format probably uses 3 times as much space.
Sure. But if you are designing something new it is fair to question whether to continue the style.
An alternative is to have two representations; a binary format to be used by computers and a textual format for humans (programmers) designed for readability, maintainabilty etc.
I would imagine that any syntax transformation can't be much better (if at all) than a simple text compression algorithm, so I don't think disk size should be a design endpoint. But the amount of information that fits on one screen without scrolling is also part of readability, because understanding why something is there can be as important as understanding its literal meaning.
By analogy, what you're asking for is the ability to type `delete3words` instead of `d3w` in Vim.
You might think you want that, what you actually want is to take an index card and write the SVG path abbreviations next to their long names, and put it by your keyboard while you work.
The path data won't be readable to the uninitiated no matter how verbose you make it. The encoding is not the mental bottleneck for reading or writing, it's the math. You'll be familiar with that encoding long before you can actually make sense of the numbers.
OP should really extend his syntax with an optional verbose version of the SVG path language. It was always the reason I found typing / reading SVG files so difficult.
I'd actually love some alternative approaches to path description, that are translated into the common SVG path representation by a compiler. E.g. something turtle-like, where the "cursor" also has a heading and you could describe a curve like "10 degrees left, radius 50" and distances by outcome "straight on until we hit absolute y==100" (in a terse syntax of course).
But a more verbose version of e.g. the arc-a? Not interested at all: those seven parameters (+2 from the implicit cursor) would not be particularly palatable even if they were all explicitly named.
Not quite what I had in mind (seems to be more like a diagram DSL?), I'd rather stay within SVG, just with an improved experience.
But thanks for sharing anyways, never heard of this and I should have. Even the name alone is awesome!
(speaking of SVG experience, I've been fantasizing about an SVG editor that would, in a mouseover on path numbers, preview what would change if that value would wiggle a little up and down. Does anything like this exist?)
Because 1. in the original, they were separate as well, 2. the path is derivative of the endpoint 3. you might want to cycle the colours or they're a pure derivative calculation based of the number of points or whatnot. So combining them like that is definitely prettier and makes sense if the requirements don't change, but also seems like a premature optimisation. (also, forgot about `key`)
Oh I didn't notice that from the example. Is it worth splitting off the last two parts for that?
> you might want to cycle the colours or they're a pure derivative calculation based of the number of points or whatnot
Simply lift color out and use the second argument to map's closure to index it modulo the length of color.
If you really anticipate this, you should have %X.length everywhere, otherwise it just looks like a bug the next guy is going to hit and blame you for it. The problem (as I see it) stems from the hardcoded [0,1,2] iota -- if there's a better (domain-specific) way to eliminate it, then great, but it'll have to consider the rank of M's constituents and I just don't think the juice is worth the squeeze.
> combining them like that is definitely prettier and makes sense if the requirements don't change, but also seems like a premature optimisation
I would urge you to reconsider.
Trying to guess what the next person is going to want to do tends to create more code, not less, and changing a little code is better than changing a lot.
Everybody already knows and uses React and I had to repeat a tag name once only (barring the hidden React.Fragment). Sure it'll be clearer and more uniform, yet somehow you're typing this in English instead of Esperanto, Volapük or Toki Pona.
It's fine that you don't understand how the Clojure ecosystem works, but you don't. No one would bother listing hiccup, which is very little more than a convention for representing HTML.
OK, fair enough, a search for JSX doesn't give any results either. To step back a bit though, there's 1 job with Clojure listed on my country's biggest job board. React? 3200.
My whole point was trying to prove that you don't have to have something new and obscure to enable something but it's already there in something that almost everyone is using already. And then you replied that you can do it cleaner in something objectively vastly more obscure. Yes, yes you can. I'm sure you can.
I'd suggest not painting yourself into a corner where your map has to be either key/value or an array.
Lua got this right, most other languages didn't.
It's an anti-feature, especially from a data modeling perspective. Treating indices as implicit is good, pretending integer indices are special, and must be separated from all other sorts of mapping, is not.
Consider that Lua can express XML without making up a fake key for children:
In my hobby DSL, those inlined childX are syntactic sugar for parent{ children=[child1, child2, child3]}.
More generally, I remain uncomfortably undecided about named params (pairs) and indexed params. Esp wrt constructors.
IIRC, I spotted a (hobby?) language that permitted both indexed params (matched in order per method signature) and named params, plus default values. So given "method( int a=10, int b=20)" you could invoke as "method( 1, 2 )", out of order like "method( b: 2, a: 1)" or partially like "method( b: 2 )".
Riffing a bit, this could then allow passing a map of params to a method. Code construction wise, that looks like passing around a context object.
I'll look at Lua again. (It's been a minute.) Thanks.
I was thinking the same thing as I was reading the code but realised that I'd worked out what it was doing pretty much as I was critiquing it. Not sure about the "pn" in "@pn" though ... does it come from something I'm not familiar with?
And as others have said, I knew the M .. Q stuff was SVG anyhow (not that I know it off the top of my head) ... generally the syntax seems nice TBH
I think this depends a lot on who the syntax is tailored towards. This compact stuff reminds me of APL and aspects of Perl. There's nothing wrong with highly specialised brevity. I personally love this syntax, coming from a place of moderate SVG knowledge and CSS fluency. Looks really cool and quick for prototypes. And even the example you posted feels mostly parseable on the first few scans. Nothing insurmountable, and in tune with most other news syntaxes and abstractions in this space tbh.
I think the real question for this whole thread is, how many SVG files are there that operate solely on integers, or could plausibly be reconstructed as such?
Once my SVG file is full of 6.829347908723890's, who cares if it is an M or a Move in terms of being human-writable? And being a vector-based format, there is indeed a real difference between 6.83 and 6.829347908723890 so there isn't a great escape from numbers that a human will find excessively precise. Honestly even the two digits is already getting up there when you see it in a big table with a thousand other numbers.
XML is verbose enough to add significant verbosity to the SVG file even in the presence of floating point numbers rendered as strings, but these sort of cute little "M 5 10 Q 5 5 8 1," go too far the other way. SVG files don't look like that.
SVGs aren't human-writable at any sort of scale anyhow. (Here, "at scale" means in the general case. Sure, you can construct an SVG by hand if you like, but that will never be the way they are primarily generated. They will be primarily generated in tools.) If you conclude from that that using a serialization format optimized for human readability was sort of silly... I agree! But it isn't XML's verbosity making SVGs human unwritable at scale, it's the problem space itself. Nobody wants to be typing in all these numbers. Even if you reduce the cost of the non-number stuff to literally zero and stipulate literal mind reading from the rest of the spec, it would still be impractical to hand-write SVGs in the general case.
I wasn't close to the story, but I'll try to summarize, as nobody else has posted a reply.
Eric Meyer was very active in the html standards community and blogged and promoted html css and firefox extensively, wrote books, etc, and was very well known in the community, perhaps the most well known.
At some point his five year old daughter was found to have a terminal illness. He wrote some wrenching blog posts about his struggle knowing she was soon to die, trying to help maintain her innocence of that fact as she continued to get worse, to enjoy the remaining days without getting overwhelmed with grief. Then she died.
In honor of Eric's loss and in recognition of his efforts to promote modern web design, they added a name to the css spec of his daughter's favorite color.
I honestly wonder if it wasn’t also influenced at least a tiny bit by people wanting a decent purple named colour. I know it had always grated with me that pretty much all the other colours were fairly well-represented, but there just wasn’t a good purple, and I regularly use rebeccapurple as a temporary colour, because of its value, not its history.
(I’m not suggesting this was a conscious factor in any way, but at the same time it wouldn’t surprise me if in an alternate history where Becca’s favourite colour was green or blue that the entire thing wouldn’t have come to fruition.)
If often then it's definietly a good idea to simplify SVG/XML for writing.
I once experimented with some extremely minimal formats[1] built on Jevko[2] (I am its father) particularly aimed at compacting SVG. For example:
svg width[391] height[391] viewBox[-70.5 -70.5 391 391] xmlns[http://www.w3.org/2000/svg] xmlns:xlink[http://www.w3.org/1999/xlink][
rect fill[#fff] stroke[#000] x[-70] y[-70] width[390] height[390]
g opacity[0.8][
rect x[25] y[25] width[200] height[200] fill[lime] stroke-width[4] stroke[pink]
circle cx[125] cy[125] r[75] fill[orange]
polyline points[50,150 50,200 200,200 200,100] stroke[red] stroke-width[4] fill[none]
line x1[50] y1[50] x2[200] y2[200] stroke[blue] stroke-width[4]
]
]
Compared to CSS-like syntax like in the post, the advantage of this is that it is extremely simple and generic, as it works for XML in general (especially the more minimal flavors, e.g. [3]).
There are no specialized features here but also not many parsing challenges or edge cases.
Clearly, there are ways to simplify these things, but not many people seem to be really interested in that.
A data point: The New York Public Library just did their fourth SVG study group earlier this month. The description was "This group is studying Scalable Vector Graphics, images which can be composed in text editors like Notepad, as a way for Blind and low-vision people to create our own drawings or work with existing images. Feel free to join us if you're interested in drawing with code."
Unfortunately that was all the info I have. It was through the workshop newsletter that the library maintains. More info on workshops and how to subscribe: https://www.nypl.org/about/locations/heiskell/news
A bit aside, but while working on a kind of CSS for a different purpose this past year I realized that there's no real distinction* between CSS-the-syntax and CSS-the-spec/rules/properties/selectors/etc.
Perpetually blows my mind that there's no great way to describe other lovely uses of its concepts.
* I couldn't find one after hours of reading old specs, searching, cold-calling a small number of people involved with the specs, working groups, CSS parsers, etc. Doesn't mean it doesn't exist--but I gave the tree the best shake I could.
Yes, CSS is not a strict "language" unfortunately.
prop: a b c / d e f;
can be treated in some properties as list:
prop: a b (c / d) e f;
and some others as
prop: (a b c) / (d e f);
Same thing for ','
prop: a b c , d;
Can be as
prop: (a b c) , (d);
as:
prop: a b (c , d); // e.g. in font property definition.
In that sense CSS syntax is a Christmas tree: each member of the family (feature author) adds its own stuff as she sees it. No moderation on that historically.
I admit that this section threw me a little bit for a loop. I mean, I can't assume the author doesn't know this, but this article and the repo give no indication that these are being used properly as rebindable prefixes mapping to namespace declarations. They're not just names-with-colons-in.
In fact, CSS already has syntax for namespaces[0]:
@namespace prefix url(XML-namespace-URL);
/* or */
@namespace prefix "XML-namespace-URL";
/* which is then referenced as */
prefix|element { }
…so I imagine it would have been a smaller innovation to continue to use the pipe as the delimiter.
@namespace url(http://www.w3.org/2000/svg);
@namespace xlink url(http://www.w3.org/1999/xlink);
use {
xlink|href: #circle;
}
(But rebindable prefixes have turned out to be bad on the open web[1], so maybe not.)
I love this. It's very similar to something I've been working on for a while - a programming language for UI designers. The syntax he's arrived at is quite similar to mine.
With a few tweaks, and adding a define & use (simple class prototyping), it's basically VRML-97. Before the X3D goons ganked it with all their XML and XSchema nonsense.
Yes exactly. My approach was to make everything a component. In each component, you'd define your props (called "variants" in my language), elements, and styles.
Something like this:
component Square
variants
color bg: red
elements
shape square
style square
width: 100px
height: 100px
fill: $bg
Why going for CSS as a syntactical starting point, if it is to change it so fundamentally that no IDE or existing tools will be able to handle it, and if it is to move away from its "theoretical" purpose of describing style independently from content?
Going that way, there are so many (existing) possibilities. Want something that looks like CSS but that has more structure? Use YAML. Preferring braces over spaces to delimit blocks, but don't fancy quotes everywhere? Use Groovy -- you will even be able to write a DSL to generate SVG in an afternoon, with the entire power of the JVM. Don't want anything executable? Forbid it. Refrain from picking a syntax that are not fitting your needs and for a language whose intent is different, you will just call for confusion
I respectfully disagree. I think it's really nice when a new language reuses existing syntax and allows me to make use of my existing mental structures.
As an example, I love it that json is like js, and that js is a bit like C. Even when there are inevitable "false friends" in any new language, it's so nice to have that starting advantage.
From the second section of the article, appropriately titled CSS Syntax:
> What I love about CSS is its readability. There are no unnecessary quotes around property values even when separated by spaces. And the CSS code always expands from top to bottom if following best practices.
My god it’s full of ~~JSX~~ s-exprs. Every time I see a declarative expression syntax exploration I’m delighted to see the lisp in it, every single time.
Yeah, that was my first thought. The author thinks they are extending CSS, but actually reinvented HAML with CSS syntax.
CSS as a language is supposed to apply to an existing DOM tree, not synthesize an entirely new one. The selector syntax alone is too ambiguous to actually do that, because it is a search lookup, not a tree structure (even though SASS/LESS can make it look like one). If you specify, say, three `svg path` selectors with rules in them, you aren't asking for three separate paths in an SVG node. You're asking for all paths in all SVG elements, including grandchildren and great-grandchildren, to be handed all of the rules in all matching selectors.
If we wanted to make this idea work while not redefining CSS selectors, we'd have to ban the descendent combinator (because it would create infinite node hierarchies), and use the child combinator and nth-child everywhere exclusively. So instead of `svg path` you'd have `svg > path:nth-child(1)`. And probably a `::synthesize()` selector for saying, "yes I want this CSS rule to create a DOM node".
I love Pug for Vue projects, especially when writing SVG components. Way cleaner markup, feels more like the other languages in my stack, and integrates perfectly with modern frameworks!
HAML structure is really easy to understand. It attempts to strip out as much of the annoying HTML repetition as possible. For example to write paragraph tag you could use:
%p This is HTML paragraph.
HAML will convert that to:
<p>This is HTML paragraph</p>
You can also pass more attributes to the tag you want:
.banners(id="top-banner", title="Your ad here") Your text here
Will be rendered like this:
<div id="top-banner" class="banners" title="Your ad here">Your text here</div>
You don't need to close <p> tag, it closes automatically.
Also supporting something as simple as </> (close current tag) would significantly reduce HTML boilerplate without inventing new language. I agree that shortcuts for id and class are nice too.
Note though that including markup declarations for enumerating custom class names and for the input element having declared content EMPTY is required (the latter declaration actually part of HTML DTDs [1]):
<!attlist div class (content) #implied>
<!element input - - empty>
Moreover, in SGML you can have tag omission/inference, like on the p element or the html element itself.
Your "</>" Close current tag syntax is actually part of SGML (as is "<>" which is treated as start element tag for the most recently closed element), known as FEATURES MINIMIZE SHORTTAG ENDTAG EMPTY and FEATURES MINIMIZE SHORTTAG STARTTAG EMPTY features, resp. ([2]).
Minor correction: the comma there isn't valid Haml syntax, when you use parenthesis for attributes it expects the same format as inside a regular HTML tag (i.e. attributes separated by whitespace).
IDK how closely HAML hews to valid HTML elements/attrs/etc., but DMark (https://denisdefreyne.github.io/d-mark/) is syntactically similar and very extensible.
Love the article and these kind of experiments! The only thing I don't like about this, is that CSS has traditionally been used to style the html components, so when doing this:
For me it's confusing since I read it as "all the rects have that x and y" while in this experiment it's actually defining a single instance of a rect. I'd rather prefer the styled components way (in fact I've done few experiments around it) like this:
I do something related; I extend sass with a few custom functions which allow a convenient way to build svg from specifications written directly into the sass. Specifically I use it to build svg filters which are intimately related to the css rules which apply them. It's very useful to have both the css and svg produced in the same pass by the same tool.
I haven't done it, but this system would probably also be useful for using CSS to animate SVG
And with such speed. I don't think I've ever seen a web page render in 150ms to here over my wireless internet connection. Even a full load of this HN page takes 800ms+, and I think of HN as the benchmark for fast loading.
I just thought about doing this exactly, but for react-three-fiber! In my previous company we did an interesting experiment that worked pretty well internally:
I’m not at all qualified to say whether what they’ve explored is objectively better, but there’s a ton of opportunity to explore the benefits and possibilities of declarative DSLs. New syntax and exploration is awesome. Cross-compiling is pretty common across many ecosystems at this point, so if the underlying tech is superior using it is still an option with whatever expressiveness a new DSL brings. My question (mostly to myself) is why haven’t we embrace this more?
> Nowadays, though, it's still possible for HTML to grow in two dimensions if using tools like Tailwind, where the long predefined class names are kind of extended attributes to HTML elements.
It's so infuriating when people say this against Tailwind. Nothing is forcing you to leave giant lists of class names directly on the HTML tags, the documentation very clearly states you can use the provided @apply function to move things into CSS. Throwing giant lists of class names down to prototype then refactoring is incredibly efficient, but it's not like you just shit out your first idea to production in any other context.
The post expresses no opinion on whether placing Tailwind class names directly on the HTML tags is better or worse than placing them in CSS. It’s merely saying that the mini-language of Tailwind class names themselves (regardless of where they are placed) is a new syntactic dimension compared to unstyled HTML—in the same way that CSS is a new syntactic dimension compared to unstyled HTML.
For example, this piece of code is very short and packs a lot of functionality:
But unless you know it by hand. The constructs @pn(...), *3, the codes 8 1, 2 4 ... or M 5 10 Q 5 5 8 1. Are not remotely obvious or intuitive. And it is not obvious what M and Q means? And what can I as programmer write instead?I realize that some of these problems comes from SVG however they are problems none the less.