habaki 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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