Serious problem with CSS style namespace vis-a-vis syntax highlighting


#1

I have a custom syntax highlighter, which I translated from a TextMate / SublimeText theme (directly; just converted the plist to json).

On Atom, with any of the standard themes, it looks like close parens and close braces get styled really weird: They get rendered on the right-hand side of the window, in a larger-than-normal size, styled bold and light grey. Here’s a screenshot.

One thing that’s different in my syntax rules compared to many is that parens and brackets generally end up getting tagged individually. In my case, I use tags along the lines of punctuation.paren.open.myname punctuation.paren.close.myname (with bracket and brace also used in addition to paren).


[Assembly] Default label styles are annoying
#2

I went ahead and created a minimal-ish grammar that demonstrates the problem. Here it is (attached below). For example, take this original source and name it foo.blort:

foo = {
  bar[baz] = biff(zorch[frotz]);
  bar[7] = { bar[8]; bar[9] };
}

Atom renders this as:

Note that with the cursor on the brace (as shown), the highlight for the close brace is in the expected position even though the brace itself is way off to the right.


blort.json

{
  "fileTypes" : [
    "blort"
  ],
  "repository" : {
    "block-body" : {
      "patterns" : [
        {
          "end" : "\\)",
          "begin" : "\\(",
          "beginCaptures" : {
            "0" : {
              "name" : "punctuation.paren.open.blort"
            }
          },
          "patterns" : [
            {
              "include" : "#block-body"
            }
          ],
          "name" : "meta.parens.blort",
          "endCaptures" : {
            "0" : {
              "name" : "punctuation.paren.close.blort"
            }
          }
        },
        {
          "end" : "\\]",
          "begin" : "\\[",
          "beginCaptures" : {
            "0" : {
              "name" : "punctuation.bracket.open.blort"
            }
          },
          "patterns" : [
            {
              "include" : "#block-body"
            }
          ],
          "name" : "meta.collection.blort",
          "endCaptures" : {
            "0" : {
              "name" : "punctuation.bracket.close.blort"
            }
          }
        },
        {
          "end" : "\\}",
          "begin" : "\\{",
          "beginCaptures" : {
            "0" : {
              "name" : "punctuation.brace.open.blort"
            }
          },
          "patterns" : [
            {
              "include" : "#block-body"
            }
          ],
          "name" : "meta.block.blort",
          "endCaptures" : {
            "0" : {
              "name" : "punctuation.brace.close.blort"
            }
          }
        },
        {
          "match" : "[a-z]+",
          "name" : "variable.parameter"
        }
      ]
    }
  },
  "patterns" : [
    {
      "include" : "#block-body"
    }
  ],
  "name" : "Blort",
  "scopeName" : "source.blort"
}

#3

I’ve played around with the syntax rules a bit, to see if I could narrow down the issue.

It looks to me like the component name close within a tag (appearing anywhere within a tag name) ends up having “magic” properties. For example, if I rename all the .close.s in the grammar to instead be .closex., then the problem goes away.

So, there is at least a workaround. However, this is pretty surprising behavior!


#4

In the developer pane, I walked the DOM to see what’s going on. It turns out that a syntax tag foo.bar.baz gets turned into a class tag on a span element of "foo bar baz". So, in my case, I see:

<span class="punctuation paren close blort">)</span>

In the “Styles” pane, it shows that, indeed, there is an entry for .close as follows:

.close {
    float: right;
    font-size: 21px;
    font-weight: bold;
    line-height: 1;
    color: #000000;
    text-shadow: 0 1px 0 #ffffff;
    opacity: 0.2;
    filter: alpha(opacity=20);
}

I don’t know where this is coming from, but this is the direct cause of the weirdness I’m seeing.

My best guess is that the .close rule is meant to be internal to Atom and not exposed as part of syntax highlighting, and the fundamental culprit is that the component names of syntax styles turn directly into the same name as a CSS class. For example, I bet you’d see some weird things if you happened to use gutter or line or scroll-view as a syntax style component.

If so, one possible way to fix this is to uniformly add a prefix, such as syn_, to all CSS classes that are derived from syntax markup. This would avoid any unintentional overlap between what’s written in syntax grammars and Atom’s internal setup.


#5

I poked around the app a bit more and found that the definition for .close is coming from the file node_modules/bootstrap/dist/css/bootstrap.css. This appears to be part of the Bootstrap UI framework http://getbootstrap.com, where it looks like it’s intended to be the style for close buttons; see http://getbootstrap.com/css/#helper-classes-close.


#6

Original source: https://github.com/twbs/bootstrap/blob/master/less/close.less


#7

[tap tap] Is this thing on?

Hoping to get an official word from one of the core devs.


#8

Per https://github.com/atom/highlights/issues/2, this is now being tracked on the (non-public I think) main Atom repo.


#9

The previously-private issue is now public: https://github.com/atom/atom/issues/1800