diff --git a/js/language/css.js b/js/language/css.js
index e3bc6f53..b5243eef 100644
--- a/js/language/css.js
+++ b/js/language/css.js
@@ -2,71 +2,429 @@
* CSS patterns
*
* @author Craig Campbell
- * @version 1.0.9
+ * @author Fabio Bucci Di Monte
+ * @version 1.1.0
*/
-Rainbow.extend('css', [
- {
- 'name': 'comment',
- 'pattern': /\/\*[\s\S]*?\*\//gm
- },
- {
- 'name': 'constant.hex-color',
- 'pattern': /#([a-f0-9]{3}|[a-f0-9]{6})(?=;|\s|,|\))/gi
- },
- {
- 'matches': {
- 1: 'constant.numeric',
- 2: 'keyword.unit'
- },
- 'pattern': /(\d+)(px|em|cm|s|%)?/g
- },
- {
- 'name': 'string',
- 'pattern': /('|")(.*?)\1/g
- },
- {
- 'name': 'support.css-property',
- 'matches': {
- 1: 'support.vendor-prefix'
- },
- 'pattern': /(-o-|-moz-|-webkit-|-ms-)?[\w-]+(?=\s?:)(?!.*\{)/g
- },
- {
- 'matches': {
+!function(){
+
+ 'use strict';
+
+ var regexes = {
+
+ /* common */
+ commonName : /(-?\w+(?:-\w+)*)/g,
+ parameters : /\((.+)\)/g,
+
+ /* reserved words / symbols */
+ atDirective : /(?:@[a-z]+)/g,
+ exception : /!important(?= *;)/g,
+ reserved : /(?:from|to(?! (?:top|bottom|right|left)))/g,
+
+ /* comments */
+ commentMulti : /\/\*[^]*?\*\//gm,
+
+ /* units */
+ unitAbsolute : /(?:p[xtc]|[cm]m|in)/g,
+ unitRelative : /(?:e[mx]|rem|ch)/g,
+ unitViewport : /(?:v(?:h|w|m(?:in|ax)))/g,
+ unitAngle : /(?:deg|g?rad|turn)/g,
+ unitTime : /(?:m?s)/g,
+ unitFrequency : /(?:k?Hz)/g,
+ unitResolution : /(?:dp(?:i|cm|px))/g,
+ unitPercentage : /%/g,
+
+ /* values */
+ valueText : /(-(?:webkit|moz|ms|o)-)\b\w+(?:-\w+)*\b/g,
+ valueString : /('|").*?\1/g,
+ valuePath : /[\w/-]+\.[a-z0-9]{3,4}\b(?!["'])/gi,
+ valueHex : /#(?:[a-f0-9]{6}|[a-f0-9]{3})\b/gi,
+ valueNumber : /(-?(?:\d*\.)?\d+)((?:p[xtc]|[cm]m|in)|(?:e[mx]|rem|ch)|(?:v(?:h|w|m(?:in|ax)))|(?:deg|g?rad|turn)|(?:m?s)|(?:k?Hz)|(?:dp(?:i|cm|px))|%)?/g,
+
+ /* css rules */
+ prefix : /-(?:webkit|moz|ms|o)-/g,
+ cssProperty : /([a-z-]+)/g,
+ cssMethod : /(-?\w+(?:-\w+)*)(\(.+\))/g,
+ cssSelector : /((?:[\w.#:()+>~\[="\] -]|,\s?|>)+)(?=\{)/g,
+
+ /* ie hacks */
+ cssPropertyWithHack : /([\*\+#_])?([a-z-]+)( *\/\*(?:\\\*)?\*\/)?(?= *:)/g,
+ hackValue : /((?:\\0|\\9|\\0\\9|\\9\\0)|!\w+?|\\0\/)(?= *[;}])/g,
+ ieHacks : /(_)|(\*|#|!.+)|(\*?\+|\+\*?)|(\\9)|(\\0\\9|\\9\\0)|(\/\*(?:\\\*)?\*\/)|(\\0\/)/g,
+
+ /* entities */
+ entityClass : /\.(?!\.)\w+(?:-\w+)*/g,
+ entityId : /#(?!#)\w+(?:-\w+)*/g,
+ entityPseudo : /::?(?!::?)[a-z-]+/g,
+ entityTag : /[a-z]+\d?(?! *:.*;)/gi,
+ entityAttribute : /\[(\w+(?:-\w+)*)=(("|')?\w+(?:-\w+)*\3)]/g,
+
+ /* siblings */
+ directChild : / ?(?:>|>) ?/g,
+ siblingGeneral : / ?~ ?/g,
+ siblingAdjacent : / ?\+ ?/g,
+
+ /* media queries */
+ mediaReserved : /\b(?:not|only|and)\b/g,
+ mediaType : /\b(?:all|aural|braille|handheld|print|projection|screen|tty|tv|embossed)\b/g,
+ mediaFeature : /(-(?:webkit|moz|ms|o)-)?\b(?:(?:(?:min|max)-)?(?:(?:device-)?(?:width|height|(?:pixel|aspect)-ratio)|color(?:-index)?|monochrome|resolution)|scan|grid|orientation)\b/g,
+ mediaExpression : /\(([^:]+)(?: *: *([^)]+))?\)/g,
+ mediaQuery : /(?:(not|only) +)?(.+)/g,
+ mediaQueryList : / *([^,\n\r]+) */g,
+ mediaQueryRule : /(@media) +(.+)(?=\{)/g
+
+ };
+
+ /********************
+ * @ DIRECTIVES
+ ********************/
+
+ var atDirective = {
+ name: 'at-directive',
+ pattern: regexes.atDirective
+ };
+
+ /********************
+ * RESERVED WORDS / SYMBOLS
+ ********************/
+
+ var reserved = {
+ name: 'reserved',
+ pattern: regexes.reserved
+ };
+
+ var exception = {
+ name: 'keyword.exception',
+ pattern: regexes.exception
+ };
+
+ var prefix = {
+ name: 'vendor-prefix',
+ pattern: regexes.prefix
+ };
+
+ /********************
+ * TYPES
+ ********************/
+
+ var unit = {
+ absolute: {
+ name: 'keyword.unit.absolute',
+ pattern: regexes.unitAbsolute
+ },
+ relative: {
+ name: 'keyword.unit.relative',
+ pattern: regexes.unitRelative
+ },
+ viewport: {
+ name: 'keyword.unit.viewport',
+ pattern: regexes.unitViewport
+ },
+ angle: {
+ name: 'keyword.unit.angle',
+ pattern: regexes.unitAngle
+ },
+ time: {
+ name: 'keyword.unit.time',
+ pattern: regexes.unitTime
+ },
+ frequency: {
+ name: 'keyword.unit.frequency',
+ pattern: regexes.unitFrequency
+ },
+ resolution: {
+ name: 'keyword.unit.resolution',
+ pattern: regexes.unitResolution
+ },
+ percentage: {
+ name: 'keyword.unit.percentage',
+ pattern: regexes.unitPercentage
+ }
+ };
+
+ var type = {
+ attribute: {
+ name: 'support.attribute-name',
+ pattern: regexes.valueText
+ },
+ text: {
+ name: 'support.text-value',
+ matches: {
+ 1: [prefix]
+ },
+ pattern: regexes.valueText
+ },
+ string: {
+ name: 'string',
+ pattern: regexes.valueString
+ },
+ path: {
+ name: 'constant.path',
+ pattern: regexes.valuePath
+ },
+ hex: {
+ name: 'constant.hex-color',
+ pattern: regexes.valueHex
+ },
+ number: {
+ name: 'constant.numeric',
+ matches: {
+ 2: [
+ unit.absolute,
+ unit.relative,
+ unit.viewport,
+ unit.angle,
+ unit.time,
+ unit.frequency,
+ unit.resolution,
+ unit.percentage
+ ]
+ },
+ pattern: regexes.valueNumber
+ }
+ };
+
+ var arr_parameters = [
+ type.number,
+ type.path,
+ type.text,
+ type.string,
+ type.hex
+ ];
+
+ /********************
+ * HACKS (css attributes)
+ ********************/
+
+ var ieHacks = {
+ name: 'hack',
+ matches: {
+ 1: 'ie-6',
+ 2: 'ie-lte7',
+ 3: 'ie-7',
+ 4: 'ie-lte9',
+ 5: 'ie-9',
+ 6: 'ie-gt6',
+ 7: 'ie-8-9'
+ },
+ pattern: regexes.ieHacks
+ };
+
+ var cssHacks = {
+ matches: {
+ 1: [ieHacks]
+ },
+ pattern: regexes.hackValue
+ };
+
+ /********************
+ * CSS PROPERTIES / METHODS
+ ********************/
+
+ var cssProperties = {
+ name: 'css-property',
+ matches: {
+ 1: [prefix]
+ },
+ pattern: regexes.cssProperty
+ };
+
+ var cssPropertiesHacked = {
+ matches: {
+ 1: [ieHacks],
+ 2: [cssProperties],
+ 3: [ieHacks]
+ },
+ pattern: regexes.cssPropertyWithHack
+ };
+
+ var cssMethods = {
+ name: 'css-method',
+ matches: {
1: [
{
- 'name': 'entity.name.sass',
- 'pattern': /&/g
- },
- {
- 'name': 'direct-descendant',
- 'pattern': />/g
- },
- {
- 'name': 'entity.name.class',
- 'pattern': /\.[\w\-_]+/g
- },
- {
- 'name': 'entity.name.id',
- 'pattern': /\#[\w\-_]+/g
- },
- {
- 'name': 'entity.name.pseudo',
- 'pattern': /:[\w\-_]+/g
- },
+ name: 'method-name',
+ matches: {
+ 1: [prefix]
+ },
+ pattern: regexes.commonName
+ }
+ ],
+ 2: [
{
- 'name': 'entity.name.tag',
- 'pattern': /\w+/g
+ name: 'method-params',
+ matches: {
+ 1: arr_parameters
+ },
+ pattern: regexes.parameters
}
]
},
- 'pattern': /([\w\ ,\n:\.\#\&\;\-_]+)(?=.*\{)/g
- },
- {
- 'matches': {
- 2: 'support.vendor-prefix',
- 3: 'support.css-value'
+ pattern: regexes.cssMethod
+ };
+
+ /********************
+ * COMMENTS
+ ********************/
+
+ var commentMultiline = {
+ name: 'comment',
+ pattern: regexes.commentMulti
+ };
+
+ /********************
+ * SELECTORS
+ ********************/
+
+ var entity = {
+ cssClass: {
+ name: 'entity.name.class',
+ pattern: regexes.entityClass
+ },
+ cssId: {
+ name: 'entity.name.id',
+ pattern: regexes.entityId
+ },
+ cssAttribute : {
+ name: 'entity.name.attribute',
+ matches: {
+ 1: [type.attribute],
+ 2: [
+ type.text,
+ type.string
+ ]
+ },
+ pattern: regexes.entityAttribute
+ },
+ cssPseudo: {
+ name: 'entity.name.pseudo',
+ pattern: regexes.entityPseudo
+ },
+ cssTag: {
+ name: 'entity.name.tag',
+ pattern: regexes.entityTag
+ }
+ };
+
+ var sibling = {
+ direct: {
+ name: 'direct-child',
+ pattern: regexes.directChild
+ },
+ general: {
+ name: 'general-sibling',
+ pattern: regexes.siblingGeneral
+ },
+ adjacent: {
+ name: 'adjacent-sibling',
+ pattern: regexes.siblingAdjacent
+ }
+ };
+
+ var arr_siblings = [
+ sibling.direct,
+ sibling.general,
+ sibling.adjacent
+ ];
+
+ var arr_commonEntities = [
+ entity.cssClass,
+ entity.cssId,
+ entity.cssTag
+ ];
+
+ var arr_entities = arr_commonEntities.concat([
+ entity.cssPseudo,
+ entity.cssAttribute
+ ]);
+
+ var cssSelectors = {
+ name: 'selector',
+ matches: {
+ 1: arr_siblings.concat([reserved]).concat(arr_entities)
+ },
+ pattern: regexes.cssSelector
+ };
+
+ /********************
+ * MEDIA QUERIES
+ * ref: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries#Pseudo-BNF_%28for_those_of_you_that_like_that_kind_of_thing%29
+ ********************/
+
+ var media = {
+ reserved: {
+ name: 'mediaquery.reserved',
+ pattern: regexes.mediaReserved
+ },
+ types: {
+ name: 'mediaquery.type',
+ pattern: regexes.mediaType
+ },
+ features: {
+ name: 'mediaquery.feature',
+ matches: {
+ 1: [prefix]
+ },
+ pattern: regexes.mediaFeature
+ }
+ };
+
+ media.expression = {
+ name: 'mediaquery.expression',
+ matches: {
+ 1: [media.features],
+ 2: arr_parameters
+ },
+ pattern: regexes.mediaExpression
+ };
+
+ media.query = {
+ name: 'mediaquery.query',
+ matches: {
+ 1: [media.reserved],
+ 2: [
+ media.reserved,
+ media.types,
+ media.expression
+ ]
+ },
+ pattern: regexes.mediaQuery
+ };
+
+ var mediaQuery = {
+ name: 'media-query',
+ matches: {
+ 1: 'at-directive',
+ 2: [
+ {
+ matches: {
+ 1: [media.query]
+ },
+ pattern: regexes.mediaQueryList
+ }
+ ]
},
- 'pattern': /(:|,)\s*(-o-|-moz-|-webkit-|-ms-)?([a-zA-Z-]*)(?=\b)(?!.*\{)/g
- }
-], true);
+ pattern: regexes.mediaQueryRule
+ };
+
+ /********************
+ * RAINBOW EXTENSION
+ ********************/
+
+ var cssSyntaxEnhanced = []
+ .concat([
+ commentMultiline,
+ exception,
+ mediaQuery,
+ atDirective,
+ cssSelectors,
+ cssPropertiesHacked,
+ cssHacks
+ ])
+ .concat(arr_parameters)
+ .concat([
+ cssMethods
+ ]);
+
+ Rainbow.extend('css', cssSyntaxEnhanced, true);
+
+}();
diff --git a/tests/language/test.css.js b/tests/language/test.css.js
index a7d473ad..c1e094d5 100644
--- a/tests/language/test.css.js
+++ b/tests/language/test.css.js
@@ -33,7 +33,7 @@ describe(language, function() {
'margin:10px 20px 5px 30px;',
- 'margin:10px 20px 5px 30px;'
+ 'margin:10px 20px 5px 30px;'
);
run(
@@ -43,7 +43,7 @@ describe(language, function() {
'margin: 1cm 2cm 1.3cm 4cm;',
- 'margin: 1cm 2cm 1.3cm 4cm;'
+ 'margin: 1cm 2cm 1.3cm 4cm;'
);
run(
@@ -53,7 +53,7 @@ describe(language, function() {
'font-size: 1.2em;',
- 'font-size: 1.2em;'
+ 'font-size: 1.2em;'
);
run(
@@ -64,8 +64,8 @@ describe(language, function() {
'width: 100%\n' +
'height: 100%',
- 'width: 100%\n' +
- 'height: 100%'
+ 'width: 100%\n' +
+ 'height: 100%'
);
run(
@@ -100,11 +100,11 @@ describe(language, function() {
' transition: color .8s ease-in;\n' +
'}',
- 'code span {\n' +
- ' -moz-transition: color .8s ease-in;\n' +
- ' -o-transition: color .8s ease-in;\n' +
- ' -webkit-transition: color .8s ease-in;\n' +
- ' transition: color .8s ease-in;\n' +
+ 'code span {\n' +
+ ' -moz-transition: color .8s ease-in;\n' +
+ ' -o-transition: color .8s ease-in;\n' +
+ ' -webkit-transition: color .8s ease-in;\n' +
+ ' transition: color .8s ease-in;\n' +
'}'
);
@@ -115,7 +115,7 @@ describe(language, function() {
'p {',
- 'p {'
+ 'p {'
);
run(
@@ -125,7 +125,7 @@ describe(language, function() {
'p.intro {',
- 'p.intro {'
+ 'p.intro {'
);
run(
@@ -135,7 +135,7 @@ describe(language, function() {
'p#intro {',
- 'p#intro {'
+ 'p#intro {'
);
run(
@@ -145,29 +145,7 @@ describe(language, function() {
'p > span {',
- 'p > span {'
- );
-
- run(
- language,
-
- 'scss',
-
- 'article {\n' +
- ' &.cool {\n' +
- ' p {\n' +
- ' margin-top: 20px;\n' +
- ' }\n' +
- ' }\n' +
- '}',
-
- 'article {\n' +
- ' &.cool {\n' +
- ' p {\n' +
- ' margin-top: 20px;\n' +
- ' }\n' +
- ' }\n' +
- '}'
+ 'p > span {'
);
run(
@@ -177,7 +155,7 @@ describe(language, function() {
'p { color: #fff; margin-top: 10px; }',
- 'p { color: #fff; margin-top: 10px; }'
+ 'p { color: #fff; margin-top: 10px; }'
);
run(
@@ -192,11 +170,11 @@ describe(language, function() {
' background: linear-gradient(#f7f7f7, #e8e8e8);\n' +
'}',
- '.gradient {\n' +
- ' background: -webkit-linear-gradient(#f7f7f7, #e8e8e8);\n' +
- ' background: -moz-linear-gradient(#f7f7f7, #e8e8e8);\n' +
- ' background: -o-linear-gradient(#f7f7f7, #e8e8e8);\n' +
- ' background: linear-gradient(#f7f7f7, #e8e8e8);\n' +
+ '.gradient {\n' +
+ ' background: -webkit-linear-gradient(#f7f7f7, #e8e8e8);\n' +
+ ' background: -moz-linear-gradient(#f7f7f7, #e8e8e8);\n' +
+ ' background: -o-linear-gradient(#f7f7f7, #e8e8e8);\n' +
+ ' background: linear-gradient(#f7f7f7, #e8e8e8);\n' +
'}'
);
@@ -212,11 +190,80 @@ describe(language, function() {
' font-weight: bold;\n' +
'}',
- '.maps-headline,\n' +
+ '.maps-headline,\n' +
'.maps-subline,\n' +
'.chart-headline,\n' +
- '.chart-subline {\n' +
- ' font-weight: bold;\n' +
+ '.chart-subline {\n' +
+ ' font-weight: bold;\n' +
'}'
);
+
+ /**
+ * IE HACKS
+ */
+
+ run(
+ language,
+
+ 'hack for ie6 only',
+
+ '_color: blue;',
+
+ '_color: blue;'
+ );
+
+ run(
+ language,
+
+ 'hack for ie6 and ie7 (aka lte7)',
+
+ '*color: blue;\n'+
+ '#color: blue;\n'+
+ 'color: blue !ie;',
+
+ '*color: blue;\n'+
+ '#color: blue;\n'+
+ 'color: blue !ie;'
+ );
+
+ run(
+ language,
+
+ 'hack for ie7+ (aka gt6)',
+
+ 'color/**/: blue;',
+
+ 'color/**/: blue;'
+ );
+
+ run(
+ language,
+
+ 'hack for ie7 and ie8',
+
+ 'color/*\\**/: blue\\9;',
+
+ 'color/*\\**/: blue\\9;'
+ );
+
+ run(
+ language,
+
+ 'hack for ie6+ (aka lte9)',
+
+ 'color: blue\\9;',
+
+ 'color: blue\\9;'
+ );
+
+ run(
+ language,
+
+ 'hack for ie8 and ie9',
+
+ 'color: blue\\0/;',
+
+ 'color: blue\\0/;'
+ );
+
});
diff --git a/tests/language/test.html.js b/tests/language/test.html.js
index 5df646f3..49461fd1 100644
--- a/tests/language/test.html.js
+++ b/tests/language/test.html.js
@@ -93,9 +93,9 @@ describe(language, function() {
'',
'<style type="text/css">\n' +
- ' body span.blah {\n' +
- ' background: #000;\n' +
- ' color: #fff;\n' +
+ ' body span.blah {\n' +
+ ' background: #000;\n' +
+ ' color: #fff;\n' +
' }\n' +
'</style>'
);
@@ -114,9 +114,9 @@ describe(language, function() {
'',
'<style>\n' +
- ' body span.blah {\n' +
- ' background: #000;\n' +
- ' color: #fff;\n' +
+ ' body span.blah {\n' +
+ ' background: #000;\n' +
+ ' color: #fff;\n' +
' }\n' +
'</style>'
);
diff --git a/themes/solarized-dark.css b/themes/solarized-dark.css
index 7f77841e..22107692 100644
--- a/themes/solarized-dark.css
+++ b/themes/solarized-dark.css
@@ -5,16 +5,18 @@
*
* @author Ethan Schoonover
* @author David Litmark
- * @version 1.0.0
+ * @author Fabio Bucci Di Monte (Additional styles for enhanced CSS syntax)
+ * @version 1.1.0
*/
pre {
background: #002b36; /* base03 */
- word-wrap: break-word;
- margin: 0px;
- padding: 10px;
+ border-color: #333333;
color: #839496; /* base0 */
- font-size: 14px;
- margin-bottom: 20px;
+ font-size: 16px;
+ line-height: 20px;
+ margin: 0 0 20px 0;
+ padding: 10px;
+ word-wrap: break-word;
}
pre, code {
@@ -84,3 +86,55 @@ pre .support.property {
pre .variable.global, pre .variable.class, pre .variable.instance {
color: #839496; /* base0 */
}
+
+/**
+ * Additional styles for enhanced CSS syntax
+ */
+
+pre .entity, pre .mediaquery.type {
+ font: inherit;
+}
+
+pre .pseudo, pre .vendor-prefix {
+ font-style: italic;
+}
+
+pre .at-directive, pre .reserved, pre .exception {
+ font-weight: bold;
+}
+
+pre .hack {
+ color: #ff0000; /* red */
+}
+
+pre .selector {
+ color: #839496; /* base0 */
+}
+
+pre .at-directive, pre .reserved, pre .exception, pre .attribute-name, pre .mediaquery.type {
+ color: #b58900; /* yellow */
+}
+
+pre .method-name {
+ color: #c5ab0b; /* light yellow */
+}
+
+pre .constant.numeric, pre .constant.hex-color {
+ color: #2aa198; /* cyan */
+}
+
+pre .css-property, pre .mediaquery.feature {
+ color: #8866dd; /* purple */
+}
+
+pre .entity.tag {
+ color: #ad5a18; /* orange */
+}
+
+pre .constant.path {
+ color: #268bd2; /* blue */
+}
+
+pre .vendor-prefix {
+ opacity: 0.7;
+}