PageSourceSearch

https://subs.springwise.com/JavaScript/mootools/core/Slick/Slick.Parser.js

js springwise.com collected 2026-09-24 08:47:38 UTC 6,817 bytes, 230 lines download raw bytes

1/*
2---
3name: Slick.Parser
4description: Standalone CSS3 Selector parser
5provides: Slick.Parser
6...
7*/
8
9;(function(){
10
11var parsed,
12	separatorIndex,
13	combinatorIndex,
14	reversed,
15	cache = {},
16	reverseCache = {},
17	reUnescape = /\\/g;
18
19var parse = function(expression, isReversed){
20	if (expression == null) return null;
21	if (expression.Slick === true) return expression;
22	expression = ('' + expression).replace(/^\s+|\s+$/g, '');
23	reversed = !!isReversed;
24	var currentCache = (reversed) ? reverseCache : cache;
25	if (currentCache[expression]) return currentCache[expression];
26	parsed = {
27		Slick: true,
28		expressions: [],
29		raw: expression,
30		reverse: function(){
31			return parse(this.raw, true);
32		}
33	};
34	separatorIndex = -1;
35	while (expression != (expression = expression.replace(regexp, parser)));
36	parsed.length = parsed.expressions.length;
37	return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed;
38};
39
40var reverseCombinator = function(combinator){
41	if (combinator === '!') return ' ';
42	else if (combinator === ' ') return '!';
43	else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
44	else return '!' + combinator;
45};
46
47var reverse = function(expression){
48	var expressions = expression.expressions;
49	for (var i = 0; i < expressions.length; i++){
50		var exp = expressions[i];
51		var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};
52
53		for (var j = 0; j < exp.length; j++){
54			var cexp = exp[j];
55			if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
56			cexp.combinator = cexp.reverseCombinator;
57			delete cexp.reverseCombinator;
58		}
59
60		exp.reverse().push(last);
61	}
62	return expression;
63};
64
65var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
66	return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){
67		return '\\' + match;
68	});
69};
70
71var regexp = new RegExp(
72/*
73#!/usr/bin/env ruby
74puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
75__END__
76	"(?x)^(?:\
77	  \\s* ( , ) \\s*               # Separator          \n\
78	| \\s* ( <combinator>+ ) \\s*   # Combinator         \n\
79	|      ( \\s+ )                 # CombinatorChildren \n\
80	|      ( <unicode>+ | \\* )     # Tag                \n\
81	| \\#  ( <unicode>+       )     # ID                 \n\
82	| \\.  ( <unicode>+       )     # ClassName          \n\
83	|                               # Attribute          \n\
84	\\[  \
85		\\s* (<unicode1>+)  (?:  \
86			\\s* ([*^$!~|]?=)  (?:  \
87				\\s* (?:\
88					([\"']?)(.*?)\\9 \
89				)\
90			)  \
91		)?  \\s*  \
92	\\](?!\\]) \n\
93	|   :+ ( <unicode>+ )(?:\
94	\\( (?:\
95		(?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
96	) \\)\
97	)?\
98	)"
99*/
100	"^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
101	.replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
102	.replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
103	.replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
104);
105
106function parser(
107	rawMatch,
108
109	separator,
110	combinator,
111	combinatorChildren,
112
113	tagName,
114	id,
115	className,
116
117	attributeKey,
118	attributeOperator,
119	attributeQuote,
120	attributeValue,
121
122	pseudoMarker,
123	pseudoClass,
124	pseudoQuote,
125	pseudoClassQuotedValue,
126	pseudoClassValue
127){
128	if (separator || separatorIndex === -1){
129		parsed.expressions[++separatorIndex] = [];
130		combinatorIndex = -1;
131		if (separator) return '';
132	}
133
134	if (combinator || combinatorChildren || combinatorIndex === -1){
135		combinator = combinator || ' ';
136		var currentSeparator = parsed.expressions[separatorIndex];
137		if (reversed && currentSeparator[combinatorIndex])
138			currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
139		currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
140	}
141
142	var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
143
144	if (tagName){
145		currentParsed.tag = tagName.replace(reUnescape, '');
146
147	} else if (id){
148		currentParsed.id = id.replace(reUnescape, '');
149
150	} else if (className){
151		className = className.replace(reUnescape, '');
152
153		if (!currentParsed.classList) currentParsed.classList = [];
154		if (!currentParsed.classes) currentParsed.classes = [];
155		currentParsed.classList.push(className);
156		currentParsed.classes.push({
157			value: className,
158			regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
159		});
160
161	} else if (pseudoClass){
162		pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
163		pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
164
165		if (!currentParsed.pseudos) currentParsed.pseudos = [];
166		currentParsed.pseudos.push({
167			key: pseudoClass.replace(reUnescape, ''),
168			value: pseudoClassValue,
169			type: pseudoMarker.length == 1 ? 'class' : 'element'
170		});
171
172	} else if (attributeKey){
173		attributeKey = attributeKey.replace(reUnescape, '');
174		attributeValue = (attributeValue || '').replace(reUnescape, '');
175
176		var test, regexp;
177
178		switch (attributeOperator){
179			case '^=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue)            ); break;
180			case '$=' : regexp = new RegExp(            escapeRegExp(attributeValue) +'$'       ); break;
181			case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
182			case '|=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue) +'(-|$)'   ); break;
183			case  '=' : test = function(value){
184				return attributeValue == value;
185			}; break;
186			case '*=' : test = function(value){
187				return value && value.indexOf(attributeValue) > -1;
188			}; break;
189			case '!=' : test = function(value){
190				return attributeValue != value;
191			}; break;
192			default   : test = function(value){
193				return !!value;
194			};
195		}
196
197		if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
198			return false;
199		};
200
201		if (!test) test = function(value){
202			return value && regexp.test(value);
203		};
204
205		if (!currentParsed.attributes) currentParsed.attributes = [];
206		currentParsed.attributes.push({
207			key: attributeKey,
208			operator: attributeOperator,
209			value: attributeValue,
210			test: test
211		});
212
213	}
214
215	return '';
216};
217
218// Slick NS
219
220var Slick = (this.Slick || {});
221
222Slick.parse = function(expression){
223	return parse(expression);
224};
225
226Slick.escapeRegExp = escapeRegExp;
227
228if (!this.Slick) this.Slick = Slick;
229
230}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.