|
5 | 5 | * case, the "public API" is exposed as properties on the `export` object, |
6 | 6 | * in the latter, as properties on `window.JSONSelect`. That API is thus: |
7 | 7 | * |
8 | | - * .match(selector, object) |
| 8 | + * Selector formating and parameter escaping: |
| 9 | + * |
| 10 | + * Anywhere where a string selector is selected, it may be followed by an |
| 11 | + * optional array of values. When provided, they will be escaped and |
| 12 | + * inserted into the selector string properly escaped. i.e.: |
| 13 | + * |
| 14 | + * .match(':has(?)', [ 'foo' ], {}) |
| 15 | + * |
| 16 | + * would result in the seclector ':has("foo")' being matched against {}. |
| 17 | + * |
| 18 | + * This feature makes dynamically generated selectors more readable. |
| 19 | + * |
| 20 | + * .match(selector, [ values ], object) |
9 | 21 | * |
10 | 22 | * Parses and "compiles" the selector, then matches it against the object |
11 | 23 | * argument. Matches are returned in an array. Throws an error when |
12 | 24 | * there's a problem parsing the selector. |
13 | 25 | * |
14 | | - * .forEach(selector, object, callback) |
| 26 | + * .forEach(selector, [ values ], object, callback) |
15 | 27 | * |
16 | 28 | * Like match, but rather than returning an array, invokes the provided |
17 | 29 | * callback once per match as the matches are discovered. |
18 | 30 | * |
19 | | - * .compile(selector) |
| 31 | + * .compile(selector, [ values ]) |
20 | 32 | * |
21 | 33 | * Parses the selector and compiles it to an internal form, and returns |
22 | 34 | * an object which contains the compiled selector and has two properties: |
|
523 | 535 | return a; |
524 | 536 | } |
525 | 537 |
|
526 | | - function compile(sel) { |
| 538 | + function format(sel, arr) { |
| 539 | + sel = sel.replace(/\?/g, function() { |
| 540 | + if (arr.length === 0) throw "too few parameters given"; |
| 541 | + var p = arr.shift(); |
| 542 | + return ((typeof p === 'string') ? JSON.stringify(p) : p); |
| 543 | + }); |
| 544 | + if (arr.length) throw "too many parameters supplied"; |
| 545 | + return sel; |
| 546 | + } |
| 547 | + |
| 548 | + function compile(sel, arr) { |
| 549 | + if (arr) sel = format(sel, arr); |
527 | 550 | return { |
528 | 551 | sel: parse(sel)[1], |
529 | 552 | match: function(obj){ |
|
537 | 560 |
|
538 | 561 | exports._lex = lex; |
539 | 562 | exports._parse = parse; |
540 | | - exports.match = function (sel, obj) { |
541 | | - return compile(sel).match(obj); |
| 563 | + exports.match = function (sel, arr, obj) { |
| 564 | + if (!obj) { obj = arr; arr = undefined; } |
| 565 | + return compile(sel, arr).match(obj); |
542 | 566 | }; |
543 | | - exports.forEach = function(sel, obj, fun) { |
544 | | - return compile(sel).forEach(obj, fun); |
| 567 | + exports.forEach = function(sel, arr, obj, fun) { |
| 568 | + if (!fun) { fun = obj; obj = arr; arr = undefined } |
| 569 | + return compile(sel, arr).forEach(obj, fun); |
545 | 570 | }; |
546 | 571 | exports.compile = compile; |
547 | 572 | })(typeof exports === "undefined" ? (window.JSONSelect = {}) : exports); |
0 commit comments