Completed
Push — master ( 6054a8...c11aa8 )
by Kacper
04:06
created

Css::getMetadata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 8
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
c 0
b 0
f 0
nc 1
nop 0
dl 8
loc 8
rs 9.4285
1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2016, Some right reserved.
6
 *
7
 * @author Kacper "Kadet" Donat <[email protected]>
8
 *
9
 * Contact with author:
10
 * Xmpp: [email protected]
11
 * E-mail: [email protected]
12
 *
13
 * From Kadet with love.
14
 */
15
16
namespace Kadet\Highlighter\Language;
17
18
use Kadet\Highlighter\Matcher\CommentMatcher;
19
use Kadet\Highlighter\Matcher\RegexMatcher;
20
use Kadet\Highlighter\Matcher\SubStringMatcher;
21
use Kadet\Highlighter\Matcher\WordMatcher;
22
use Kadet\Highlighter\Parser\CloseRule;
23
use Kadet\Highlighter\Parser\OpenRule;
24
use Kadet\Highlighter\Parser\Rule;
25
use Kadet\Highlighter\Parser\Token\MetaToken;
26
use Kadet\Highlighter\Parser\Token\Token;
27
use Kadet\Highlighter\Parser\TokenFactory;
28
use Kadet\Highlighter\Parser\Validator\Validator;
29
30
class Css extends GreedyLanguage
31
{
32
33
    /**
34
     * Tokenization rules
35
     */
36
    public function setupRules()
37
    {
38
        $identifier = '-?[_a-zA-Z]+[_a-zA-Z0-9-]*';
39
        $at = [
40
            'charset', 'import', 'namespace',
41
            'media', 'supports', 'document', 'page', 'font-face', 'keyframes', 'viewport', 'counter-style',
42
            'font-feature-values', 'swash', 'ornaments', 'annotation', 'stylistic', 'styleset', 'character-variant'
43
        ];
44
        
45
        $this->rules->addMany([
46
            'string' => CommonFeatures::strings(['single' => '\'', 'double' => '"'], [
47
                'context' => $this->everywhere()
48
            ]),
49
50
            'meta.declaration' => [
51
                new OpenRule(new SubStringMatcher('{'), [
52
                    'context' => ['!meta.declaration.media', '!comment'],
53
                    'factory' => new TokenFactory(MetaToken::class)
54
                ]),
55
                new CloseRule(new SubStringMatcher('}')),
56
            ],
57
58
            'meta.declaration.media' => [
59
                new Rule(new RegexMatcher('/@media(.*?\{)/'), [
60
                    'context' => Validator::everywhere(),
61
                    'factory' => new TokenFactory(MetaToken::class)
62
                ]),
63
            ],
64
65
            'meta.declaration.rule' => [
66
                new OpenRule(new RegexMatcher('/@media.*(\()/'), [
67
                    'context' => ['meta.declaration.media'],
68
                    'factory' => new TokenFactory(MetaToken::class)
69
                ]),
70
                new CloseRule(new SubStringMatcher(')')),
71
            ],
72
73
            'keyword.at-rule' => new Rule(new RegexMatcher('/(@(?:-[a-z]+-)?(?:'.implode('|', $at).'))/'), [
74
                'priority' => 2
75
            ]),
76
77
            'symbol.selector.id'    => new Rule(new RegexMatcher("/(#$identifier)/i")),
78
            'symbol.selector.tag'   => new Rule(new RegexMatcher('/(?>[\s}]|^)(?=(\w+)[^;]*\{)/ms')),
79
            'symbol.selector.class' => new Rule(new RegexMatcher("/(\\.$identifier)/i")),
80
81
            'symbol.selector.class.pseudo' => new Rule(new RegexMatcher("/(:{1,2}$identifier)/")),
82
83
            'number' => new Rule(new RegexMatcher("/([-+]?[0-9]*\\.?[0-9]+([\\w%]+)?)/"), [
84
                'context'  => ['meta.declaration', '!constant.color', '!comment', '!symbol', '!comment', '!string'],
85
                'priority' => 0
86
            ]),
87
            
88
            'symbol.property' => new Rule(new RegexMatcher("/($identifier:)/"), [
89
                'context' => ['meta.declaration', '!symbol', '!comment'],
90
                'priority' => 2
91
            ]),
92
93
            'call' => new Rule(new RegexMatcher("/($identifier)\\s*\\((?:(?P<string>[a-z].*?)|.*?)\\)/", [
94
                1 => Token::NAME,
95
                'string' => 'string.argument'
96
            ]), [
97
                'context' => ['meta.declaration', '!comment', '!string', '!keyword']
98
            ]),
99
100
            'constant.color' => [
101
                new Rule(new RegexMatcher("/(#[0-9a-f]{3,6})/i"), [
102
                    'priority' => 2,
103
                    'context'  => ['meta.declaration', '!comment']
104
                ]),
105
                new Rule(new WordMatcher([
106
                    'white', 'silver', 'gray', 'black', 'red', 'maroon', 'yellow', 'olive',
107
                    'lime', 'green', 'aqua', 'teal', 'blue', 'navy', 'fuchsia', 'purple'
108
                ]), [
109
                    'context'  => ['meta.declaration', '!comment', '!symbol', '!variable']
110
                ]),
111
            ],
112
113
            'operator' => new Rule(new WordMatcher(['>', '+', '*', '!important'], ['separated' => false]), [
114
                'context' => $this->everywhere()
115
            ]),
116
117
            'operator.punctuation' => new Rule(new SubStringMatcher(';'), [
118
                'context' => $this->everywhere()
119
            ]),
120
121
            'comment' => new Rule(new CommentMatcher([], [['/*', '*/']]), ['context' => $this->everywhere()])
122
        ]);
123
    }
124
125
    /**
126
     * Unique language identifier, for example 'php'
127
     *
128
     * @return string
129
     */
130
    public function getIdentifier()
131
    {
132
        return 'css';
133
    }
134
135
    protected function everywhere() {
136
        static $validator;
137
        if (!$validator) {
138
            $validator = new Validator(['!string', '!comment']);
139
        }
140
141
        return $validator;
142
    }
143
144 View Code Duplication
    public static function getMetadata()
145
    {
146
        return [
147
            'name'      => ['css'],
148
            'mime'      => ['text/css'],
149
            'extension' => ['*.css']
150
        ];
151
    }
152
}
153