module Rouge module Lexers class CSS < RegexLexer desc "Cascading Style Sheets, used to style web pages" tag 'css' filenames '*.css' mimetypes 'text/css' identifier = /[a-zA-Z0-9_-]+/ number = /-?(?:[0-9]+(\.[0-9]+)?|\.[0-9]+)/ def self.attributes @attributes ||= Set.new %w( azimuth background background-attachment background-color background-image background-position background-repeat border border-bottom border-bottom-color border-bottom-style border-bottom-width border-collapse border-color border-left border-left-color border-left-style border-left-width border-right border-right-color border-right-style border-right-width border-spacing border-style border-top border-top-color border-top-style border-top-width border-width bottom caption-side clear clip color content counter-increment counter-reset cue cue-after cue-before cursor direction display elevation empty-cells float font font-family font-size font-size-adjust font-stretch font-style font-variant font-weight height left letter-spacing line-height list-style list-style-image list-style-position list-style-type margin margin-bottom margin-left margin-right margin-top marker-offset marks max-height max-width min-height min-width opacity orphans outline outline-color outline-style outline-width overflow-x overflow-y padding padding-bottom padding-left padding-right padding-top page page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position quotes richness right size speak speak-header speak-numeral speak-punctuation speech-rate src stress table-layout text-align text-decoration text-indent text-shadow text-transform top unicode-bidi vertical-align visibility voice-family volume white-space widows width word-spacing z-index ) end def self.builtins @builtins ||= Set.new %w( above absolute always armenian aural auto avoid left bottom baseline behind below bidi-override blink block bold bolder both bottom capitalize center center-left center-right circle cjk-ideographic close-quote collapse condensed continuous crop cross crosshair cursive dashed decimal decimal-leading-zero default digits disc dotted double e-resize embed expanded extra-condensed extra-expanded fantasy far-left far-right fast faster fixed georgian groove hebrew help hidden hide high higher hiragana hiragana-iroha icon inherit inline inline-table inset inside invert italic justify katakana katakana-iroha landscape large larger left left-side leftwards level lighter line-through list-item loud low lower lower-alpha lower-greek lower-roman lowercase ltr medium message-box middle mix monospace n-resize narrower ne-resize no-close-quote no-open-quote no-repeat none normal nowrap nw-resize oblique once open-quote outset outside overline pointer portrait px relative repeat repeat-x repeat-y rgb ridge right right-side rightwards s-resize sans-serif scroll se-resize semi-condensed semi-expanded separate serif show silent slow slower small-caps small-caption smaller soft solid spell-out square static status-bar super sw-resize table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group text text-bottom text-top thick thin top transparent ultra-condensed ultra-expanded underline upper-alpha upper-latin upper-roman uppercase url visible w-resize wait wider x-fast x-high x-large x-loud x-low x-small x-soft xx-large xx-small yes ) end def self.constants @constants ||= Set.new %w( indigo gold firebrick indianred yellow darkolivegreen darkseagreen mediumvioletred mediumorchid chartreuse mediumslateblue black springgreen crimson lightsalmon brown turquoise olivedrab cyan silver skyblue gray darkturquoise goldenrod darkgreen darkviolet darkgray lightpink teal darkmagenta lightgoldenrodyellow lavender yellowgreen thistle violet navy orchid blue ghostwhite honeydew cornflowerblue darkblue darkkhaki mediumpurple cornsilk red bisque slategray darkcyan khaki wheat deepskyblue darkred steelblue aliceblue gainsboro mediumturquoise floralwhite coral purple lightgrey lightcyan darksalmon beige azure lightsteelblue oldlace greenyellow royalblue lightseagreen mistyrose sienna lightcoral orangered navajowhite lime palegreen burlywood seashell mediumspringgreen fuchsia papayawhip blanchedalmond peru aquamarine white darkslategray ivory dodgerblue lemonchiffon chocolate orange forestgreen slateblue olive mintcream antiquewhite darkorange cadetblue moccasin limegreen saddlebrown darkslateblue lightskyblue deeppink plum aqua darkgoldenrod maroon sandybrown magenta tan rosybrown pink lightblue palevioletred mediumseagreen dimgray powderblue seagreen snow mediumblue midnightblue paleturquoise palegoldenrod whitesmoke darkorchid salmon lightslategray lawngreen lightgreen tomato hotpink lightyellow lavenderblush linen mediumaquamarine green blueviolet peachpuff ) end # source: http://www.w3.org/TR/CSS21/syndata.html#vendor-keyword-history def self.vendor_prefixes @vendor_prefixes ||= Set.new %w( -ah- -atsc- -hp- -khtml- -moz- -ms- -o- -rim- -ro- -tc- -wap- -webkit- -xv- mso- prince- ) end state :root do mixin :basics rule /{/, 'Punctuation', :stanza rule /:#{identifier}/, 'Name.Decorator' rule /\.#{identifier}/, 'Name.Class' rule /##{identifier}/, 'Name.Function' rule /@#{identifier}/, 'Keyword', :at_rule rule identifier, 'Name.Tag' rule %r([~^*!%&\[\]()<>|+=@:;,./?-]), 'Operator' end state :value do mixin :basics rule /url\(.*?\)/, 'Literal.String.Other' rule /#[0-9a-f]{1,6}/i, 'Literal.Number' # colors rule /#{number}(?:em|px|%|pt|pc|in|mm|m|ex|s)?\b/, 'Literal.Number' rule /[\[\]():\/.]/, 'Punctuation' rule /"(\\\\|\\"|[^"])*"/, 'Literal.String.Single' rule /'(\\\\|\\'|[^'])*'/, 'Literal.String.Double' rule(identifier) do |m| if self.class.constants.include? m[0] token 'Name.Constant' elsif self.class.builtins.include? m[0] token 'Name.Builtin' else token 'Name' end end end state :at_rule do rule /{(?=\s*#{identifier}\s*:)/m, 'Punctuation', :at_stanza rule /{/, 'Punctuation', :at_body rule /;/, 'Punctuation', :pop! mixin :value end state :at_body do mixin :at_content mixin :root end state :at_stanza do mixin :at_content mixin :stanza end state :at_content do rule /}/ do token 'Punctuation' pop!; pop! end end state :basics do rule /\s+/m, 'Text' rule %r(/\*(?:.*?)\*/)m, 'Comment' end state :stanza do mixin :basics rule /}/, 'Punctuation', :pop! rule /(#{identifier})(\s*)(:)/m do |m| if self.class.attributes.include? m[1] group 'Name.Label' elsif self.class.vendor_prefixes.any? { |p| m[1].start_with?(p) } group 'Name.Label' else group 'Name.Property' end group 'Text' group 'Punctuation' push :stanza_value end end state :stanza_value do rule /;/, 'Punctuation', :pop! rule(/(?=})/) { pop! } rule /!important\b/, 'Comment.Preproc' rule /^@.*?$/, 'Comment.Preproc' mixin :value end end end end