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,590 @@
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
+ // CSS Spec: http://www.w3.org/TR/css-syntax-3/
24
+
25
+ #ifndef __Katana__katana__
26
+ #define __Katana__katana__
27
+
28
+ #include <stdio.h>
29
+ #include <stdbool.h>
30
+ #include <stddef.h>
31
+
32
+ #ifdef __cplusplus
33
+ extern "C" {
34
+ #endif
35
+
36
+ #define KATANA_ERROR_MESSAGE_SIZE 100
37
+
38
+ typedef enum {
39
+ KatanaRuleUnkown,
40
+ KatanaRuleStyle,
41
+ KatanaRuleImport,
42
+ KatanaRuleMedia,
43
+ KatanaRulePage,
44
+ KatanaRuleFontFace,
45
+ KatanaRuleSupports,
46
+ KatanaRuleNamespace,
47
+ KatanaRuleKeyframes,
48
+ KatanaRuleCharset,
49
+ KatanaRuleHost,
50
+ } KatanaRuleType;
51
+
52
+ typedef enum {
53
+ KatanaMediaQueryRestrictorNone,
54
+ KatanaMediaQueryRestrictorOnly,
55
+ KatanaMediaQueryRestrictorNot,
56
+ } KatanaMediaQueryRestrictor;
57
+
58
+ typedef enum {
59
+ KatanaSupportsOperatorNone,
60
+ KatanaSupportsOperatorNot,
61
+ KatanaSupportsOperatorAnd,
62
+ KatanaSupportsOperatorOr,
63
+ } KatanaSupportsOperator;
64
+
65
+ typedef enum {
66
+ KatanaSelectorMatchUnknown = 0,
67
+ KatanaSelectorMatchTag, // Example: div
68
+ KatanaSelectorMatchId, // Example: #id
69
+ KatanaSelectorMatchClass, // example: .class
70
+ KatanaSelectorMatchPseudoClass, // Example: :nth-child(2)
71
+ KatanaSelectorMatchPseudoElement, // Example: ::first-line
72
+ KatanaSelectorMatchPagePseudoClass, // ??
73
+ KatanaSelectorMatchAttributeExact, // Example: E[foo="bar"]
74
+ KatanaSelectorMatchAttributeSet, // Example: E[foo]
75
+ KatanaSelectorMatchAttributeList, // Example: E[foo~="bar"]
76
+ KatanaSelectorMatchAttributeHyphen, // Example: E[foo|="bar"]
77
+ KatanaSelectorMatchAttributeContain, // css3: E[foo*="bar"]
78
+ KatanaSelectorMatchAttributeBegin, // css3: E[foo^="bar"]
79
+ KatanaSelectorMatchAttributeEnd, // css3: E[foo$="bar"]
80
+ KatanaSelectorMatchFirstAttribute = KatanaSelectorMatchAttributeExact,
81
+ } KatanaSelectorMatch;
82
+
83
+ typedef enum {
84
+ KatanaSelectorRelationSubSelector, // "No space" combinator
85
+ KatanaSelectorRelationDescendant, // "Space" combinator
86
+ KatanaSelectorRelationChild, // > combinator
87
+ KatanaSelectorRelationDirectAdjacent, // + combinator
88
+ KatanaSelectorRelationIndirectAdjacent, // ~ combinator
89
+ KatanaSelectorRelationShadowPseudo, // Special case of shadow DOM pseudo elements / shadow pseudo element
90
+ KatanaSelectorRelationShadowDeep // /shadow-deep/ combinator
91
+ } KatanaSelectorRelation;
92
+
93
+ typedef enum {
94
+ KatanaPseudoNotParsed,
95
+ KatanaPseudoUnknown,
96
+ KatanaPseudoEmpty,
97
+ KatanaPseudoFirstChild,
98
+ KatanaPseudoFirstOfType,
99
+ KatanaPseudoLastChild,
100
+ KatanaPseudoLastOfType,
101
+ KatanaPseudoOnlyChild,
102
+ KatanaPseudoOnlyOfType,
103
+ KatanaPseudoFirstLine,
104
+ KatanaPseudoFirstLetter,
105
+ KatanaPseudoNthChild,
106
+ KatanaPseudoNthOfType,
107
+ KatanaPseudoNthLastChild,
108
+ KatanaPseudoNthLastOfType,
109
+ KatanaPseudoLink,
110
+ KatanaPseudoVisited,
111
+ KatanaPseudoAny,
112
+ KatanaPseudoAnyLink,
113
+ KatanaPseudoAutofill,
114
+ KatanaPseudoHover,
115
+ KatanaPseudoDrag,
116
+ KatanaPseudoFocus,
117
+ KatanaPseudoActive,
118
+ KatanaPseudoChecked,
119
+ KatanaPseudoEnabled,
120
+ KatanaPseudoFullPageMedia,
121
+ KatanaPseudoDefault,
122
+ KatanaPseudoDisabled,
123
+ KatanaPseudoOptional,
124
+ KatanaPseudoRequired,
125
+ KatanaPseudoReadOnly,
126
+ KatanaPseudoReadWrite,
127
+ KatanaPseudoValid,
128
+ KatanaPseudoInvalid,
129
+ KatanaPseudoIndeterminate,
130
+ KatanaPseudoTarget,
131
+ KatanaPseudoBefore,
132
+ KatanaPseudoAfter,
133
+ KatanaPseudoBackdrop,
134
+ KatanaPseudoLang,
135
+ KatanaPseudoNot, // :not(selector), selector is Kind of KatanaSelector
136
+ KatanaPseudoResizer,
137
+ KatanaPseudoRoot,
138
+ KatanaPseudoScope,
139
+ KatanaPseudoScrollbar,
140
+ KatanaPseudoScrollbarButton,
141
+ KatanaPseudoScrollbarCorner,
142
+ KatanaPseudoScrollbarThumb,
143
+ KatanaPseudoScrollbarTrack,
144
+ KatanaPseudoScrollbarTrackPiece,
145
+ KatanaPseudoWindowInactive,
146
+ KatanaPseudoCornerPresent,
147
+ KatanaPseudoDecrement,
148
+ KatanaPseudoIncrement,
149
+ KatanaPseudoHorizontal,
150
+ KatanaPseudoVertical,
151
+ KatanaPseudoStart,
152
+ KatanaPseudoEnd,
153
+ KatanaPseudoDoubleButton,
154
+ KatanaPseudoSingleButton,
155
+ KatanaPseudoNoButton,
156
+ KatanaPseudoSelection,
157
+ KatanaPseudoLeftPage,
158
+ KatanaPseudoRightPage,
159
+ KatanaPseudoFirstPage,
160
+ KatanaPseudoFullScreen,
161
+ KatanaPseudoFullScreenDocument,
162
+ KatanaPseudoFullScreenAncestor,
163
+ KatanaPseudoInRange,
164
+ KatanaPseudoOutOfRange,
165
+ KatanaPseudoWebKitCustomElement,
166
+ KatanaPseudoCue,
167
+ KatanaPseudoFutureCue,
168
+ KatanaPseudoPastCue,
169
+ KatanaPseudoUnresolved,
170
+ KatanaPseudoContent,
171
+ KatanaPseudoHost,
172
+ KatanaPseudoHostContext,
173
+ KatanaPseudoShadow,
174
+ KatanaPseudoSpatialNavigationFocus,
175
+ KatanaPseudoListBox
176
+ } KatanaPseudoType;
177
+
178
+ typedef enum {
179
+ KatanaAttributeMatchTypeCaseSensitive,
180
+ KatanaAttributeMatchTypeCaseInsensitive,
181
+ } KatanaAttributeMatchType;
182
+
183
+ typedef enum {
184
+ KATANA_VALUE_UNKNOWN = 0,
185
+ KATANA_VALUE_NUMBER = 1,
186
+ KATANA_VALUE_PERCENTAGE = 2,
187
+ KATANA_VALUE_EMS = 3,
188
+ KATANA_VALUE_EXS = 4,
189
+
190
+ // double
191
+ KATANA_VALUE_PX = 5,
192
+ KATANA_VALUE_CM = 6,
193
+ KATANA_VALUE_MM = 7,
194
+ KATANA_VALUE_IN = 8,
195
+ KATANA_VALUE_PT = 9,
196
+ KATANA_VALUE_PC = 10,
197
+ KATANA_VALUE_DEG = 11,
198
+ KATANA_VALUE_RAD = 12,
199
+ KATANA_VALUE_GRAD = 13,
200
+ KATANA_VALUE_MS = 14,
201
+ KATANA_VALUE_S = 15,
202
+ KATANA_VALUE_HZ = 16,
203
+ KATANA_VALUE_KHZ = 17,
204
+ KATANA_VALUE_DIMENSION = 18,
205
+ KATANA_VALUE_STRING = 19,
206
+ KATANA_VALUE_URI = 20,
207
+ KATANA_VALUE_IDENT = 21,
208
+ KATANA_VALUE_ATTR = 22,
209
+ KATANA_VALUE_COUNTER = 23,
210
+ KATANA_VALUE_RECT = 24,
211
+ KATANA_VALUE_RGBCOLOR = 25,
212
+
213
+ KATANA_VALUE_VW = 26,
214
+ KATANA_VALUE_VH = 27,
215
+ KATANA_VALUE_VMIN = 28,
216
+ KATANA_VALUE_VMAX = 29,
217
+ KATANA_VALUE_DPPX = 30,
218
+ KATANA_VALUE_DPI = 31,
219
+ KATANA_VALUE_DPCM = 32,
220
+ KATANA_VALUE_FR = 33,
221
+ KATANA_VALUE_UNICODE_RANGE = 102,
222
+
223
+ KATANA_VALUE_PARSER_OPERATOR = 103,
224
+ KATANA_VALUE_PARSER_INTEGER = 104,
225
+ KATANA_VALUE_PARSER_HEXCOLOR = 105,
226
+ KATANA_VALUE_PARSER_FUNCTION = 0x100001,
227
+ KATANA_VALUE_PARSER_LIST = 0x100002,
228
+ KATANA_VALUE_PARSER_Q_EMS = 0x100003,
229
+
230
+ KATANA_VALUE_PARSER_IDENTIFIER = 106,
231
+
232
+ KATANA_VALUE_TURN = 107,
233
+ KATANA_VALUE_REMS = 108,
234
+ KATANA_VALUE_CHS = 109,
235
+
236
+ KATANA_VALUE_COUNTER_NAME = 110,
237
+
238
+ KATANA_VALUE_SHAPE = 111,
239
+
240
+ KATANA_VALUE_QUAD = 112,
241
+
242
+ KATANA_VALUE_CALC = 113,
243
+ KATANA_VALUE_CALC_PERCENTAGE_WITH_NUMBER = 114,
244
+ KATANA_VALUE_CALC_PERCENTAGE_WITH_LENGTH = 115,
245
+ KATANA_VALUE_VARIABLE_NAME = 116,
246
+
247
+ KATANA_VALUE_PROPERTY_ID = 117,
248
+ KATANA_VALUE_VALUE_ID = 118
249
+ } KatanaValueUnit;
250
+
251
+ //typedef enum {
252
+ // KATANA_VALUE_PARSER_OPERATOR = 0x100000,
253
+ // KATANA_VALUE_PARSER_FUNCTION = 0x100001,
254
+ // KATANA_VALUE_PARSER_LIST = 0x100002,
255
+ // KATANA_VALUE_PARSER_Q_EMS = 0x100003,
256
+ //} KatanaParserValueUnit;
257
+
258
+ typedef enum { KatanaParseError } KatanaErrorType;
259
+
260
+ /**
261
+ * Positon, for error debug
262
+ */
263
+ typedef struct {
264
+ unsigned int line;
265
+ unsigned int column;
266
+ } KatanaSourcePosition;
267
+
268
+ typedef struct {
269
+ const char* local; // tag local name
270
+ const char* prefix; // namesapce identifier
271
+ const char* uri; // namesapce uri
272
+ } KatanaQualifiedName;
273
+
274
+ typedef struct {
275
+ /** Data elements. This points to a dynamically-allocated array of capacity
276
+ * elements, each a void* to the element itself, remember free each element.
277
+ */
278
+ void** data;
279
+
280
+ /** Number of elements currently in the array. */
281
+ unsigned int length;
282
+
283
+ /** Current array capacity. */
284
+ unsigned int capacity;
285
+
286
+ } KatanaArray;
287
+
288
+ typedef struct {
289
+ const char* encoding;
290
+ KatanaArray /* KatanaRule */ rules;
291
+ KatanaArray /* KatanaImportRule */ imports;
292
+ } KatanaStylesheet;
293
+
294
+ typedef struct {
295
+ const char* name;
296
+ KatanaRuleType type;
297
+ } KatanaRule;
298
+
299
+ typedef struct {
300
+ KatanaRule base;
301
+ KatanaArray* /* KatanaSelector */ selectors;
302
+ KatanaArray* /* KatanaDeclaration */ declarations;
303
+ } KatanaStyleRule;
304
+
305
+ typedef struct {
306
+ const char* comment;
307
+ } KatanaComment; // unused for right
308
+
309
+ /**
310
+ * The `@font-face` at-rule.
311
+ */
312
+ typedef struct {
313
+ KatanaRule base;
314
+ KatanaArray* /* KatanaDeclaration */ declarations;
315
+ } KatanaFontFaceRule;
316
+
317
+ /**
318
+ * The `@host` at-rule.
319
+ */
320
+ typedef struct {
321
+ KatanaRule base;
322
+ KatanaArray* /* KatanaRule */ host;
323
+ } KatanaHostRule;
324
+
325
+ /**
326
+ * The `@import` at-rule.
327
+ */
328
+ typedef struct {
329
+ KatanaRule base;
330
+ /**
331
+ * The part following `@import `
332
+ */
333
+ const char* href;
334
+ /**
335
+ * The media list belonging to this import rule
336
+ */
337
+ KatanaArray* /* KatanaMediaQuery* */ medias;
338
+ } KatanaImportRule;
339
+
340
+ /**
341
+ * The `@keyframes` at-rule.
342
+ * Spec: http://www.w3.org/TR/css3-animations/#keyframes
343
+ */
344
+ typedef struct {
345
+ KatanaRule base;
346
+ /**
347
+ * The vendor prefix in `@keyframes`, or `undefined` if there is none.
348
+ */
349
+ const char* name;
350
+ KatanaArray* /* KatanaKeyframe */ keyframes;
351
+ } KatanaKeyframesRule;
352
+
353
+ typedef struct {
354
+ KatanaArray* /* KatanaValue: `percentage`, `from`, `to` */ selectors;
355
+ KatanaArray* /* KatanaDeclaration */ declarations;
356
+ } KatanaKeyframe;
357
+
358
+ /* @namespace */
359
+ typedef struct {
360
+ KatanaRule base;
361
+
362
+ const char* prefix;
363
+ const char* uri;
364
+ } KatanaNamespaceRule;
365
+
366
+ /**
367
+ * The `@media` at-rule.
368
+ */
369
+ typedef struct {
370
+ KatanaRule base;
371
+ /**
372
+ * The part following `@media `
373
+ */
374
+ KatanaArray* medias;
375
+ /**
376
+ * An `Array` of nodes with the types `rule`, `comment` and any of the
377
+ at-rule types.
378
+ */
379
+ KatanaArray* /* KatanaRule */ rules;
380
+ } KatanaMediaRule;
381
+
382
+ /**
383
+ * Media Query Exp List
384
+ * Spec: http://www.w3.org/TR/mediaqueries-4/
385
+ */
386
+
387
+ typedef struct {
388
+ KatanaMediaQueryRestrictor restrictor;
389
+ const char* type;
390
+ KatanaArray* expressions;
391
+ bool ignored;
392
+ } KatanaMediaQuery;
393
+
394
+ typedef struct {
395
+ const char* feature;
396
+ KatanaArray* values;
397
+ const char* raw;
398
+ } KatanaMediaQueryExp;
399
+
400
+ typedef struct {
401
+ KatanaRule base;
402
+ KatanaArray* /* KatanaDeclaration */ declarations;
403
+ } KatanaPageRule;
404
+
405
+ typedef struct {
406
+ const char* value;
407
+ union {
408
+ struct {
409
+ int a; // Used for :nth-*
410
+ int b; // Used for :nth-*
411
+ } nth;
412
+ KatanaAttributeMatchType attributeMatchType; // used for attribute selector (with value)
413
+ } bits;
414
+ KatanaQualifiedName* attribute;
415
+ const char* argument; // Used for :contains, :lang, :nth-*
416
+ KatanaArray* selectors; // Used for :any and :not
417
+ } KatanaSelectorRareData;
418
+
419
+ typedef struct KatanaSelector {
420
+ KatanaSourcePosition position;
421
+
422
+ size_t specificity;
423
+ KatanaSelectorMatch match;
424
+ KatanaPseudoType pseudo;
425
+ KatanaSelectorRelation relation;
426
+ KatanaQualifiedName* tag;
427
+ KatanaSelectorRareData* data;
428
+ struct KatanaSelector* tagHistory;
429
+ } KatanaSelector;
430
+
431
+ unsigned katana_calc_specificity_for_selector(KatanaSelector* selector);
432
+
433
+ typedef struct {
434
+ KatanaSourcePosition position;
435
+
436
+ // property name
437
+ const char* property;
438
+
439
+ // property value
440
+ KatanaArray* /* KatanaValue */ values;
441
+ const char* string;
442
+
443
+ // is this property marked important
444
+ bool important;
445
+
446
+ // origin css text of the property
447
+ const char* raw;
448
+ } KatanaDeclaration;
449
+
450
+ typedef struct {
451
+ const char* name;
452
+ KatanaArray* args;
453
+ } KatanaValueFunction;
454
+
455
+ typedef struct KatanaValue {
456
+ bool isInt;
457
+ union {
458
+ int iValue;
459
+ double fValue;
460
+ const char* string;
461
+ KatanaValueFunction* function;
462
+ KatanaArray* list;
463
+ };
464
+ KatanaValueUnit unit;
465
+ const char* raw;
466
+ } KatanaValue;
467
+
468
+ typedef struct {
469
+ KatanaSupportsOperator op;
470
+ KatanaArray* exps;
471
+ KatanaDeclaration* decl;
472
+ const char* raw;
473
+ } KatanaSupportsExp;
474
+
475
+ /**
476
+ * The `@supports` at-rule.
477
+ */
478
+ typedef struct {
479
+ KatanaRule base;
480
+ KatanaSupportsExp* exp;
481
+ KatanaArray* /* KatanaRule */ rules;
482
+ } KatanaSupportsRule;
483
+
484
+ /**
485
+ * The `@charset` at-rule.
486
+ */
487
+ typedef struct {
488
+ KatanaRule base;
489
+ /**
490
+ * The encoding information
491
+ */
492
+ const char* encoding;
493
+ } KatanaCharsetRule;
494
+
495
+ typedef struct {
496
+ KatanaErrorType type;
497
+ int first_line;
498
+ int first_column;
499
+ int last_line;
500
+ int last_column;
501
+ char message[KATANA_ERROR_MESSAGE_SIZE];
502
+ } KatanaError;
503
+
504
+ // TODO: @document
505
+ // TODO: @supports
506
+ // TODO: custom-at-rule
507
+
508
+ /**
509
+ * Parser mode
510
+ */
511
+ typedef enum KatanaParserMode {
512
+ // Normal CSS content used in External CSS files or Internal CSS, may include more than 1 css rules.
513
+ KatanaParserModeStylesheet,
514
+
515
+ // Single CSS rule like "@import", "selector{...}"
516
+ KatanaParserModeRule,
517
+
518
+ KatanaParserModeKeyframeRule,
519
+ KatanaParserModeKeyframeKeyList,
520
+ KatanaParserModeMediaList,
521
+
522
+ // CSS property value like "1px", "1em", "#eee"
523
+ KatanaParserModeValue,
524
+
525
+ // CSS selector like ".pages.active"
526
+ KatanaParserModeSelector,
527
+
528
+ // Inline stylesheet like "width: 20px; height: 20px;"
529
+ KatanaParserModeDeclarationList,
530
+ } KatanaParserMode;
531
+
532
+ typedef struct KatanaInternalOutput {
533
+ // Complete CSS string
534
+ KatanaStylesheet* stylesheet;
535
+ union {
536
+ // fragmental CSS string
537
+ KatanaRule* rule;
538
+ KatanaKeyframe* keyframe;
539
+ KatanaArray* keyframe_keys;
540
+ KatanaArray* values;
541
+ KatanaArray* medias;
542
+ KatanaArray* /* KatanaDeclaration */ declarations;
543
+ KatanaArray* selectors;
544
+ KatanaArray* supports;
545
+ };
546
+ KatanaParserMode mode;
547
+ KatanaArray /* KatanaError */ errors;
548
+ } KatanaOutput;
549
+
550
+ /**
551
+ * Parse a complete or fragmental CSS string
552
+ *
553
+ * @param str Input CSS string
554
+ * @param len Length of the input CSS string
555
+ * @param mode Parser mode, depends on the input
556
+ *
557
+ * @return The result of parsing
558
+ */
559
+ KatanaOutput* katana_parse(const char* str, size_t len, KatanaParserMode mode);
560
+
561
+ /**
562
+ * Parse a complete CSS file
563
+ *
564
+ * @param fp `FILE` point to the CSS file
565
+ *
566
+ * @return The result of parsing
567
+ */
568
+ KatanaOutput* katana_parse_in(FILE* fp);
569
+
570
+ /**
571
+ * Free the output
572
+ *
573
+ * @param output The result of parsing
574
+ */
575
+ void katana_destroy_output(KatanaOutput* output);
576
+
577
+ /**
578
+ * Print the formatted CSS string
579
+ *
580
+ * @param output The result of parsing
581
+ *
582
+ * @return The origin output
583
+ */
584
+ KatanaOutput* katana_dump_output(KatanaOutput* output);
585
+
586
+ #ifdef __cplusplus
587
+ }
588
+ #endif
589
+
590
+ #endif /* defined(__Katana__katana__) */