garden icon indicating copy to clipboard operation
garden copied to clipboard

Comments or docstrings for rules

Open gnarmis opened this issue 11 years ago • 7 comments

I'm really liking how data-driven this project makes the writing of styles. I imagine having a datastructure that is literally a set of rule vectors, and then passing the whole thing to the css macro for rendering. Kinda like this:

#{[:.red {:color "red"}]
 [:.blue {:color "blue"}]}

But one thing that's missing is comments for each rule. It'd be great if I could define comments/docstrings like in the def and defn macros. So, it'd end up looking like:

#{[:.red "this rule makes text red" {:color "red"}]
  [:.blue "this rule makes text blue" {:color "blue"}]}

Thoughts?

gnarmis avatar Jun 19 '13 10:06 gnarmis

I think this is a brilliant idea. There's only one catch though; Garden treats "the first n non-collection elements of a vector" as rule's selector. This includes keywords, strings, and symbols. To assume a string, or one in a special position, represents documentation would make it difficult to handles cases such as the example below.

[:&:hover (format "&:nth-child(%s)" "even") 
  {:background :green}]

That being said, I still think the general idea is sound.

One way to get around this would be to use a meta and look for, say, a :doc key when the stylesheet is compiled. The "doc string" could be emitted as a css comment when the stylesheet is compiled in non-compressed modes.

So this

^{:doc "This makes text red."} 
[:.red {:color "red"}]

^{:doc "This makes text blue."} 
[:.blue {:color "blue"}]

would emit

/* This makes text red. */
.red { color: red }

/* This makes text blue. */
.blue { color: blue }

Using meta in this way means we could even do this

[:a
  ^{:doc "This makes the text bold."}
  {:font-weight "bold"}
  ^{:doc "This makes the text italic."}
  {:font-style "italic"}]

and have it compile to

a {
  /* This makes the text bold. */
  font-weight: bold;
  /* This makes the text italic. */
  font-style: italic;
}

What do you think?

noprompt avatar Jun 19 '13 23:06 noprompt

The example you provided is great! And it's even better that you could get a property-level comment also.

I'm wondering if this might be better named as 'comment'? I don't want to confuse this CSS comment with clojure's own doc-strings, which drive clojure.repl/doc and other such things. Or is it better to be able to leverage the doc-finding functions in clojure by naming it 'doc'? I'm leaning towards 'doc' because it seems to be what the string actually represents.

I haven't played around with metadata in Clojure before, this seems very useful!

gnarmis avatar Jun 20 '13 04:06 gnarmis

:doc as a meta key should be fine when attached to a map or vector. clojure.repl/doc only cares about vars and special forms (ie. #'garden.core/css, def, let). So calling clojure.repl/doc on one of the example structures above would result in an error. In other words, commenting the stylesheet in this manor shouldn't be a source of interference. Plus it would be fairly easy to implement this feature in the compiler since it's just a matter of checking for the meta :doc value and emitting it as a CSS comment.

One small draw back to this approach, however, is that it wouldn't be possible to emit arbitrary comments. Comments would have to belong to something. Personally, I like that sound of that but it might be a bit too restrictive for some.

Considering your thoughts about the use of :comment, and the small draw back mentioned, another idea might be to do introduce a special comment notation.

^:comment ["This is a line."
           "This is another line."]

In this case when the compiler encounters a vector with the {:comment true} meta attached it could emit an arbitrary comment. The draw backs would be losing the ability to "attach" the comment to whatever it's documenting and figuring out the rendering aesthetics.

Meditating on both of these approaches it may actually be possible to get the best of both worlds.

^:doc ["I'm arbitrary."]

^{:doc "Select anchors..."}
[:a
 ^{:doc ["... and make them bold..."
         "... because it's bold to be bold."]}
 {:font-weight "bold"}
 ^:doc ["My old friend anonymous!"]]

The compiled result would be:

/* I'm arbitrary. */

/* Select anchors... */
a {
  /* ... and make them bold... 
   *
   * ... because it's bold to be bold.
   */
  font-weight: bold;
  /* My old friend anonymous! */
}

The convention basically says if the meta value of :doc is a string or vector compile an "attached" comment. If it's value is true expect a vector, the string contents of which will be compiled as CSS comments.

So how about that?

I haven't played around with metadata in Clojure before, this seems very useful!

Meta is a very interesting idea in Clojure. It's one I haven't seen in other languages. While it isn't always useful, when it is it's really useful.

noprompt avatar Jun 20 '13 09:06 noprompt

That would be really nice to have!

A concrete example where it's needed for more than just comments: polymer uses special comments (like / *@polyfill .content-container div * /) to get a hint on what to do when some feature is not shimed.

jeluard avatar Feb 04 '14 15:02 jeluard

Note that ClojureScript has some restrictions around metadata, not sure how it applies here.

jeluard avatar Feb 04 '14 23:02 jeluard

@jeluard The idea to use meta data is that it's attractive but I'm not sure if it's the right solution anymore.

We might implement a CSSComment type for this sort of thing and expose a css-comment function for convenience with various flags. The CSSComment would be recognized everywhere but within declaration values and automatically formatted to enhance readability. This would provide better control over rendering comments, "parsing" them, and we wouldn't have to worry about inconsistent behavior with ClojureScript. Also, by exposing a function we gain all the benefits therein.

Aside from the formatting code and the rendering implementation, I'd say this is fairly low hanging fruit.

noprompt avatar Feb 05 '14 01:02 noprompt

Makes sense.

I will probably take a look at that but just not right now :)

jeluard avatar Feb 05 '14 02:02 jeluard