From 36e4577bb124aa9a57bb901fd3acc694b466d2e1 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 29 Oct 2012 23:51:23 +0100 Subject: [PATCH 1/6] Add Sass/Scss syntax --- components/prism-sass.js | 89 ++++++++++++++++++++++++++++++++++++ components/prism-sass.min.js | 5 ++ 2 files changed, 94 insertions(+) create mode 100644 components/prism-sass.js create mode 100644 components/prism-sass.min.js diff --git a/components/prism-sass.js b/components/prism-sass.js new file mode 100644 index 0000000000..f41600878d --- /dev/null +++ b/components/prism-sass.js @@ -0,0 +1,89 @@ +Prism.fn = Prism.fn || {}; + +// Taken from Dabblet source & renamed +Prism.fn.createRegExp = function(str, replacements, flags) { + for(var id in replacements) { + var replacement = replacements[id], + idRegExp = RegExp('{{' + id + '}}', 'gi'); + + if(replacement.source) { + replacement = replacement.source.replace(/^\^|\$$/g, ''); + } + + // Don't add extra parentheses if they already exist + str = str.replace(RegExp('\\(' + idRegExp.source + '\\)', 'gi'), '(' + replacement + ')'); + + str = str.replace(idRegExp, '(?:' + replacement + ')'); + } + + return RegExp(str, flags); +}; + +Prism.regExp = Prism.regExp || {}; + +Prism.regExp.number = /-?\d*\.?\d+/; + +Prism.languages.sass = Prism.languages.scss = { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g, + lookbehind: true + }, + + 'control': /@(if|else if|else|for|each|while)/i, + 'directive': /@(import|extend|debug|warn)/i, + 'keyword': /&|@(mixin|include|function|return)/i, + + 'atrule': /@[\w-]+?(?=(\s+.+)?(\s*{|\s*;))/gi, + //'url': /url\((["']?).*?\1\)/gi, + 'string': /("|')(\\?.)*?\1/g, + 'url': /([-a-z]+-)*url(?=\()/gi, // compassified + + 'placeholder': /%[-_\w]+/i, + 'variable': /\$[-_\w]+/i, + + 'property': /(\b|\B)[a-z-]+(?=\s*:)/ig, + + 'important': /\B!important\b/gi, + 'statement': /\B!(default|optional)\b/gi, + + 'boolean': /\b(true|false)\b/g, + 'null': /\b(null)\b/g, + 'number': /\b-?(0x)?(\d*\.?\d+|([\da-f]{3}){1,2})(?=(ddpx|px|pt|cm|mm|in|em|ex|pc)|\b)/g, + + // sass short mixin declaration + 'mixin': /(^|\\n)\\s*=.*/g, + 'mixin': /(^|\\n)\\s*\\+.*/g, + + // specific css values (taken from dabblet source) + 'gradient': /\b(repeating-)?(linear|radial)-gradient\(((rgb|hsl)a?\(.+?\)|[^\)])+\)/gi, + 'abslength': Prism.fn.createRegExp('(\\b|\\B){{number}}{{unit}}\\b', { + number: Prism.regExp.number, + unit: /(cm|mm|in|pt|pc|px)/ + }, 'gi'), + 'easing': Prism.fn.createRegExp('\\b{{bezier}}\\B|\\b{{keyword}}(?=\\s|;|\\}|$)', { + bezier: Prism.fn.createRegExp('cubic-bezier\\(({{number}},\\s*){3}{{number}}\\)', { + number: Prism.regExp.number + }), + keyword: /linear|ease(-in)?(-out)?/ + }, 'gi'), + 'time': Prism.fn.createRegExp('(\\b|\\B){{number}}m?s\\b', { + number: Prism.regExp.number + }, 'gi'), + 'angle': Prism.fn.createRegExp('(\\b|\\B){{number}}(deg|g?rad|turn)\\b', { + number: Prism.regExp.number + }, 'gi'), + 'fontfamily': /(("|')[\w\s]+\2,\s*|\w+,\s*)*(sans-serif|serif|monospace|cursive|fantasy)\b/gi, + + 'entity': /\\[\da-f]{1,8}/gi, + + //'selector-id': /#(\\w|-|_)+/g, + //'selector-class': /\\.(\\w|-|_)+/g, + 'selector': /[^;\{\}\(\)\s][^;\{\}\(\)]*(?=\s*\{)/g, + + 'operator': /\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g, + + 'unit': /\b(ddpx|px|pt|cm|mm|in|em|ex|pc)\b|%/i, + + 'ignore': /&(lt|gt|amp);/gi, + 'punctuation': /[\{\}\(\);:,\.#]/g +}; diff --git a/components/prism-sass.min.js b/components/prism-sass.min.js new file mode 100644 index 0000000000..5b6856080c --- /dev/null +++ b/components/prism-sass.min.js @@ -0,0 +1,5 @@ +Prism.fn=Prism.fn||{};Prism.fn.createRegExp=function(a,c,f){for(var d in c){var b=c[d],e=RegExp("{{"+d+"}}","gi");b.source&&(b=b.source.replace(/^\^|\$$/g,""));a=a.replace(RegExp("\\("+e.source+"\\)","gi"),"("+b+")");a=a.replace(e,"(?:"+b+")")}return RegExp(a,f)};Prism.regExp=Prism.regExp||{};Prism.regExp.number=/-?\d*\.?\d+/; +Prism.languages.sass=Prism.languages.scss={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},control:/@(if|else if|else|for|each|while)/i,directive:/@(import|extend|debug|warn)/i,keyword:/&|@(mixin|include|function|return)/i,atrule:/@[\w-]+?(?=(\s+.+)?(\s*{|\s*;))/gi,string:/("|')(\\?.)*?\1/g,url:/([-a-z]+-)*url(?=\()/gi,placeholder:/%[-_\w]+/i,variable:/\$[-_\w]+/i,property:/(\b|\B)[a-z-]+(?=\s*:)/ig,important:/\B!important\b/gi,statement:/\B!(default|optional)\b/gi, +"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,number:/\b-?(0x)?(\d*\.?\d+|([\da-f]{3}){1,2})(?=(ddpx|px|pt|cm|mm|in|em|ex|pc)|\b)/g,mixin:/(^|\\n)\\s*=.*/g,mixin:/(^|\\n)\\s*\\+.*/g,gradient:/\b(repeating-)?(linear|radial)-gradient\(((rgb|hsl)a?\(.+?\)|[^\)])+\)/gi,abslength:Prism.fn.createRegExp("(\\b|\\B){{number}}{{unit}}\\b",{number:Prism.regExp.number,unit:/(cm|mm|in|pt|pc|px)/},"gi"),easing:Prism.fn.createRegExp("\\b{{bezier}}\\B|\\b{{keyword}}(?=\\s|;|\\}|$)",{bezier:Prism.fn.createRegExp("cubic-bezier\\(({{number}},\\s*){3}{{number}}\\)", +{number:Prism.regExp.number}),keyword:/linear|ease(-in)?(-out)?/},"gi"),time:Prism.fn.createRegExp("(\\b|\\B){{number}}m?s\\b",{number:Prism.regExp.number},"gi"),angle:Prism.fn.createRegExp("(\\b|\\B){{number}}(deg|g?rad|turn)\\b",{number:Prism.regExp.number},"gi"),fontfamily:/(("|')[\w\s]+\2,\s*|\w+,\s*)*(sans-serif|serif|monospace|cursive|fantasy)\b/gi,entity:/\\[\da-f]{1,8}/gi,selector:/[^;\{\}\(\)\s][^;\{\}\(\)]*(?=\s*\{)/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g,unit:/\b(ddpx|px|pt|cm|mm|in|em|ex|pc)\b|%/i, +ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\}\(\);:,\.#]/g}; \ No newline at end of file From 84cb9f4ed11c3f9f868b7838600707187c414106 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 29 Oct 2012 23:51:40 +0100 Subject: [PATCH 2/6] Add Sass/Scss examples --- examples.html | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/examples.html b/examples.html index 9094064dc0..b51c36f6c8 100644 --- a/examples.html +++ b/examples.html @@ -295,6 +295,91 @@

Simple class example

As you can notice String keyword is not highlighted because it's not a Java language keyword (cf. Java Language Keywords). The main reason is that String is not a primitive type such as int but a class type like Integer.

+
+

Sass (& Scss)

+ +

Comments

+
// This is a simple one line comment
+ +

Variables

+
$var: value;
+$bool: true;
+$nullValue: null;
+	
+ +

Directives

+
@import "compass";
+
+.class {
+	@extend %placeholder;
+}
+
+@debug $var;
+
+@warn "This is a Warning in the console";
+ +

Keywords

+
&.parentSelector {}
+
+@mixin super-mixin() {
+	@include great-mixin();
+}
+
+@function fn() {
+	@return value;
+}
+	
+ +

URLs Functions (Compass Style)

+
selector {
+	background: image-url('stuff.png');
+}
+
+@font-face {
+	src: font-url('font.woff');
+}
+	
+ +

Statements

+
$var: value !default;
+
+selector {
+	@extend %stuff !optional;
+}
+	
+ +

Controls

+
@if(true) {
+	// ...
+}
+@else if {
+	// ...
+}
+@else {
+	// ...
+}
+
+@for $i from 1 through 3 { {
+	// ...
+}
+
+@each $animal in puma, sea-slug, egret, salamander {
+	// ...
+}
+
+$i: 2;
+@while $i > 0 {
+  //...
+  $i: $i - 1;
+}
+
+ +

+ This Sass/Scss syntax can be used just for CSS. It add some stuffs directly related to CSS like highlight of some functions (like gradients, cube-bezier), keywords & more (unit, operator, selector, hexa color, angle, time, font family). + Highlight renders better with an appropriate theme (to customize specific classes). +

+
+

Known failures (JavaScript)

There are certain edge cases where Prism will fail. From bc2fac7c9688151a572a70ee4f4106a3092241e7 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 29 Oct 2012 23:54:00 +0100 Subject: [PATCH 3/6] Add Sass/Scss support to the website & downloader --- code.js | 1 + 1 file changed, 1 insertion(+) diff --git a/code.js b/code.js index 723a74c80e..25a81eb76c 100644 --- a/code.js +++ b/code.js @@ -28,6 +28,7 @@ var components = { 'css': 'CSS', 'javascript': 'JavaScript', 'java' : 'Java', + 'sass' : 'Sass (and Scss)', }, plugins: { meta: { From feadeff49dbecd0e5f137ed200698c20e2828f8d Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Sat, 8 Dec 2012 09:29:16 +0100 Subject: [PATCH 4/6] Rewrote Sass (scss) from scratch --- components/prism-sass.js | 89 ------------------------------------ components/prism-sass.min.js | 5 -- components/prism-scss.js | 32 +++++++++++++ components/prism-scss.min.js | 2 + examples.html | 79 ++++++++++++++++++++++++++------ prism.js | 37 +++++++++++++++ 6 files changed, 135 insertions(+), 109 deletions(-) delete mode 100644 components/prism-sass.js delete mode 100644 components/prism-sass.min.js create mode 100644 components/prism-scss.js create mode 100644 components/prism-scss.min.js diff --git a/components/prism-sass.js b/components/prism-sass.js deleted file mode 100644 index f41600878d..0000000000 --- a/components/prism-sass.js +++ /dev/null @@ -1,89 +0,0 @@ -Prism.fn = Prism.fn || {}; - -// Taken from Dabblet source & renamed -Prism.fn.createRegExp = function(str, replacements, flags) { - for(var id in replacements) { - var replacement = replacements[id], - idRegExp = RegExp('{{' + id + '}}', 'gi'); - - if(replacement.source) { - replacement = replacement.source.replace(/^\^|\$$/g, ''); - } - - // Don't add extra parentheses if they already exist - str = str.replace(RegExp('\\(' + idRegExp.source + '\\)', 'gi'), '(' + replacement + ')'); - - str = str.replace(idRegExp, '(?:' + replacement + ')'); - } - - return RegExp(str, flags); -}; - -Prism.regExp = Prism.regExp || {}; - -Prism.regExp.number = /-?\d*\.?\d+/; - -Prism.languages.sass = Prism.languages.scss = { - 'comment': { - pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g, - lookbehind: true - }, - - 'control': /@(if|else if|else|for|each|while)/i, - 'directive': /@(import|extend|debug|warn)/i, - 'keyword': /&|@(mixin|include|function|return)/i, - - 'atrule': /@[\w-]+?(?=(\s+.+)?(\s*{|\s*;))/gi, - //'url': /url\((["']?).*?\1\)/gi, - 'string': /("|')(\\?.)*?\1/g, - 'url': /([-a-z]+-)*url(?=\()/gi, // compassified - - 'placeholder': /%[-_\w]+/i, - 'variable': /\$[-_\w]+/i, - - 'property': /(\b|\B)[a-z-]+(?=\s*:)/ig, - - 'important': /\B!important\b/gi, - 'statement': /\B!(default|optional)\b/gi, - - 'boolean': /\b(true|false)\b/g, - 'null': /\b(null)\b/g, - 'number': /\b-?(0x)?(\d*\.?\d+|([\da-f]{3}){1,2})(?=(ddpx|px|pt|cm|mm|in|em|ex|pc)|\b)/g, - - // sass short mixin declaration - 'mixin': /(^|\\n)\\s*=.*/g, - 'mixin': /(^|\\n)\\s*\\+.*/g, - - // specific css values (taken from dabblet source) - 'gradient': /\b(repeating-)?(linear|radial)-gradient\(((rgb|hsl)a?\(.+?\)|[^\)])+\)/gi, - 'abslength': Prism.fn.createRegExp('(\\b|\\B){{number}}{{unit}}\\b', { - number: Prism.regExp.number, - unit: /(cm|mm|in|pt|pc|px)/ - }, 'gi'), - 'easing': Prism.fn.createRegExp('\\b{{bezier}}\\B|\\b{{keyword}}(?=\\s|;|\\}|$)', { - bezier: Prism.fn.createRegExp('cubic-bezier\\(({{number}},\\s*){3}{{number}}\\)', { - number: Prism.regExp.number - }), - keyword: /linear|ease(-in)?(-out)?/ - }, 'gi'), - 'time': Prism.fn.createRegExp('(\\b|\\B){{number}}m?s\\b', { - number: Prism.regExp.number - }, 'gi'), - 'angle': Prism.fn.createRegExp('(\\b|\\B){{number}}(deg|g?rad|turn)\\b', { - number: Prism.regExp.number - }, 'gi'), - 'fontfamily': /(("|')[\w\s]+\2,\s*|\w+,\s*)*(sans-serif|serif|monospace|cursive|fantasy)\b/gi, - - 'entity': /\\[\da-f]{1,8}/gi, - - //'selector-id': /#(\\w|-|_)+/g, - //'selector-class': /\\.(\\w|-|_)+/g, - 'selector': /[^;\{\}\(\)\s][^;\{\}\(\)]*(?=\s*\{)/g, - - 'operator': /\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g, - - 'unit': /\b(ddpx|px|pt|cm|mm|in|em|ex|pc)\b|%/i, - - 'ignore': /&(lt|gt|amp);/gi, - 'punctuation': /[\{\}\(\);:,\.#]/g -}; diff --git a/components/prism-sass.min.js b/components/prism-sass.min.js deleted file mode 100644 index 5b6856080c..0000000000 --- a/components/prism-sass.min.js +++ /dev/null @@ -1,5 +0,0 @@ -Prism.fn=Prism.fn||{};Prism.fn.createRegExp=function(a,c,f){for(var d in c){var b=c[d],e=RegExp("{{"+d+"}}","gi");b.source&&(b=b.source.replace(/^\^|\$$/g,""));a=a.replace(RegExp("\\("+e.source+"\\)","gi"),"("+b+")");a=a.replace(e,"(?:"+b+")")}return RegExp(a,f)};Prism.regExp=Prism.regExp||{};Prism.regExp.number=/-?\d*\.?\d+/; -Prism.languages.sass=Prism.languages.scss={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},control:/@(if|else if|else|for|each|while)/i,directive:/@(import|extend|debug|warn)/i,keyword:/&|@(mixin|include|function|return)/i,atrule:/@[\w-]+?(?=(\s+.+)?(\s*{|\s*;))/gi,string:/("|')(\\?.)*?\1/g,url:/([-a-z]+-)*url(?=\()/gi,placeholder:/%[-_\w]+/i,variable:/\$[-_\w]+/i,property:/(\b|\B)[a-z-]+(?=\s*:)/ig,important:/\B!important\b/gi,statement:/\B!(default|optional)\b/gi, -"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,number:/\b-?(0x)?(\d*\.?\d+|([\da-f]{3}){1,2})(?=(ddpx|px|pt|cm|mm|in|em|ex|pc)|\b)/g,mixin:/(^|\\n)\\s*=.*/g,mixin:/(^|\\n)\\s*\\+.*/g,gradient:/\b(repeating-)?(linear|radial)-gradient\(((rgb|hsl)a?\(.+?\)|[^\)])+\)/gi,abslength:Prism.fn.createRegExp("(\\b|\\B){{number}}{{unit}}\\b",{number:Prism.regExp.number,unit:/(cm|mm|in|pt|pc|px)/},"gi"),easing:Prism.fn.createRegExp("\\b{{bezier}}\\B|\\b{{keyword}}(?=\\s|;|\\}|$)",{bezier:Prism.fn.createRegExp("cubic-bezier\\(({{number}},\\s*){3}{{number}}\\)", -{number:Prism.regExp.number}),keyword:/linear|ease(-in)?(-out)?/},"gi"),time:Prism.fn.createRegExp("(\\b|\\B){{number}}m?s\\b",{number:Prism.regExp.number},"gi"),angle:Prism.fn.createRegExp("(\\b|\\B){{number}}(deg|g?rad|turn)\\b",{number:Prism.regExp.number},"gi"),fontfamily:/(("|')[\w\s]+\2,\s*|\w+,\s*)*(sans-serif|serif|monospace|cursive|fantasy)\b/gi,entity:/\\[\da-f]{1,8}/gi,selector:/[^;\{\}\(\)\s][^;\{\}\(\)]*(?=\s*\{)/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g,unit:/\b(ddpx|px|pt|cm|mm|in|em|ex|pc)\b|%/i, -ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\}\(\);:,\.#]/g}; \ No newline at end of file diff --git a/components/prism-scss.js b/components/prism-scss.js new file mode 100644 index 0000000000..42e18866e9 --- /dev/null +++ b/components/prism-scss.js @@ -0,0 +1,32 @@ +Prism.languages.scss = Prism.languages.extend('css', { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g, + lookbehind: true + }, + // aturle is just the @***, not the entire rule (to highlight var & stuffs) + // + add ability to highlight number & unit for media queries + 'atrule': /@[\w-]+(?=\s+(\(|\{|;))/gi, + // url, compassified + 'url': /([-a-z]+-)*url(?=\()/gi, + // CSS selector regex is not appropriate for Sass + // since there can be lot more things (var, @ directive, nesting..) + // a selector must start at the end of a property or after a brace (end of other rules or nesting) + // it can contain some caracters that aren't used for defining rules or end of selector, & (parent selector), or interpolated variable + // the end of a selector is found when there is no rules in it ( {} or {\s}) or if there is a property (because an interpolated var + // can "pass" as a selector- e.g: proper#{$erty}) + // this one was ard to do, so please be careful if you edit this one :) + 'selector': /([^@;:\{\}\(\)]?([^@;:\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm +}); + +Prism.languages.insertBefore('scss', 'atrule', { + 'keyword': /@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i +}); + +Prism.languages.insertBefore('scss', 'ignore', { + 'placeholder': /%[-_\w]+/i, + //'variable': /\$[-_\w]+/i, + 'statement': /\B!(default|optional)\b/gi, + 'boolean': /\b(true|false)\b/g, + 'null': /\b(null)\b/g, + 'operator': /\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g +}); \ No newline at end of file diff --git a/components/prism-scss.min.js b/components/prism-scss.min.js new file mode 100644 index 0000000000..5c9e8c8439 --- /dev/null +++ b/components/prism-scss.min.js @@ -0,0 +1,2 @@ +Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},atrule:/@[\w-]+(?=\s+(\(|\{|;))/gi,url:/([-a-z]+-)*url(?=\()/gi,selector:/([^@;:\{\}\(\)]?([^@;:\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm});Prism.languages.insertBefore("scss","atrule",{keyword:/@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i}); +Prism.languages.insertBefore("scss","ignore",{placeholder:/%[-_\w]+/i,statement:/\B!(default|optional)\b/gi,"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g}); \ No newline at end of file diff --git a/examples.html b/examples.html index 71b45248c4..d2eeb8243e 100644 --- a/examples.html +++ b/examples.html @@ -303,8 +303,8 @@

Simple class example

As you can notice String keyword is not highlighted because it's not a Java language keyword (cf. Java Language Keywords). The main reason is that String is not a primitive type such as int but a class type like Integer.

-
-

Sass (& Scss)

+
+

Sass (Scss)

Comments

// This is a simple one line comment
@@ -313,7 +313,19 @@

Variables

$var: value;
 $bool: true;
 $nullValue: null;
-	
+$interpolation: -vendor-#{$var}; + +

Nesting

+
sel {
+	ector {
+		#chi,
+		ld .ren { } inline {} * {}
+	}
+	
+	&.parentSelector {
+		nested & test #{$inter}pol {}
+	}
+}

Directives

@import "compass";
@@ -327,9 +339,7 @@ 

Directives

@warn "This is a Warning in the console";

Keywords

-
&.parentSelector {}
-
-@mixin super-mixin() {
+	
@mixin super-mixin() {
 	@include great-mixin();
 }
 
@@ -345,16 +355,14 @@ 

URLs Functions (Compass Style)

@font-face { src: font-url('font.woff'); -} -
+}

Statements

$var: value !default;
 
 selector {
 	@extend %stuff !optional;
-}
-	
+}

Controls

@if(true) {
@@ -367,7 +375,7 @@ 

Controls

// ... } -@for $i from 1 through 3 { { +@for $i from 1 through 3 { // ... } @@ -378,14 +386,55 @@

Controls

$i: 2; @while $i > 0 { //... - $i: $i - 1; + $i: $i - 1; // note the operator + $i: 3 * 2 + $i % 5; +}
+ +

Scss full example

+
@import "compass";
+	
+@mixin mixin($param) {
+	@if($param==true) {
+		selector-#{$test}-stuff,
+		sel2 {
+			property: -moz-#{$param};
+			aze: rty;
+			
+			child {
+				test: $param * 3;
+				a: bcd;
+				color: #f45f55;
+			}
+		}
+	}
+	@else {
+		property: $param + #aaa;
+		test: stupid;
+	}
+}
+
+$i: 2;
+@while $i > 0 {
+	sel#{$i}: $i * 2
 }
-
+ +selector { + @media (min-width: 800px) { + stuff: $thing; + } +}

- This Sass/Scss syntax can be used just for CSS. It add some stuffs directly related to CSS like highlight of some functions (like gradients, cube-bezier), keywords & more (unit, operator, selector, hexa color, angle, time, font family). - Highlight renders better with an appropriate theme (to customize specific classes). + This Scss syntax can be used just for CSS too since regular CSS is valid Scss too. + Highlight renders better with an appropriate theme (to customize specific tokens).

+

Known issues

+
    +
  • & keyword and interpolated variables are not highlighted in selectors.
  • +
  • Some control directives parameters are parsed as selectors.
  • +
  • Does not work very well with indented Sass syntax. That's why it's just called "scss".
  • +
+

If you are good with regex, maybe you can help to improve this.

diff --git a/prism.js b/prism.js index f1940348b1..1cd17dcd7c 100644 --- a/prism.js +++ b/prism.js @@ -492,3 +492,40 @@ Prism.languages.java = Prism.languages.extend('clike', { lookbehind: true } }); + +/* ********************************************** + Begin prism-scss.js +********************************************** */ + +Prism.languages.scss = Prism.languages.extend('css', { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g, + lookbehind: true + }, + // aturle is just the @***, not the entire rule (to highlight var & stuffs) + // + add ability to highlight number & unit for media queries + 'atrule': /@[\w-]+(?=\s+(\(|\{|;))/gi, + // url, compassified + 'url': /([-a-z]+-)*url(?=\()/gi, + // CSS selector regex is not appropriate for Sass + // since there can be lot more things (var, @ directive, nesting..) + // a selector must start at the end of a property or after a brace (end of other rules or nesting) + // it can contain some caracters that aren't used for defining rules or end of selector, & (parent selector), or interpolated variable + // the end of a selector is found when there is no rules in it ( {} or {\s}) or if there is a property (because an interpolated var + // can "pass" as a selector- e.g: proper#{$erty}) + // this one was ard to do, so please be careful if you edit this one :) + 'selector': /([^@;:\{\}\(\)]?([^@;:\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm +}); + +Prism.languages.insertBefore('scss', 'atrule', { + 'keyword': /@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i +}); + +Prism.languages.insertBefore('scss', 'ignore', { + 'placeholder': /%[-_\w]+/i, + //'variable': /\$[-_\w]+/i, + 'statement': /\B!(default|optional)\b/gi, + 'boolean': /\b(true|false)\b/g, + 'null': /\b(null)\b/g, + 'operator': /\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g +}); From a484dedd3cce9e6f6632c32b82912f55e2c9ebf5 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 10 Dec 2012 07:58:10 +0100 Subject: [PATCH 5/6] Fix variable highlight (was commented, oups!) --- components/prism-scss.js | 4 ++-- components/prism-scss.min.js | 3 +-- prism.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/components/prism-scss.js b/components/prism-scss.js index 42e18866e9..afa13d8380 100644 --- a/components/prism-scss.js +++ b/components/prism-scss.js @@ -24,9 +24,9 @@ Prism.languages.insertBefore('scss', 'atrule', { Prism.languages.insertBefore('scss', 'ignore', { 'placeholder': /%[-_\w]+/i, - //'variable': /\$[-_\w]+/i, + 'variable': /\$[-_\w]+/i, 'statement': /\B!(default|optional)\b/gi, 'boolean': /\b(true|false)\b/g, 'null': /\b(null)\b/g, 'operator': /\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g -}); \ No newline at end of file +}); diff --git a/components/prism-scss.min.js b/components/prism-scss.min.js index 5c9e8c8439..d6ff8fb401 100644 --- a/components/prism-scss.min.js +++ b/components/prism-scss.min.js @@ -1,2 +1 @@ -Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},atrule:/@[\w-]+(?=\s+(\(|\{|;))/gi,url:/([-a-z]+-)*url(?=\()/gi,selector:/([^@;:\{\}\(\)]?([^@;:\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm});Prism.languages.insertBefore("scss","atrule",{keyword:/@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i}); -Prism.languages.insertBefore("scss","ignore",{placeholder:/%[-_\w]+/i,statement:/\B!(default|optional)\b/gi,"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g}); \ No newline at end of file +Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},atrule:/@[\w-]+(?=\s+(\(|\{|;))/gi,url:/([-a-z]+-)*url(?=\()/gi,selector:/([^@;:\{\}\(\)]?([^@;:\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm});Prism.languages.insertBefore("scss","atrule",{keyword:/@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i});Prism.languages.insertBefore("scss","ignore",{placeholder:/%[-_\w]+/i,variable:/\$[-_\w]+/i,statement:/\B!(default|optional)\b/gi,"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g}); \ No newline at end of file diff --git a/prism.js b/prism.js index 1cd17dcd7c..b6b356c62e 100644 --- a/prism.js +++ b/prism.js @@ -523,7 +523,7 @@ Prism.languages.insertBefore('scss', 'atrule', { Prism.languages.insertBefore('scss', 'ignore', { 'placeholder': /%[-_\w]+/i, - //'variable': /\$[-_\w]+/i, + 'variable': /\$[-_\w]+/i, 'statement': /\B!(default|optional)\b/gi, 'boolean': /\b(true|false)\b/g, 'null': /\b(null)\b/g, From a9e4656b0dcaeb7d3312efd5aa549b809804197d Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 10 Dec 2012 08:04:15 +0100 Subject: [PATCH 6/6] Fix variable parsing position. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I don't really know what I did. Too obsessed by the selector regex maybe… --- components/prism-scss.js | 5 ++++- components/prism-scss.min.js | 2 +- prism.js | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/components/prism-scss.js b/components/prism-scss.js index afa13d8380..c51c55c317 100644 --- a/components/prism-scss.js +++ b/components/prism-scss.js @@ -22,9 +22,12 @@ Prism.languages.insertBefore('scss', 'atrule', { 'keyword': /@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i }); +Prism.languages.insertBefore('scss', 'property', { + 'variable': /\$[-_\w]+/i +}); + Prism.languages.insertBefore('scss', 'ignore', { 'placeholder': /%[-_\w]+/i, - 'variable': /\$[-_\w]+/i, 'statement': /\B!(default|optional)\b/gi, 'boolean': /\b(true|false)\b/g, 'null': /\b(null)\b/g, diff --git a/components/prism-scss.min.js b/components/prism-scss.min.js index d6ff8fb401..058dbc87c6 100644 --- a/components/prism-scss.min.js +++ b/components/prism-scss.min.js @@ -1 +1 @@ -Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},atrule:/@[\w-]+(?=\s+(\(|\{|;))/gi,url:/([-a-z]+-)*url(?=\()/gi,selector:/([^@;:\{\}\(\)]?([^@;:\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm});Prism.languages.insertBefore("scss","atrule",{keyword:/@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i});Prism.languages.insertBefore("scss","ignore",{placeholder:/%[-_\w]+/i,variable:/\$[-_\w]+/i,statement:/\B!(default|optional)\b/gi,"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g}); \ No newline at end of file +Prism.languages.java=Prism.languages.extend("clike",{keyword:/\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/g,number:/\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+[e]?[\d]*[df]\b|\W\d*\.?\d+\b/gi,operator:{pattern:/([^\.]|^)([-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\/|%|\^|(<){2}|($gt;){2,3}|:|~)/g,lookbehind:!0}});Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},atrule:/@[\w-]+(?=\s+(\(|\{|;))/gi,url:/([-a-z]+-)*url(?=\()/gi,selector:/([^@;:\{\}\(\)]?([^@;:\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm});Prism.languages.insertBefore("scss","atrule",{keyword:/@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i});Prism.languages.insertBefore("scss","property",{variable:/\$[-_\w]+/i});Prism.languages.insertBefore("scss","ignore",{placeholder:/%[-_\w]+/i,statement:/\B!(default|optional)\b/gi,"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g}); \ No newline at end of file diff --git a/prism.js b/prism.js index b6b356c62e..106d29e1ec 100644 --- a/prism.js +++ b/prism.js @@ -521,9 +521,12 @@ Prism.languages.insertBefore('scss', 'atrule', { 'keyword': /@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i }); +Prism.languages.insertBefore('scss', 'property', { + 'variable': /\$[-_\w]+/i +}); + Prism.languages.insertBefore('scss', 'ignore', { 'placeholder': /%[-_\w]+/i, - 'variable': /\$[-_\w]+/i, 'statement': /\B!(default|optional)\b/gi, 'boolean': /\b(true|false)\b/g, 'null': /\b(null)\b/g,