.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / normalize-selector / lib / normalize-selector.js
1 /* normalize-selector v0.1.0 (c) 2014 Kyle Simpson */
2
3 (function UMD(name,context,definition){
4         if (typeof module !== "undefined" && module.exports) { module.exports = definition(); }
5         else if (typeof define === "function" && define.amd) { define(definition); }
6         else { context[name] = definition(name,context); }
7 })("normalizeSelector",this,function DEF(name,context){
8         "use strict";
9
10         function normalizeSelector(sel) {
11
12                 // save unmatched text, if any
13                 function saveUnmatched() {
14                         if (unmatched) {
15                                 // whitespace needed after combinator?
16                                 if (tokens.length > 0 &&
17                                         /^[~+>]$/.test(tokens[tokens.length-1])
18                                 ) {
19                                         tokens.push(" ");
20                                 }
21
22                                 // save unmatched text
23                                 tokens.push(unmatched);
24                         }
25                 }
26
27                 var tokens = [], match, unmatched, regex, state = [0],
28                         next_match_idx = 0, prev_match_idx,
29                         not_escaped_pattern = /(?:[^\\]|(?:^|[^\\])(?:\\\\)+)$/,
30                         whitespace_pattern = /^\s+$/,
31                         attribute_nonspecial_pattern = /[^\s=~!^|$*\[\]\(\)]{2}/,
32                         state_patterns = [
33                                 /\s+|\/\*|["'>~+\[\(]/g, // general
34                                 /\s+|\/\*|["'\[\]\(\)]/g, // [..] set
35                                 /\s+|\/\*|["'\[\]\(\)]/g, // (..) set
36                                 null, // string literal (placeholder)
37                                 /\*\//g // comment
38                         ]
39                 ;
40
41                 sel = sel.trim();
42
43                 while (true) {
44                         unmatched = "";
45
46                         regex = state_patterns[state[state.length-1]];
47
48                         regex.lastIndex = next_match_idx;
49                         match = regex.exec(sel);
50
51                         // matched text to process?
52                         if (match) {
53                                 prev_match_idx = next_match_idx;
54                                 next_match_idx = regex.lastIndex;
55
56                                 // collect the previous string chunk not matched before this token
57                                 if (prev_match_idx < next_match_idx - match[0].length) {
58                                         unmatched = sel.substring(prev_match_idx,next_match_idx - match[0].length);
59                                 }
60
61                                 // need to force a space (possibly skipped
62                                 // previously by the parser)?
63                                 if (
64                                         state[state.length-1] === 1 &&
65                                         attribute_nonspecial_pattern.test(
66                                                 tokens[tokens.length-1].substr(-1) +
67                                                 unmatched.charAt(0)
68                                         )
69                                 ) {
70                                         tokens.push(" ");
71                                 }
72
73                                 // general, [ ] pair, ( ) pair?
74                                 if (state[state.length-1] < 3) {
75                                         saveUnmatched();
76
77                                         // starting a [ ] pair?
78                                         if (match[0] === "[") {
79                                                 state.push(1);
80                                         }
81                                         // starting a ( ) pair?
82                                         else if (match[0] === "(") {
83                                                 state.push(2);
84                                         }
85                                         // starting a string literal?
86                                         else if (/^["']$/.test(match[0])) {
87                                                 state.push(3);
88                                                 state_patterns[3] = new RegExp(match[0],"g");
89                                         }
90                                         // starting a comment?
91                                         else if (match[0] === "/*") {
92                                                 state.push(4);
93                                         }
94                                         // ending a [ ] or ( ) pair?
95                                         else if (/^[\]\)]$/.test(match[0]) && state.length > 0) {
96                                                 state.pop();
97                                         }
98                                         // handling whitespace or a combinator?
99                                         else if (/^(?:\s+|[~+>])$/.test(match[0])) {
100                                                 // need to insert whitespace before?
101                                                 if (tokens.length > 0 &&
102                                                         !whitespace_pattern.test(tokens[tokens.length-1]) &&
103                                                         state[state.length-1] === 0
104                                                 ) {
105                                                         // add normalized whitespace
106                                                         tokens.push(" ");
107                                                 }
108
109                                                 // whitespace token we can skip?
110                                                 if (whitespace_pattern.test(match[0])) {
111                                                         continue;
112                                                 }
113                                         }
114
115                                         // save matched text
116                                         tokens.push(match[0]);
117                                 }
118                                 // otherwise, string literal or comment
119                                 else {
120                                         // save unmatched text
121                                         tokens[tokens.length-1] += unmatched;
122
123                                         // unescaped terminator to string literal or comment?
124                                         if (not_escaped_pattern.test(tokens[tokens.length-1])) {
125                                                 // comment terminator?
126                                                 if (state[state.length-1] === 4) {
127                                                         // ok to drop comment?
128                                                         if (tokens.length < 2 ||
129                                                                 whitespace_pattern.test(tokens[tokens.length-2])
130                                                         ) {
131                                                                 tokens.pop();
132                                                         }
133                                                         // otherwise, turn comment into whitespace
134                                                         else {
135                                                                 tokens[tokens.length-1] = " ";
136                                                         }
137
138                                                         // handled already
139                                                         match[0] = "";
140                                                 }
141
142                                                 state.pop();
143                                         }
144
145                                         // append matched text to existing token
146                                         tokens[tokens.length-1] += match[0];
147                                 }
148                         }
149                         // otherwise, end of processing (no more matches)
150                         else {
151                                 unmatched = sel.substr(next_match_idx);
152                                 saveUnmatched();
153
154                                 break;
155                         }
156                 }
157
158                 return tokens.join("").trim();
159         }
160
161         return normalizeSelector;
162 });
163