atom-github-syntax

Up-to-date syntax colours that match GitHub's motif, including day/night mode.

Alhadis

75

0

1.0.0

ISC

GitHub

GitHub syntax theme for Atom

This is a syntax highlighting theme for Atom that replicates the exact appearance of highlighted source-code on GitHub.com. It was created to facilitate development of TextMate-compatible grammars for use on GitHub.

Comparison between syntax theme and GitHub's styling (as of 2022-02-26)

Features

To-do list

TextMate vs CSS

TextMate Scope Selectors are not completely compatible with CSS classes, despite sharing a superficial resemblance:

.string.quoted.double      CSS
 string.quoted.double      TextMate

In CSS, the order in which classes are listed in a class selector is irrelevant: .string.quoted.double is behaves the same as .double.quoted.string. TextMate selectors, however, are sensitive to the order in which scopes are listed, which means string.quoted matches string.quoted.double but not quoted.string, string.foo.quoted, or even foo.string.quoted.

Why is this relevant?

GitHub uses TextMate selectors to map tokenised scope-lists onto CSS classes. In rare cases, a grammar might specify a scope-list that TextMate and CSS selectors interpret differently. For example, consider the following pattern:

name: "variable.global.other"
match: /\$\w+/

GitHub recognises both the variable and variable.other scopes, and assigns a different colour to each. On GitHub, the aforementioned rule will be highlighted as the former (variable), whereas a naïve theme targeting .variable.other in CSS will see the latter.

The solution

CSS provides no elegant way to implement an “order-dependent class selector”. An ugly alternative is to use attribute selectors instead:

// NB: This example omits the rebarbative `syntax--` prefix necessitated by Atom
:is([class="string quoted double"], [class^="string quoted double "]){
	
}

Astute authors will correctly note several limitations with this approach:

  1. Classes must be separated by a single space (U+0020) only.
    Multiple spaces or other whitespace characters won't match.
  2. class attributes cannot contain leading or trailing whitespace.
  3. Selectors must avoid matching more qualified scope-lists.
    E.g., variable.other should not inherit the styling applied to variable, or vice versa. This requires the inclusion of a :not() qualifier for every conflicting scope-list. For example:
    // Target "string" scope, but not more qualified selectors
    // such as "string.quoted.double" or "string.quoted.single"
    :is([class^="string "]):not(
    	[class^="string quoted double"],
    	[class^="string quoted single"]
    ){ }
    
  4. The list of supported scopes must be known ahead-of-time.
    This is stipulated by the previous point.

Thankfully, each constraint is satisfied by Atom's built-in use of Less for generating stylesheets. A script is provided for regenerating the scope-map variables listed in scope-map.less.

Related links