UNPKG

4.12 kBJavaScriptView Raw
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2015 - present Instructure, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25/**
26 * ---
27 * category: utilities/themes
28 * ---
29 * Parses a CSS string into an AST object
30 * @module parseCss
31 * @param {String} cssText CSS string to parse
32 * @returns {Object} AST for the CSS string
33 */
34function parseCss() {
35 var cssText = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : '';
36 var cleaned = cleanCss(cssText);
37 return parseLexed(lex(cleaned), cleaned);
38}
39/**
40 * CSSRule types (https://developer.mozilla.org/en-US/docs/Web/API/CSSRule)
41 */
42
43
44var ruleTypes = {
45 style: 1,
46 keyframes: 7,
47 media: 4
48};
49/**
50 * Removes comments and import statements from a CSS string
51 * (to prep for parsing and applying transforms)
52 * @param {String} cssText CSS string to parse
53 * @returns {String} cleaned CSS string
54 */
55
56function cleanCss() {
57 var text = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : '';
58 // remove comments and imports
59 return text.replace(/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, '').replace(/@import[^;]*;/gim, '');
60}
61
62function lex(text) {
63 var rootNode = {
64 start: 0,
65 end: text.length
66 };
67 var node = rootNode;
68 var chars = text.split('');
69 chars.forEach(function (char, i) {
70 switch (char) {
71 case '{':
72 {
73 if (!node.rules) {
74 node.rules = [];
75 }
76
77 var parent = node;
78 var previous = parent.rules[parent.rules.length - 1];
79 node = {
80 start: i + 1,
81 parent: parent,
82 previous: previous
83 };
84 parent.rules.push(node);
85 break;
86 }
87
88 case '}':
89 {
90 node.end = i + 1;
91 node = node.parent || rootNode;
92 break;
93 }
94
95 default:
96 {
97 break;
98 }
99 }
100 });
101 return rootNode;
102}
103
104function parseSelector(node, text) {
105 var start = node.previous ? node.previous.end : node.parent.start;
106 var end = node.start - 1;
107 var selector = text.substring(start, end);
108 selector = selector.replace(/\s+/g, ' ');
109 selector = selector.substring(selector.lastIndexOf(';') + 1);
110 return selector.trim();
111}
112
113function parseRuleType(selector) {
114 if (selector.indexOf('@') === 0) {
115 if (selector.indexOf('@media') === 0) {
116 return ruleTypes.media;
117 } else if (selector.match(/^@[^\s]*keyframes/)) {
118 return ruleTypes.keyframes;
119 }
120 } else {
121 return ruleTypes.style;
122 }
123}
124
125function parseLexed(node) {
126 var text = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : '';
127
128 /* eslint-disable no-param-reassign */
129 if (node.parent) {
130 node.selector = parseSelector(node, text);
131 node.type = parseRuleType(node.selector);
132 }
133
134 node.cssText = text.substring(node.start, node.end - 1).trim();
135
136 if (node.rules && node.rules.length > 0) {
137 node.rules = node.rules.map(function (rule) {
138 return parseLexed(rule, text);
139 });
140 }
141 /* eslint-enable no-param-reassign */
142
143
144 return node;
145}
146
147export default parseCss;
148export { parseCss, cleanCss, ruleTypes };
\No newline at end of file