habaki 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/ext/katana/extconf.rb +20 -0
  4. data/ext/katana/rb_katana.c +280 -0
  5. data/ext/katana/rb_katana.h +102 -0
  6. data/ext/katana/rb_katana_array.c +144 -0
  7. data/ext/katana/rb_katana_declaration.c +389 -0
  8. data/ext/katana/rb_katana_rule.c +461 -0
  9. data/ext/katana/rb_katana_selector.c +559 -0
  10. data/ext/katana/src/foundation.c +237 -0
  11. data/ext/katana/src/foundation.h +120 -0
  12. data/ext/katana/src/katana.h +590 -0
  13. data/ext/katana/src/katana.lex.c +4104 -0
  14. data/ext/katana/src/katana.lex.h +592 -0
  15. data/ext/katana/src/katana.tab.c +4422 -0
  16. data/ext/katana/src/katana.tab.h +262 -0
  17. data/ext/katana/src/parser.c +1563 -0
  18. data/ext/katana/src/parser.h +237 -0
  19. data/ext/katana/src/selector.c +659 -0
  20. data/ext/katana/src/selector.h +54 -0
  21. data/ext/katana/src/tokenizer.c +300 -0
  22. data/ext/katana/src/tokenizer.h +41 -0
  23. data/lib/habaki/charset_rule.rb +25 -0
  24. data/lib/habaki/declaration.rb +53 -0
  25. data/lib/habaki/declarations.rb +346 -0
  26. data/lib/habaki/error.rb +43 -0
  27. data/lib/habaki/font_face_rule.rb +24 -0
  28. data/lib/habaki/formal_syntax.rb +464 -0
  29. data/lib/habaki/formatter.rb +99 -0
  30. data/lib/habaki/import_rule.rb +34 -0
  31. data/lib/habaki/media_rule.rb +173 -0
  32. data/lib/habaki/namespace_rule.rb +31 -0
  33. data/lib/habaki/node.rb +52 -0
  34. data/lib/habaki/page_rule.rb +24 -0
  35. data/lib/habaki/qualified_name.rb +29 -0
  36. data/lib/habaki/rule.rb +48 -0
  37. data/lib/habaki/rules.rb +225 -0
  38. data/lib/habaki/selector.rb +98 -0
  39. data/lib/habaki/selectors.rb +49 -0
  40. data/lib/habaki/style_rule.rb +35 -0
  41. data/lib/habaki/stylesheet.rb +158 -0
  42. data/lib/habaki/sub_selector.rb +234 -0
  43. data/lib/habaki/sub_selectors.rb +42 -0
  44. data/lib/habaki/supports_rule.rb +65 -0
  45. data/lib/habaki/value.rb +321 -0
  46. data/lib/habaki/values.rb +86 -0
  47. data/lib/habaki/visitor/element.rb +50 -0
  48. data/lib/habaki/visitor/media.rb +22 -0
  49. data/lib/habaki/visitor/nokogiri_element.rb +56 -0
  50. data/lib/habaki.rb +39 -0
  51. metadata +190 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Copyright (c) 2015 QFish <im@qfi.sh>
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
21
+ */
22
+
23
+ #ifndef __Katana__selector__
24
+ #define __Katana__selector__
25
+
26
+ #include <stdio.h>
27
+ #include "katana.h"
28
+ #include "parser.h"
29
+
30
+ #ifdef __cplusplus
31
+ extern "C" {
32
+ #endif
33
+
34
+ KatanaParserString* katana_selector_to_string(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* next);
35
+
36
+ bool katana_selector_crosses_tree_scopes(const KatanaSelector* selector);
37
+ bool katana_selector_matches_pseudo_element(KatanaSelector* selector);
38
+ bool katana_selector_is_custom_pseudo_element(KatanaSelector* selector);
39
+ bool katana_selector_is_direct_adjacent(KatanaSelector* selector);
40
+ bool katana_selector_is_adjacent(KatanaSelector* selector);
41
+ bool katana_selector_is_shadow(KatanaSelector* selector);
42
+ bool katana_selector_is_sibling(KatanaSelector* selector);
43
+ bool katana_selector_is_attribute(const KatanaSelector* selector);
44
+ bool katana_selector_is_content_pseudo_element(KatanaSelector* selector);
45
+ bool katana_selector_is_shadow_pseudo_element(KatanaSelector* selector);
46
+ bool katana_selector_is_host_pseudo_class(KatanaSelector* selector);
47
+ bool katana_selector_is_tree_boundary_crossing(KatanaSelector* selector);
48
+ bool katana_selector_is_insertion_point_crossing(KatanaSelector* selector);
49
+
50
+ #ifdef __cplusplus
51
+ }
52
+ #endif
53
+
54
+ #endif /* defined(__Katana__selector__) */
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Copyright (c) 2015 QFish <im@qfi.sh>
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
21
+ */
22
+
23
+ #include <assert.h>
24
+
25
+ #include "tokenizer.h"
26
+ #include "katana.tab.h"
27
+ #include "katana.lex.h"
28
+ #include "parser.h"
29
+ #include "foundation.h"
30
+
31
+ #undef assert
32
+ #define assert(x)
33
+
34
+ static inline double katana_characters_to_double(const char* data, size_t length, bool* ok);
35
+ static inline bool katana_is_html_space(char c);
36
+ static inline char* katana_normalize_text(yy_size_t* length, char *origin_text, yy_size_t origin_length, int tok);
37
+
38
+ #ifdef KATANA_FELX_DEBUG
39
+ #if KATANA_FELX_DEBUG
40
+ static char * katana_token_string(int tok);
41
+ #endif // #if KATANA_FELX_DEBUG
42
+ #endif // #ifdef KATANA_FELX_DEBUG
43
+
44
+ /**
45
+ * A hook function of flex, processing tokens which will be passed to bison
46
+ *
47
+ * @param yylval the medium for flex and bison
48
+ * @param yyscanner flex state
49
+ * @param tok the type of token
50
+ *
51
+ * @return the type of token
52
+ */
53
+ int katana_tokenize(KATANASTYPE* lval , KATANALTYPE* loc, yyscan_t scanner, KatanaParser* parser, int tok)
54
+ {
55
+ char* origin_text = katanaget_text(scanner);
56
+
57
+ yy_size_t len = 0;
58
+
59
+ char* text = katana_normalize_text(&len, origin_text, katanaget_leng(scanner), tok);
60
+
61
+ #ifdef KATANA_FELX_DEBUG
62
+ #if KATANA_FELX_DEBUG
63
+ if ( tok == KATANA_CSS_WHITESPACE ) {
64
+ katana_parser_log(parser, "【%30s】=>【%30s】: %s", "", "", katana_token_string(tok));
65
+ } else {
66
+ katana_parser_log(parser, "【%30s】=>【%30s】: %s", origin_text, text, katana_token_string(tok));
67
+ }
68
+ #endif // #if KATANA_FELX_DEBUG
69
+ #endif // #ifdef KATANA_FELX_DEBUG
70
+ yy_size_t length = len;
71
+ switch ( tok ) {
72
+ case KATANA_CSS_INCLUDES:
73
+ case KATANA_CSS_DASHMATCH:
74
+ case KATANA_CSS_BEGINSWITH:
75
+ case KATANA_CSS_ENDSWITH:
76
+ case KATANA_CSS_CONTAINS:
77
+ break;
78
+ case KATANA_CSS_STRING:
79
+ case KATANA_CSS_IDENT:
80
+ case KATANA_CSS_NTH:
81
+
82
+ case KATANA_CSS_HEX:
83
+ case KATANA_CSS_IDSEL:
84
+
85
+ case KATANA_CSS_DIMEN:
86
+ case KATANA_CSS_INVALIDDIMEN:
87
+ case KATANA_CSS_URI:
88
+ case KATANA_CSS_FUNCTION:
89
+ case KATANA_CSS_ANYFUNCTION:
90
+ case KATANA_CSS_CUEFUNCTION:
91
+ case KATANA_CSS_NOTFUNCTION:
92
+ case KATANA_CSS_CALCFUNCTION:
93
+ case KATANA_CSS_MINFUNCTION:
94
+ case KATANA_CSS_MAXFUNCTION:
95
+ case KATANA_CSS_HOSTFUNCTION:
96
+ case KATANA_CSS_HOSTCONTEXTFUNCTION:
97
+ case KATANA_CSS_UNICODERANGE:
98
+ {
99
+ lval->string.data = text;
100
+ lval->string.length = length;
101
+ }
102
+ break;
103
+ case KATANA_CSS_IMPORT_SYM:
104
+ case KATANA_CSS_PAGE_SYM:
105
+ case KATANA_CSS_MEDIA_SYM:
106
+ case KATANA_CSS_SUPPORTS_SYM:
107
+ case KATANA_CSS_FONT_FACE_SYM:
108
+ case KATANA_CSS_CHARSET_SYM:
109
+ case KATANA_CSS_NAMESPACE_SYM:
110
+ // case KATANA_CSS_VIEWPORT_RULE_SYM:
111
+ case KATANA_INTERNAL_DECLS_SYM:
112
+ case KATANA_INTERNAL_MEDIALIST_SYM:
113
+ case KATANA_INTERNAL_RULE_SYM:
114
+ case KATANA_INTERNAL_SELECTOR_SYM:
115
+ case KATANA_INTERNAL_VALUE_SYM:
116
+ case KATANA_INTERNAL_KEYFRAME_RULE_SYM:
117
+ case KATANA_INTERNAL_KEYFRAME_KEY_LIST_SYM:
118
+ case KATANA_INTERNAL_SUPPORTS_CONDITION_SYM:
119
+ case KATANA_CSS_KEYFRAMES_SYM:
120
+ break;
121
+ case KATANA_CSS_QEMS:
122
+ length--;
123
+ case KATANA_CSS_GRADS:
124
+ case KATANA_CSS_TURNS:
125
+ length--;
126
+ case KATANA_CSS_DEGS:
127
+ case KATANA_CSS_RADS:
128
+ case KATANA_CSS_KHERTZ:
129
+ case KATANA_CSS_REMS:
130
+ length--;
131
+ case KATANA_CSS_MSECS:
132
+ case KATANA_CSS_HERTZ:
133
+ case KATANA_CSS_EMS:
134
+ case KATANA_CSS_CHS:
135
+ case KATANA_CSS_EXS:
136
+ case KATANA_CSS_PXS:
137
+ case KATANA_CSS_CMS:
138
+ case KATANA_CSS_MMS:
139
+ case KATANA_CSS_INS:
140
+ case KATANA_CSS_PTS:
141
+ case KATANA_CSS_PCS:
142
+ case KATANA_CSS_DPPX:
143
+ case KATANA_CSS_DPI:
144
+ case KATANA_CSS_DPCM:
145
+ case KATANA_CSS_VW:
146
+ case KATANA_CSS_VH:
147
+ case KATANA_CSS_VMIN:
148
+ case KATANA_CSS_VMAX:
149
+ length--;
150
+ case KATANA_CSS_SECS:
151
+ case KATANA_CSS_PERCENTAGE:
152
+ length--;
153
+ case KATANA_CSS_FLOATTOKEN:
154
+ lval->number.val = katana_characters_to_double(text, length, NULL);
155
+ lval->number.raw.data = text;
156
+ lval->number.raw.length = len;
157
+ break;
158
+ case KATANA_CSS_INTEGER:
159
+ lval->number.val = (int)katana_characters_to_double(text, length, NULL);
160
+ lval->number.raw.data = text;
161
+ lval->number.raw.length = len;
162
+
163
+ break;
164
+ default:
165
+ break;
166
+ }
167
+
168
+ return tok;
169
+ }
170
+
171
+ /**
172
+ * Format token
173
+ *
174
+ * @param length
175
+ * @param origin_text original text from the flex
176
+ * @param origin_length formatted length
177
+ * @param tok
178
+ *
179
+ * @return normalized text
180
+ */
181
+ static inline char* katana_normalize_text(yy_size_t* length, char *origin_text, yy_size_t origin_length, int tok)
182
+ {
183
+ char * start = origin_text;
184
+ yy_size_t l = origin_length;
185
+ switch ( tok ) {
186
+ case KATANA_CSS_STRING:
187
+ l--;
188
+ /* nobreak */
189
+ case KATANA_CSS_HEX:
190
+ case KATANA_CSS_IDSEL:
191
+ start++;
192
+ l--;
193
+ break;
194
+ case KATANA_CSS_URI:
195
+ // "url("{w}{string}{w}")"
196
+ // "url("{w}{url}{w}")"
197
+ // strip "url(" and ")"
198
+ start += 4;
199
+ l -= 5;
200
+ // strip {w}
201
+ while (l && katana_is_html_space(*start)) {
202
+ ++start;
203
+ --l;
204
+ }
205
+ while (l && katana_is_html_space(start[l - 1]))
206
+ --l;
207
+ if (l && (*start == '"' || *start == '\'')) {
208
+ assert(l >= 2 && start[l - 1] == *start);
209
+ ++start;
210
+ l -= 2;
211
+ }
212
+ break;
213
+ default:
214
+ break;
215
+ }
216
+
217
+ *length = l;
218
+ return start;
219
+ }
220
+
221
+ double katana_characters_to_double(const char* data, size_t length, bool* ok)
222
+ {
223
+ if (!length) {
224
+ if (ok)
225
+ *ok = false;
226
+ return 0.0;
227
+ }
228
+
229
+ char* bytes = malloc(sizeof(char) * (length + 1));
230
+ for (unsigned i = 0; i < length; ++i)
231
+ bytes[i] = data[i] < 0x7F ? data[i] : '?';
232
+ bytes[length] = '\0';
233
+ char* end;
234
+ double val = strtod(bytes, &end);
235
+ if (ok)
236
+ *ok = (end == 0 || *end == '\0');
237
+ free(bytes);
238
+ return val;
239
+ }
240
+
241
+ #ifdef KATANA_FELX_DEBUG
242
+ #if KATANA_FELX_DEBUG
243
+ static char * katana_token_table[] = {
244
+ "TOKEN_EOF", "LOWEST_PREC", "UNIMPORTANT_TOK",
245
+ "KATANA_CSS_SGML_CD", "KATANA_CSS_WHITESPACE", "KATANA_CSS_INCLUDES",
246
+ "KATANA_CSS_DASHMATCH", "KATANA_CSS_BEGINSWITH", "KATANA_CSS_ENDSWITH",
247
+ "KATANA_CSS_CONTAINS", "KATANA_CSS_STRING", "KATANA_CSS_IDENT",
248
+ "KATANA_CSS_NTH", "KATANA_CSS_HEX", "KATANA_CSS_IDSEL", "KATANA_CSS_IMPORT_SYM", "KATANA_CSS_PAGE_SYM",
249
+ "KATANA_CSS_MEDIA_SYM", "KATANA_CSS_SUPPORTS_SYM",
250
+ "KATANA_CSS_FONT_FACE_SYM", "KATANA_CSS_CHARSET_SYM",
251
+ "KATANA_CSS_NAMESPACE_SYM", "KATANA_INTERNAL_DECLS_SYM",
252
+ "KATANA_INTERNAL_MEDIALIST_SYM", "KATANA_INTERNAL_RULE_SYM",
253
+ "KATANA_INTERNAL_SELECTOR_SYM", "KATANA_INTERNAL_VALUE_SYM",
254
+ "KATANA_INTERNAL_KEYFRAME_RULE_SYM",
255
+ "KATANA_INTERNAL_KEYFRAME_KEY_LIST_SYM",
256
+ "KATANA_INTERNAL_SUPPORTS_CONDITION_SYM", "KATANA_CSS_KEYFRAMES_SYM",
257
+ "KATANA_CSS_ATKEYWORD", "KATANA_CSS_IMPORTANT_SYM",
258
+ "KATANA_CSS_MEDIA_NOT", "KATANA_CSS_MEDIA_ONLY", "KATANA_CSS_MEDIA_AND",
259
+ "KATANA_CSS_MEDIA_OR", "KATANA_CSS_SUPPORTS_NOT",
260
+ "KATANA_CSS_SUPPORTS_AND", "KATANA_CSS_SUPPORTS_OR", "KATANA_CSS_REMS",
261
+ "KATANA_CSS_CHS", "KATANA_CSS_QEMS", "KATANA_CSS_EMS", "KATANA_CSS_EXS",
262
+ "KATANA_CSS_PXS", "KATANA_CSS_CMS", "KATANA_CSS_MMS", "KATANA_CSS_INS",
263
+ "KATANA_CSS_PTS", "KATANA_CSS_PCS", "KATANA_CSS_DEGS", "KATANA_CSS_RADS",
264
+ "KATANA_CSS_GRADS", "KATANA_CSS_TURNS", "KATANA_CSS_MSECS",
265
+ "KATANA_CSS_SECS", "KATANA_CSS_HERTZ", "KATANA_CSS_KHERTZ",
266
+ "KATANA_CSS_DIMEN", "KATANA_CSS_INVALIDDIMEN", "KATANA_CSS_PERCENTAGE",
267
+ "KATANA_CSS_FLOATTOKEN", "KATANA_CSS_INTEGER", "KATANA_CSS_VW",
268
+ "KATANA_CSS_VH", "KATANA_CSS_VMIN", "KATANA_CSS_VMAX", "KATANA_CSS_DPPX",
269
+ "KATANA_CSS_DPI", "KATANA_CSS_DPCM", "KATANA_CSS_FR", "KATANA_CSS_URI",
270
+ "KATANA_CSS_FUNCTION", "KATANA_CSS_ANYFUNCTION",
271
+ "KATANA_CSS_CUEFUNCTION", "KATANA_CSS_NOTFUNCTION",
272
+ "KATANA_CSS_CALCFUNCTION", "KATANA_CSS_MINFUNCTION",
273
+ "KATANA_CSS_MAXFUNCTION", "KATANA_CSS_HOSTFUNCTION",
274
+ "KATANA_CSS_HOSTCONTEXTFUNCTION", "KATANA_CSS_UNICODERANGE" };
275
+
276
+ static char * katana_token_string(int tok)
277
+ {
278
+ if (tok > 257)
279
+ {
280
+ return katana_token_table[tok-257];
281
+ }
282
+ else if ( 0 == tok )
283
+ {
284
+ return katana_token_table[0];
285
+ }
286
+ else
287
+ {
288
+ char* unicode = malloc(2);
289
+ unicode[0] = (char)tok;
290
+ unicode[1] = '\0';
291
+ return unicode;
292
+ }
293
+ }
294
+ #endif // #if KATANA_FELX_DEBUG
295
+ #endif // #ifdef KATANA_FELX_DEBUG
296
+
297
+ inline bool katana_is_html_space(char c)
298
+ {
299
+ return c <= ' ' && (c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f');
300
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) 2015 QFish <im@qfi.sh>
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
21
+ */
22
+
23
+ #ifndef __Katana__tokenizer__
24
+ #define __Katana__tokenizer__
25
+
26
+ #include <stdio.h>
27
+ #include "katana.lex.h"
28
+ #include "katana.tab.h"
29
+ #include "parser.h"
30
+
31
+ #ifdef __cplusplus
32
+ extern "C" {
33
+ #endif
34
+
35
+ int katana_tokenize(KATANASTYPE* lval , KATANALTYPE* loc, yyscan_t scanner, KatanaParser* parser, int tok);
36
+
37
+ #ifdef __cplusplus
38
+ }
39
+ #endif
40
+
41
+ #endif /* defined(__Katana__tokenizer__) */
@@ -0,0 +1,25 @@
1
+ module Habaki
2
+ # Rule for @charset
3
+ class CharsetRule < Rule
4
+ # @return [String]
5
+ attr_accessor :encoding
6
+
7
+ # @param [String] encoding
8
+ def initialize(encoding = nil)
9
+ @encoding
10
+ end
11
+
12
+ # @param [Formatter::Base] format
13
+ # @return [String]
14
+ def string(format = Formatter::Base.new)
15
+ "@charset #{format.quote}#{@encoding}#{format.quote};"
16
+ end
17
+
18
+ # @api private
19
+ # @param [Katana::CharsetRule] rule
20
+ # @return [void]
21
+ def read_from_katana(rule)
22
+ @encoding = rule.encoding
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,53 @@
1
+ module Habaki
2
+ class Declaration < Node
3
+ # @return [String]
4
+ attr_accessor :property
5
+ # @return [Values]
6
+ attr_accessor :values
7
+ # @return [Boolean]
8
+ attr_accessor :important
9
+
10
+ # @return [SourcePosition]
11
+ attr_accessor :position
12
+
13
+ def initialize(property = nil, important = false)
14
+ @property = property
15
+ @important = important
16
+ @values = Values.new
17
+ end
18
+
19
+ # shortcut to first value
20
+ # @return [Value]
21
+ def value
22
+ @values.first
23
+ end
24
+
25
+ # check validity
26
+ # @return [Boolean]
27
+ def check
28
+ Habaki::FormalSyntax::Matcher.new(self).match?
29
+ end
30
+
31
+ # @param [Formatter::Base] format
32
+ # @return [String]
33
+ def string(format = Formatter::Base.new)
34
+ "#{format.declaration_prefix}#{@property}: #{@values.string(format)}#{important_string}"
35
+ end
36
+
37
+ # @api private
38
+ # @param [Katana::Declaration] decl
39
+ # @return [void]
40
+ def read_from_katana(decl)
41
+ @property = decl.property.downcase if decl.property
42
+ @important = decl.important
43
+ @values = Values.read_from_katana(decl.values)
44
+ @position = SourcePosition.new(decl.position.line, decl.position.column)
45
+ end
46
+
47
+ private
48
+
49
+ def important_string
50
+ @important ? " !important" : ""
51
+ end
52
+ end
53
+ end