Commit 472515ec authored by Jeffery To's avatar Jeffery To
Browse files

scss.lang, less.lang: Add new languages

SCSS (a newer syntax of Sass[1]) and Less[2] are two popular
preprocessor style sheet languages that are interpreted or compiled into
CSS. This adds language definitions for these two languages.

This also depends on the extensibility changes in !1.

[1] http://sass-lang.com/
[2] http://lesscss.org/
parent a8c4ef09
......@@ -65,6 +65,7 @@ LANGUAGES = \
julia.lang \
kotlin.lang \
latex.lang \
less.lang \
lex.lang \
libtool.lang \
llvm.lang \
......@@ -110,6 +111,7 @@ LANGUAGES = \
scala.lang \
scheme.lang \
scilab.lang \
scss.lang \
sh.lang \
sml.lang \
sparql.lang \
......
This diff is collapsed.
This diff is collapsed.
......@@ -68,6 +68,7 @@ data/language-specs/json.lang
data/language-specs/julia.lang
data/language-specs/kotlin.lang
data/language-specs/latex.lang
data/language-specs/less.lang
data/language-specs/lex.lang
data/language-specs/libtool.lang
data/language-specs/llvm.lang
......@@ -113,6 +114,7 @@ data/language-specs/rust.lang
data/language-specs/scala.lang
data/language-specs/scheme.lang
data/language-specs/scilab.lang
data/language-specs/scss.lang
data/language-specs/sh.lang
data/language-specs/sml.lang
data/language-specs/sparql.lang
......
/*
* nesting
*/
#header {
width: 300px;
.navigation {
font-size: 12px;
}
@media (min-width: 768px) {
width: 600px;
@media (min-resolution: 192dpi) {
background-image: url(/img/retina2x.png);
}
}
}
/*
* parent selector
*/
.component {
&:hover {
text-decoration: underline;
}
// compound selector
&__element,
&--modifier {
border: 1px;
}
// multiple &
& + & {
color: red;
}
// changing selector order
body.firefox & {
font-weight: normal;
}
}
/*
* variables, data types
*/
// assignment
@number: 5em;
@double-quoted-string: "foo";
@single-quoted-string: 'bar';
@double-quoted-escape-string: ~"foo";
@single-quoted-escape-string: ~'bar';
@not-quoted-string: baz;
@spaces-list: 1px 2px 3px 4px;
@commas-list: arial, some-other-arial, sans-serif;
@color: #fe57a1;
@detached-ruleset: {
color: red;
div {
color: blue;
}
};
#main {
// property value
width: @width;
// variable reference
color: @@color-variable-name;
// property variable
background-color: $color;
// use detached ruleset
@detached-ruleset(); // parentheses required
}
// media type, feature test
@import "foo" @type and @feature-test, (@feature-test-content);
@media @type and @feature-test, (@feature-test-content) {
width: 700px;
}
// font feature value
@font-feature-values Font One {
@styleset {
nice-style: @value;
}
}
// @keyframes name
@keyframes @myanim {
from { width: 0; }
to { width: 100%; }
}
/*
* cases where Less doesn't currently accept variables (as of Less 3.0.0)
* but may be still be incidentally highlighted
*/
// font feature values font name
@font-feature-values @fontname {
@styleset {
nice-style: 12;
}
}
// @namespace name
@namespace @name url('http://www.w3.org/2000/svg');
// @page custom name, pseudo-page
@page @name {
margin: 0;
@left-top {
content: '';
}
}
/*
* variable interpolation
*/
// selector
@{hash-id},
#@{id},
#i@{d},
@{whole-class},
.part-@{class}-fragment,
@{div},
d@{i}v,
[@{attr}=@{value}],
[@{attr-selector-content}],
@{attr-selector},
@{selection},
::se@{lect}ion,
@{hover},
:ho@{v}er,
@{lang-fr},
:la@{ng}(fr),
:lang(@{fr}),
:nth-child(@{expr}),
:not(@{div}) {
// property name
@{font}: serif;
background-@{image}: none;
border-@{bottom}-width: 0;
// inside strings
content: "@{var}";
content: '@{var}';
// nested interpolations
content: "@{@{nested}-variable}";
}
// font feature type, custom name
@font-feature-values Font One {
@{type} {
@{name}: 12;
}
}
// inside @import url()
@import url("http://fonts.googleapis.com/css?family=@{family}");
// inside @import string
@import "http://fonts.googleapis.com/css?family=@{family}";
// @keyframes selectors
@keyframes myanim {
@{from} { width: 0; }
@{to} { width: 100%; }
}
// @page margin box type
@page toc, :first {
margin: 0;
@{margin-box-type} {
content: '';
}
}
/*
* operations
*/
body {
width: (1px + (2em - 3rem)) * (4 / 5vh);
// unary negation
z-index: -@z-index;
margin-bottom: -(@base * 2);
}
/*
* functions
*/
body {
// Less string format function
content: %("1 plus 2 is %d", 1 + 2);
// single line comments not parsed inside url()
background: url(http://example.com/styles.css);
// semicolons separators
color: hsl(90; 100%; 50%);
}
/*
* extend
*/
// attached to selector
#main:extend(.card-style),
.sidebar :extend(div pre) {
color: blue;
}
#main {
// inside ruleset
&:extend(#board:nth-child(2n+3));
// all keyword
&:extend(div ~ .inline[name="foo"] all);
}
/*
* property merge
*/
code {
// with comma
box-shadow+: 0 0 20px black;
// with space
transform+_: scale(2);
}
/*
* mixins
*/
// mixin definition
.black() {
color: black;
}
// with parameters
.box(@margin, @padding) { // comma separated
margin: @margin;
padding: @padding;
}
.box(@margin; @padding) { // semicolon separated
margin: @margin;
padding: @padding;
}
.box(@margin: 10px; @padding: 10px) { // default parameters
margin: @margin;
padding: @padding;
}
// @arguments
.box-shadow(@x: 0; @y: 0; @blur: 1px; @color: #000) {
box-shadow: @arguments;
}
// variable arguments
.mixin(...) {} // 0 or more arguments
.mixin(@a; ...) {} // at least 1 argument
.mixin(@a; @rest...) {} // remaining arguments bound to variable
// with pattern
.mixin(dark; 5px) {}
.mixin(light; #000) {}
// mixin call
#main {
// existing styles
#header;
.card-style;
// existing styles with parentheses (optional),
// or mixins with parentheses and no required parameters
#header();
.card-style();
// namespaced styles
#outer > .inner;
#outer .inner;
#outer.inner;
// important modifier
#header !important;
.card-style() !important;
#outer > .inner !important;
// with parameters
.box(20px, 10px); // comma separated
.box(20px; 10px); // semicolon separated
.box(@padding: 10px; @margin: 20px); // named parameters
.box(@list...); // expands values in @list as arguments
.mixin({ // detached ruleset
color: red;
div {
color: blue;
}
});
// with pattern
.mixin(dark; 5px);
.mixin(light; #000);
}
/*
* guards
*/
// regular styles
button when (@my-option = true) {
color: white;
}
& when (@my-option = true) {
button {
color: white;
}
a {
color: blue;
}
}
// namespace
#namespace when (@mode = huge) {
.mixin() {}
}
#namespace {
.mixin() when (@mode = huge) {}
}
// mixin
.mixin (@a) when (lightness(@a) >= 50%) {
background-color: black;
}
.mixin (@a) when (lightness(@a) < 50%) {
background-color: white;
}
// comparison operators, logical operators
.mixin (@a) when (@a >= 0) and (@a =< 0) {}
.mixin (@a) when (@a < 0) or (@a > 0) {}
.mixin (@a) when (@a < 0), (@a > 0) {}
.mixin (@a) when not (@a = 0) {}
// true keyword
.mixin (@a) when (@a) {}
.mixin (@a) when (@a = true) {}
/*
* at-rules
*/
// @import
@import "@{themes}/tidal-wave.less";
@import (optional, reference) "foo.less" screen and (orientation: landscape), print; // import options
// @plugin
@plugin 'my-plugin';
@plugin (options) 'my-plugin'; // plugin options
// @plugin function call
my-plugin();
div {
my-plugin(red; 10px);
}
/*
* test cases
*/
.declarations-or-selectors {
// declarations
display:block;
font-family:arial;
@{property}:block;
// selectors
input:focus {
opacity: 0.5;
}
div:nth-child(2n+1) {
background-color: gray;
}
@{selector}:focus {
color: blue;
}
a:@{state} {
color: blue;
}
}
// from file.css
/*
* general
*/
/* whitespace */
#main
{
color:aqua;
float: left!important;
margin : 0 ;
width
:
100%
!
important
;
}
/* case insensitivity */
Body {
FONT: 12Px/16pX iTaLiC sans-SERIF;
}
/*
* selectors
*/
/* simple selectors */
#testID, /* id */
.someclass, /* class */
div, /* type */
*, /* universal */
[lang|="zh"] { /* attribute */
color: black;
}
/* combinators */
header + main, /* adjacent sibling */
li ~ li, /* general sibling */
ul > li, /* child */
ul ul { /* descendant */
color: blue;
}
/* pseudo-elements */
:after,
::after,
::placeholder,
::selection {
color: green;
}
/* pseudo-classes */
:hover,
:required,
:lang(fr),
:not(div#sidebar.fancy),
:nth-child(n+1),
:nth-last-child(-2n - 30),
:nth-of-type(5),
:nth-last-of-type(even) {
color: yellow;
}
/* pseudo-classes with invalid arguments */
:not(div:before), /* pseudo-element */
:not(input::placeholder), /* pseudo-element */
:not(p:not(:lang(en))), /* nested :not */
:nth-child(1.2n), /* non-integer */
:nth-child(.5), /* non-integer */
:nth-child(n+-1) { /* number sign */
color: red;
}
/* namespace qualified */
a, /* type in default namespace */
svg|a, /* type in specified namespace */
|a, /* type in no namespace */
*|a, /* type in all namespaces (including no namespace) */
svg|*, /* universal */
svg|[fill] { /* attribute */
color: white;
}
/*
* basic data types
*/
#main {
/* angle */
transform: rotate(+33.333e+3deg);
/* color */
color: #f00;
color: #f00f; /* #rgba */
color: #ff0000;
color: #ff0000ff; /* #rrggbbaa */
color: red;
color: lightgoldenrodyellow;
color: rebeccapurple;
color: currentColor;
/* freqency (not currently used for any property) */
content: 44.1kHz;
/* integer */
z-index: +255;
z-index: -1;
/* length */
width: 10px;
width: 10.5rem;
width: -10e-2vw;
/* number */
opacity: .5;
opacity: 0.3333;
opacity: 1;
opacity: 2e-34;
/* percentage */
width: 100%;
/* string */
content: "double quoted";
content: 'single quoted';
/* time */
transition-duration: .4s;
transition-duration: 400ms;
/* unicode range */
unicode-range: U+0025-00FF;
unicode-range: U+4??; /* wildcard range */
}
/* ratio */
@media (min-aspect-ratio: 16/9) {}
/* resolution */
@media (min-resolution: +2.54dpcm) {}
/*
* identifiers
*/
/* leading hyphens */
#-here.-there,
#-- .--everywhere { /* two hyphens: https://stackoverflow.com/a/30822662 */
color: blue;
}
/* non-ASCII */
#español,
#你好,
.❤♫ {
color: green;
}
/* invalid identifiers */
#1id, /* starts with digit */
.-2class { /* starts with hyphen digit */
color: maroon;
}
/*
* escaping
*/
/* selectors */
#\..\+\ space\@\>, /* special character escape */
#\E9 dition .\0000E9dition .motion_\e9motion, /* Unicode character escape */
.\e33 div, /* trailing space terminates Unicode character escape */
.\e33 div, /* extra space to denote separate tokens */
.\31 23 { /* escape leading digit of identifier */
/* property value */
content: "\E9 dition \
\"\0000E9dition\" \
\e9motion";