Changeset 7221
- Timestamp:
- 07/24/07 17:24:25 (1 year ago)
- Files:
-
- spinoffs/prototype/trunk/CHANGELOG (modified) (1 diff)
- spinoffs/prototype/trunk/src/string.js (modified) (2 diffs)
- spinoffs/prototype/trunk/test/unit/string.html (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
spinoffs/prototype/trunk/CHANGELOG
r7219 r7221 1 1 *SVN* 2 2 3 * Extended grep semantics. The first argument to Enumerable#grep is now a "filter" (an object with a match() method) so you can now e.g. filter an array of DOM nodes by CSS selector. RegExp#match is now an alias to RegExp#test, so grep can still be used to filter an array of strings with a regular expression. Closes #7596. [Christophe Porteneuve, sam] 3 * Template enhancements. Closes #8166. [Christophe Porteneuve] 4 - Added String#interpolate as a shortcut for new Template(...).evaluate(...). 5 - If you pass String#interpolate or Template#evaluate an object with a toTemplateReplacements() method, the return value of that method will be used as the replacement object. 6 - You can now substitute properties of template replacement values in template strings, using dot or bracket notation (or both). Example: 7 "#{name.last}, #{name.first[0]}. (#{location})".interpolate({ 8 name: { first: "Christophe", last: "Porteneuve" }, location: "Paris" 9 }) // "Porteneuve, C. (Paris)" 10 11 * Extended grep semantics. The first argument to Enumerable#grep is now a "filter" (an object with a match() method) so you can now e.g. filter an array of DOM nodes by CSS selector. RegExp#match is now an alias to RegExp#test, so grep can still be used to filter an array of strings with a regular expression. Closes #7596. [Christophe Porteneuve, sam] 4 12 5 13 * Make String#scan explicitly return a string. This prevents possible issues with methods expecting input data that is typeof == 'string'. Closes #6350. [AndrewRev, Tobie Langel] spinoffs/prototype/trunk/src/string.js
r7218 r7221 200 200 blank: function() { 201 201 return /^\s*$/.test(this); 202 }, 203 204 interpolate: function(object, pattern) { 205 return new Template(this, pattern).evaluate(object); 202 206 } 203 207 }); … … 232 236 initialize: function(template, pattern) { 233 237 this.template = template.toString(); 234 this.pattern = pattern || Template.Pattern;238 this.pattern = pattern || Template.Pattern; 235 239 }, 236 240 237 241 evaluate: function(object) { 242 if (typeof object.toTemplateReplacements == 'function') 243 object = object.toTemplateReplacements(); 244 238 245 return this.template.gsub(this.pattern, function(match) { 239 var before = match[1]; 246 if (object == null) return ''; 247 248 var before = match[1] || ''; 240 249 if (before == '\\') return match[2]; 241 return before + String.interpret(object[match[3]]); 242 }); 243 } 244 } 250 251 var ctx = object, expr = match[3]; 252 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); 253 if (match == null) return ''; 254 255 while (match != null) { 256 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; 257 ctx = ctx[comp]; 258 if (null == ctx || '' == match[3]) break; 259 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 260 match = pattern.exec(expr); 261 } 262 263 return before + String.interpret(ctx); 264 }.bind(this)); 265 } 266 }; spinoffs/prototype/trunk/test/unit/string.html
r7218 r7221 147 147 assertEnumEqual(['f','o','o'],'foo'.toArray()); 148 148 }}, 149 149 150 150 /* 151 151 Note that camelize() differs from its Rails counterpart, … … 314 314 template.evaluate(falses)); 315 315 }}, 316 316 317 testTemplateEvaluationWithNested: function() {with(this) { 318 var source = '#{name} #{manager.name} #{manager.age} #{manager.undef} #{manager.age.undef} #{colleagues.first.name}'; 319 var subject = { manager: { name: 'John', age: 29 }, name: 'Stephan', age: 22, colleagues: { first: { name: 'Mark' }Â } }; 320 assertEqual('Stephan', new Template('#{name}').evaluate(subject)); 321 assertEqual('John', new Template('#{manager.name}').evaluate(subject)); 322 assertEqual('29', new Template('#{manager.age}').evaluate(subject)); 323 assertEqual('', new Template('#{manager.undef}').evaluate(subject)); 324 assertEqual('', new Template('#{manager.age.undef}').evaluate(subject)); 325 assertEqual('Mark', new Template('#{colleagues.first.name}').evaluate(subject)); 326 assertEqual('Stephan John 29 Mark', new Template(source).evaluate(subject)); 327 }}, 328 329 testTemplateEvaluationWithIndexing: function() {with(this) { 330 var source = '#{0} = #{[0]} - #{1} = #{[1]} - #{[2][0]} - #{[2].name} - #{first[0]} - #{[first][0]} - #{[\\]]} - #{first[\\]]}'; 331 var subject = [ 'zero', 'one', [ 'two-zero' ] ]; 332 subject[2].name = 'two-zero-name'; 333 subject.first = subject[2]; 334 subject[']'] = '\\'; 335 subject.first[']'] = 'first\\'; 336 assertEqual('zero', new Template('#{[0]}').evaluate(subject)); 337 assertEqual('one', new Template('#{[1]}').evaluate(subject)); 338 assertEqual('two-zero', new Template('#{[2][0]}').evaluate(subject)); 339 assertEqual('two-zero-name', new Template('#{[2].name}').evaluate(subject)); 340 assertEqual('two-zero', new Template('#{first[0]}').evaluate(subject)); 341 assertEqual('\\', new Template('#{[\\]]}').evaluate(subject)); 342 assertEqual('first\\', new Template('#{first[\\]]}').evaluate(subject)); 343 assertEqual('empty - empty2', new Template('#{[]} - #{m[]}').evaluate({ '': 'empty', m: {'': 'empty2'}})); 344 assertEqual('zero = zero - one = one - two-zero - two-zero-name - two-zero - two-zero - \\ - first\\', new Template(source).evaluate(subject)); 345 }}, 346 347 testTemplateToTemplateReplacements: function() {with(this) { 348 var source = 'My name is #{name}, my job is #{job}'; 349 var subject = { 350 name: 'Stephan', 351 getJob: function() { return 'Web developer'; }, 352 toTemplateReplacements: function() { return { name: this.name, job: this.getJob() } } 353 }; 354 assertEqual('My name is Stephan, my job is Web developer', new Template(source).evaluate(subject)); 355 }}, 356 357 testTemplateEvaluationCombined: function() {with(this) { 358 var source = '#{name} is #{age} years old, managed by #{manager.name}, #{manager.age}.\n' + 359 'Colleagues include #{colleagues[0].name} and #{colleagues[1].name}.'; 360 var subject = { 361 name: 'Stephan', age: 22, 362 manager: { name: 'John', age: 29 }, 363 colleagues: [ { name: 'Mark' }, { name: 'Indy' } ] 364 }; 365 assertEqual('Stephan is 22 years old, managed by John, 29.\n' + 366 'Colleagues include Mark and Indy.', 367 new Template(source).evaluate(subject)); 368 }}, 369 370 testInterpolate: function() {with(this) { 371 var subject = { name: 'Stephan' }; 372 var pattern = /(^|.|\r|\n)(#\((.*?)\))/; 373 assertEqual('#{name}: Stephan', '\\#{name}: #{name}'.interpolate(subject)); 374 assertEqual('#(name): Stephan', '\\#(name): #(name)'.interpolate(subject, pattern)); 375 }}, 376 317 377 testToQueryParams: function() {with(this) { 318 378 // only the query part