Skip to content

Commit bba199a

Browse files
committed
add - implement support for filters
1 parent 6d224a0 commit bba199a

File tree

11 files changed

+1435
-901
lines changed

11 files changed

+1435
-901
lines changed

build.xml

+7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131
<fileset file="src/runner.js" />
3232
<fileset file="src/global.js" />
3333
<fileset file="src/core.js" />
34+
<fileset file="src/element.js" />
35+
<fileset file="src/recipes.js" />
36+
<fileset file="src/coloring.js" />
37+
<fileset file="src/stylesheets.js" />
38+
<fileset file="src/html.js" />
39+
<fileset file="src/lines.js" />
40+
<fileset file="src/filters.js" />
3441
<fileset file="src/text_selection.js" />
3542
<fileset file="src/_end.js" />
3643
</concat>

src/coloring.js

+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
2+
/**
3+
* Returns all the steps of the given blockName of the given recipe
4+
*
5+
* @param {String} recipe
6+
* @param {String} blockName
7+
*
8+
* @return Array<Object>
9+
*/
10+
function prepareBlock( recipe, blockName )
11+
{
12+
var steps = [];
13+
var block = recipe[ blockName ];
14+
for( var stepName in block )
15+
{
16+
var prepared = prepareStep( recipe, blockName, stepName );
17+
steps.push( prepared );
18+
}
19+
return steps;
20+
}
21+
22+
/**
23+
* Returns the number of sub matches in the given regular expression (as
24+
* a string)
25+
*
26+
* @param {String} re
27+
*
28+
* @return integer
29+
*/
30+
function numberOfSubmatches( re )
31+
{
32+
var submatches = re
33+
.replace( /\\./g, "%" ) // disable any escaped character
34+
.replace( /\[.*?\]/g, "%" ) // disable any character class
35+
.match( /\((?!\?)/g ) // match any open parenthesis, not followed by a ?
36+
;
37+
var result = (submatches || []).length;
38+
return result;
39+
}
40+
41+
/**
42+
* Returns a step built from the given stepName of the given blockName
43+
* of the given recipe
44+
*
45+
* @param {String} recipe
46+
* @param {String} blockName
47+
* @param {String} stepName
48+
*
49+
* @return Object
50+
*/
51+
function prepareStep( recipe, blockName, stepName )
52+
{
53+
var step = recipe[ blockName ][ stepName ];
54+
var exp = ( typeof step._match == "string" )
55+
? step._match
56+
: step._match.source;
57+
var replacement = step._replace
58+
? step._replace
59+
: '<span class="$0">$$</span>';
60+
var result = {
61+
recipe: recipe,
62+
blockName: blockName,
63+
stepName: stepName,
64+
exp: '(' + exp + ')', // new exp will have 1 more submatch
65+
length: numberOfSubmatches( exp ) + 1,
66+
replacement: replacement
67+
};
68+
return result;
69+
}
70+
71+
/**
72+
* Returns the given steps, with back references in the regular
73+
* expression of each step renumbered according to the number of back
74+
* references found in any previous step
75+
*
76+
* @param {Array} steps
77+
*
78+
* @return Array
79+
*/
80+
function adjustBackReferences( steps )
81+
{
82+
var prevLength = 1;
83+
var exps = [];
84+
for (var i = 0, iTop = steps.length; i < iTop; i++) {
85+
var exp = steps[ i ].exp;
86+
exp = exp.replace( /\\\\|\\(\d+)/g,
87+
function( m, aNum )
88+
{
89+
return !aNum ? m : "\\" + ( prevLength + 1 + parseInt( aNum, 10 ) );
90+
}
91+
);
92+
exps.push( exp );
93+
prevLength += steps[ i ].length;
94+
}
95+
return exps;
96+
}
97+
98+
/**
99+
* Returns a regular expression built from all the given steps
100+
*
101+
* @param {Array} steps
102+
*
103+
* @return RegExp
104+
*/
105+
function knowHow( steps, flags )
106+
{
107+
var prolog = '((?:\\s|\\S)*?)';
108+
var epilog = '((?:\\s|\\S)+)';
109+
var exps = adjustBackReferences( steps );
110+
var source = '(?:' + exps.join( '|' ) + ')';
111+
source = prolog + source + '|' + epilog;
112+
return new RegExp( source, flags );
113+
}
114+
115+
/**
116+
* Returns the given replacement, after adding the given prefix to all
117+
* classes of all SPANs
118+
*
119+
* @param {String} prefix
120+
* @param {String} replacement
121+
*
122+
* @return String
123+
*/
124+
function addPrefix( prefix, replacement )
125+
{
126+
var lookFor = /(<span\s+class\s*=\s*(["']))((?:(?!__)\w)+\2\s*>)/ig;
127+
var replaceWith = '$1' + prefix + '__$3';
128+
var aux = replacement.replace( lookFor, replaceWith );
129+
return aux;
130+
}
131+
132+
/**
133+
* Returns the step in the given steps and its matches in the given
134+
* allMatches
135+
*
136+
* @param {Object} steps the steps of a recipe
137+
* @param {Array} allMatches the corresponding matches
138+
*
139+
* @return Object
140+
*/
141+
function locateStepMatches( steps, allMatches )
142+
{
143+
var matchesIndex = 2;
144+
for (var i = 0, iTop = steps.length; i < iTop; i++)
145+
{
146+
var step = steps[ i ];
147+
var stepMatches = allMatches[ matchesIndex ];
148+
if (stepMatches) break;
149+
matchesIndex += step.length;
150+
}
151+
var matches = allMatches.slice(matchesIndex, matchesIndex + step.length);
152+
var offset = allMatches[ allMatches.length - 2 ];
153+
var original = allMatches[ allMatches.length - 1 ];
154+
matches.push( offset );
155+
matches.push( original );
156+
return {step: step, matches: matches};
157+
}
158+
159+
/**
160+
* Returns the replacement for the given stepMatches, based on the
161+
* function in stepMatches.step.replacement
162+
*
163+
* @param {Object} stepMatches
164+
*
165+
* @return String
166+
*/
167+
function functionReplacement( stepMatches )
168+
{
169+
var that =
170+
{
171+
x: function( subject, module )
172+
{
173+
var result = applyModule( subject, module, stepMatches.step );
174+
return result;
175+
}
176+
};
177+
var result = stepMatches.step.replacement.apply(that, stepMatches.matches);
178+
return result;
179+
}
180+
181+
/**
182+
* Returns the replacement for the given stepMatches, based on the
183+
* template in stepMatches.step.replacement
184+
*
185+
* @param {Object} stepMatches
186+
*
187+
* @return String
188+
*/
189+
function templateReplacement( stepMatches )
190+
{
191+
var re = /(\\\$)|(?:\$\$)|(?:\$(\d+))/g;
192+
var substitution = function( m, escaped, K )
193+
{
194+
var result = '';
195+
if ( escaped ) /* \$ */
196+
{
197+
result = "$";
198+
}
199+
else if ( !K ) /* $$ */
200+
{
201+
result = escapeHtmlSpecialChars( stepMatches.matches[ 0 ] ); //stepMatches
202+
}
203+
else if ( K == "0" ) /* $0 */
204+
{
205+
result = stepMatches.step.stepName;
206+
}
207+
else /* $K */
208+
{
209+
result = escapeHtmlSpecialChars( stepMatches.matches[ K ] );
210+
}
211+
return result;
212+
};
213+
var result = stepMatches.step.replacement.replace(re, substitution);
214+
return result;
215+
}
216+
217+
/**
218+
* Returns the replacement for any match found. This is a callback
219+
* function passed to String.replace()
220+
*
221+
* @return String
222+
*/
223+
function chef( steps, replaceArgs )
224+
{
225+
var result = '';
226+
var anyMatch = replaceArgs[ 0 ];
227+
if (! anyMatch) return result;
228+
229+
var epilog = replaceArgs[ replaceArgs.length - 3 ];
230+
if (epilog) {
231+
result = escapeHtmlSpecialChars( epilog );
232+
return result;
233+
}
234+
var stepMatches = locateStepMatches( steps, replaceArgs );
235+
result = $.isFunction(stepMatches.step.replacement)
236+
? functionReplacement(stepMatches)
237+
: templateReplacement(stepMatches)
238+
;
239+
var prolog = replaceArgs[ 1 ];
240+
prolog = escapeHtmlSpecialChars( prolog );
241+
result = addPrefix( stepMatches.step.recipe._name, result );
242+
result = prolog + result;
243+
return result;
244+
}
245+
246+
/**
247+
* Returns the given ingredients, after applying the given blockName of
248+
* the given recipe to it
249+
*
250+
* @param {String} ingredients
251+
* @param {Object} recipe
252+
* @param {String} blockName
253+
*
254+
* @return String
255+
*/
256+
function cook( ingredients, recipe, blockName )
257+
{
258+
if (! blockName)
259+
{
260+
blockName = '_main';
261+
checkSpices( recipe );
262+
}
263+
if (! blockName in recipe) return escapeHtmlSpecialChars( ingredients );
264+
var steps = prepareBlock( recipe, blockName );
265+
var flags = recipe._case
266+
? "g"
267+
: "gi";
268+
var kh = knowHow( steps, flags );
269+
var perfect = ingredients.replace( kh,
270+
function()
271+
{
272+
var args = Array.prototype.slice.call(arguments);
273+
var result = chef(steps, args);
274+
return result;
275+
}
276+
);
277+
return perfect;
278+
}
279+
280+

0 commit comments

Comments
 (0)