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.
- Automatic dark-mode detected from system settings.
- Support for high-contrast and “dimmed” theme variants.
- Support for colourblind users (protanopia, deuteranopia, tritanopia)
- Pathologically-accurate highlighting (see next section)
- Automated styling updates; run
tools/update-styles.shto update CSS.
- Setup continuous integration
- Write up contributor docs
- Add setting to enable manual dark/light-mode selection
- Investigate supporting ChromeDriver for headless updates
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.
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.
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:
- Classes must be separated by a single space (
U+0020) only.
Multiple spaces or other whitespace characters won't match. classattributes cannot contain leading or trailing whitespace.- Selectors must avoid matching more qualified scope-lists.
E.g.,variable.othershould not inherit the styling applied tovariable, 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"] ){ }
- 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.
- Live preview of all TextMate scopes supported by GitHub
textmate(5)man page documenting the TextMate grammar format.- SCSS source for Primer's various colour-themes. It's not directly used by this project out of an overabundance of caution—no assumptions are ever made about the stability of GitHub's pipeline and front-end.