| # -*- coding: utf-8 -*- # |
| |
| module Rouge |
| module Lexers |
| class CSS < RegexLexer |
| title "CSS" |
| 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( |
| align-content align-items align-self alignment-adjust |
| alignment-baseline all anchor-point animation |
| animation-delay animation-direction animation-duration |
| animation-fill-mode animation-iteration-count animation-name |
| animation-play-state animation-timing-function appearance |
| azimuth backface-visibility background background-attachment |
| background-clip background-color background-image |
| background-origin background-position background-repeat |
| background-size baseline-shift binding bleed bookmark-label |
| bookmark-level bookmark-state bookmark-target border |
| border-bottom border-bottom-color border-bottom-left-radius |
| border-bottom-right-radius border-bottom-style |
| border-bottom-width border-collapse border-color |
| border-image border-image-outset border-image-repeat |
| border-image-slice border-image-source border-image-width |
| border-left border-left-color border-left-style |
| border-left-width border-radius border-right |
| border-right-color border-right-style border-right-width |
| border-spacing border-style border-top border-top-color |
| border-top-left-radius border-top-right-radius |
| border-top-style border-top-width border-width bottom |
| box-align box-decoration-break box-direction box-flex |
| box-flex-group box-lines box-ordinal-group box-orient |
| box-pack box-shadow box-sizing break-after break-before |
| break-inside caption-side clear clip clip-path |
| clip-rule color color-profile columns column-count |
| column-fill column-gap column-rule column-rule-color |
| column-rule-style column-rule-width column-span |
| column-width content counter-increment counter-reset |
| crop cue cue-after cue-before cursor direction display |
| dominant-baseline drop-initial-after-adjust |
| drop-initial-after-align drop-initial-before-adjust |
| drop-initial-before-align drop-initial-size |
| drop-initial-value elevation empty-cells filter fit |
| fit-position flex flex-basis flex-direction flex-flow |
| flex-grow flex-shrink flex-wrap float float-offset |
| font font-family font-feature-settings |
| font-kerning font-language-override font-size |
| font-size-adjust font-stretch font-style font-synthesis |
| font-variant font-variant-alternates font-variant-caps |
| font-variant-east-asian font-variant-ligatures |
| font-variant-numeric font-variant-position font-weight |
| grid-cell grid-column grid-column-align grid-column-sizing |
| grid-column-span grid-columns grid-flow grid-row |
| grid-row-align grid-row-sizing grid-row-span |
| grid-rows grid-template hanging-punctuation height |
| hyphenate-after hyphenate-before hyphenate-character |
| hyphenate-lines hyphenate-resource hyphens icon |
| image-orientation image-rendering image-resolution |
| ime-mode inline-box-align justify-content |
| left letter-spacing line-break line-height |
| line-stacking line-stacking-ruby line-stacking-shift |
| line-stacking-strategy list-style list-style-image |
| list-style-position list-style-type margin |
| margin-bottom margin-left margin-right margin-top |
| mark marker-offset marks mark-after mark-before |
| marquee-direction marquee-loop marquee-play-count |
| marquee-speed marquee-style mask max-height max-width |
| min-height min-width move-to nav-down |
| nav-index nav-left nav-right nav-up object-fit |
| object-position opacity order orphans outline |
| outline-color outline-offset outline-style |
| outline-width overflow overflow-style overflow-wrap |
| overflow-x overflow-y padding padding-bottom |
| padding-left padding-right padding-top |
| page page-break-after page-break-before |
| page-break-inside page-policy pause pause-after |
| pause-before perspective perspective-origin |
| phonemes pitch pitch-range play-during pointer-events |
| position presentation-level punctuation-trim quotes |
| rendering-intent resize rest rest-after rest-before |
| richness right rotation rotation-point ruby-align |
| ruby-overhang ruby-position ruby-span size speak |
| speak-as speak-header speak-numeral speak-punctuation |
| speech-rate src stress string-set |
| tab-size table-layout target target-name |
| target-new target-position text-align |
| text-align-last text-combine-horizontal |
| text-decoration text-decoration-color |
| text-decoration-line text-decoration-skip |
| text-decoration-style text-emphasis |
| text-emphasis-color text-emphasis-position |
| text-emphasis-style text-height text-indent |
| text-justify text-orientation text-outline |
| text-overflow text-rendering text-shadow |
| text-space-collapse text-transform |
| text-underline-position text-wrap top |
| transform transform-origin transform-style |
| transition transition-delay transition-duration |
| transition-property transition-timing-function |
| unicode-bidi vertical-align |
| visibility voice-balance voice-duration |
| voice-family voice-pitch voice-pitch-range |
| voice-range voice-rate voice-stress voice-volume |
| volume white-space widows width word-break |
| word-spacing word-wrap writing-mode 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 |
| rule /"(\\\\|\\"|[^"])*"/, Str::Single |
| rule /'(\\\\|\\'|[^'])*'/, Str::Double |
| end |
| |
| state :value do |
| mixin :basics |
| rule /url\(.*?\)/, Str::Other |
| rule /#[0-9a-f]{1,6}/i, Num # colors |
| rule /#{number}(?:%|(?:em|px|pt|pc|in|mm|cm|ex|rem|ch|vw|vh|vmin|vmax|dpi|dpcm|dppx|deg|grad|rad|turn|s|ms|Hz|kHz)\b)?/, Num |
| rule /[\[\]():\/.,]/, Punctuation |
| rule /"(\\\\|\\"|[^"])*"/, Str::Single |
| rule /'(\\\\|\\'|[^'])*'/, Str::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! 2 |
| 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| |
| name_tok = if self.class.attributes.include? m[1] |
| Name::Label |
| elsif self.class.vendor_prefixes.any? { |p| m[1].start_with?(p) } |
| Name::Label |
| else |
| Name::Property |
| end |
| |
| groups name_tok, Text, 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 |