3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
7 YUI.add('highlight-accentfold', function(Y) {
10 Adds accent-folding highlighters to `Y.Highlight`.
13 @submodule highlight-accentfold
21 var AccentFold = Y.Text.AccentFold,
26 Highlight = Y.mix(Y.Highlight, {
27 // -- Public Static Methods ------------------------------------------------
30 Accent-folding version of `all()`.
33 @param {String} haystack String to apply highlighting to.
34 @param {String|String[]} needles String or array of strings that should be
36 @param {Object} [options] Options object.
37 @param {Boolean} [options.startsWith=false] If `true`, matches must be
38 anchored to the beginning of the string.
39 @return {String} Escaped and highlighted copy of _haystack_.
42 allFold: function (haystack, needles, options) {
43 var template = Highlight._TEMPLATE,
46 chunk, i, len, match, result;
49 // This tells Highlight.all() not to escape HTML, in order to ensure
50 // usable match offsets. The output of all() is discarded, and we
51 // perform our own escaping before returning the highlighted string.
54 // While the highlight regex operates on the accent-folded strings,
55 // this replacer will highlight the matched positions in the
58 // Note: this implementation doesn't handle multi-character folds,
59 // like "æ" -> "ae". Doing so correctly would be prohibitively
60 // expensive both in terms of code size and runtime performance, so
61 // I've chosen to take the pragmatic route and just not do it at
62 // all. This is one of many reasons why accent folding is best done
64 replacer: function (match, p1, foldedNeedle, pos) {
67 // Ignore matches inside HTML entities.
68 if (p1 && !(/\s/).test(foldedNeedle)) {
72 len = foldedNeedle.length;
75 haystack.substring(startPos, pos), // substring between previous match and this match
76 haystack.substr(pos, len) // match to be highlighted
81 }, options || EMPTY_OBJECT);
83 // Run the highlighter on the folded strings. We don't care about the
84 // output; our replacer function will build the canonical highlighted
85 // string, with original accented characters.
86 Highlight.all(AccentFold.fold(haystack), AccentFold.fold(needles), options);
88 // Tack on the remainder of the haystack that wasn't highlighted, if
90 if (startPos < haystack.length) {
91 results.push([haystack.substr(startPos)]);
94 // Highlight and escape the string.
95 for (i = 0, len = results.length; i < len; ++i) {
96 chunk = Escape.html(results[i][0]);
98 if ((match = results[i][1])) {
99 chunk += template.replace(/\{s\}/g, Escape.html(match));
105 return results.join('');
109 Accent-folding version of `start()`.
112 @param {String} haystack String to apply highlighting to.
113 @param {String|String[]} needles String or array of strings that should be
115 @return {String} Escaped and highlighted copy of _haystack_.
118 startFold: function (haystack, needles) {
119 return Highlight.allFold(haystack, needles, {startsWith: true});
123 Accent-folding version of `words()`.
126 @param {String} haystack String to apply highlighting to.
127 @param {String|String[]} needles String or array of strings containing words
128 that should be highlighted. If a string is passed, it will be split
129 into words; if an array is passed, it is assumed to have already been
131 @return {String} Escaped and highlighted copy of _haystack_.
134 wordsFold: function (haystack, needles) {
135 var template = Highlight._TEMPLATE;
137 return Highlight.words(haystack, AccentFold.fold(needles), {
138 mapper: function (word, needles) {
139 if (needles.hasOwnProperty(AccentFold.fold(word))) {
140 return template.replace(/\{s\}/g, Escape.html(word));
143 return Escape.html(word);
150 }, '3.5.0' ,{requires:['highlight-base', 'text-accentfold']});