src/cm/media/js/lib/yui/yui3-3.15.0/build/highlight-base/highlight-base-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('highlight-base', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4 Provides methods for highlighting strings within other strings by wrapping
       
     5 them in HTML.
       
     6 
       
     7 @module highlight
       
     8 @submodule highlight-base
       
     9 @main
       
    10 @since 3.3.0
       
    11 **/
       
    12 
       
    13 /**
       
    14 Provides methods for highlighting strings within other strings by wrapping
       
    15 them in HTML.
       
    16 
       
    17 The highlight methods first escape any special HTML characters in the input
       
    18 strings and then highlight the appropriate substrings by wrapping them in a
       
    19 `<b class="yui3-highlight"></b>` element. The `<b>` element is used rather than
       
    20 `<strong>` in accordance with HTML5's definition of `<b>` as being purely
       
    21 presentational, which is exactly what highlighting is.
       
    22 
       
    23 @class Highlight
       
    24 @static
       
    25 **/
       
    26 
       
    27 var YArray    = Y.Array,
       
    28     Escape    = Y.Escape,
       
    29     WordBreak = Y.Text.WordBreak,
       
    30 
       
    31     isArray = Y.Lang.isArray,
       
    32 
       
    33     EMPTY_OBJECT = {},
       
    34 
       
    35     // Regex string that captures zero or one unclosed HTML entities. Used in
       
    36     // the static regex template properties below. The entity matching is
       
    37     // intentionally loose here, since there's a world of complexity involved in
       
    38     // doing strict matching for this use case.
       
    39     UNCLOSED_ENTITY = '(&[^;\\s]*)?',
       
    40 
       
    41 Highlight = {
       
    42     // -- Protected Static Properties ------------------------------------------
       
    43 
       
    44     /**
       
    45     Regular expression template for highlighting a match that occurs anywhere
       
    46     in a string. The placeholder `%needles` will be replaced with a list of
       
    47     needles to match, joined by `|` characters.
       
    48 
       
    49     This regex should have two capturing subpatterns:
       
    50 
       
    51       1. Zero or one unclosed HTML entity (e.g. "&amp" without a ";" at the
       
    52          end).
       
    53       2. The `%needles` placeholder.
       
    54 
       
    55     The first subpattern match is used to emulate a negative lookbehind
       
    56     assertion in order to prevent highlighting inside HTML entities.
       
    57 
       
    58     @property _REGEX
       
    59     @type String
       
    60     @protected
       
    61     @static
       
    62     @final
       
    63     **/
       
    64     _REGEX: UNCLOSED_ENTITY + '(%needles)',
       
    65 
       
    66     /**
       
    67     Regex replacer function or string for normal matches.
       
    68 
       
    69     @property _REPLACER
       
    70     @type Function|String
       
    71     @protected
       
    72     @static
       
    73     @final
       
    74     **/
       
    75     _REPLACER: function (match, p1, p2) {
       
    76          // Mimicking a negative lookbehind assertion to prevent matches inside
       
    77          // HTML entities. Hat tip to Steven Levithan for the technique:
       
    78          // http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript
       
    79          return p1 && !(/\s/).test(p2) ? match :
       
    80                     Highlight._TEMPLATE.replace(/\{s\}/g, p2);
       
    81      },
       
    82 
       
    83     /**
       
    84     Regular expression template for highlighting start-of-string matches
       
    85     (i.e., only matches that occur at the beginning of a string). The
       
    86     placeholder `%needles` will be replaced with a list of needles to match,
       
    87     joined by `|` characters.
       
    88 
       
    89     See `_REGEX` for a description of the capturing subpatterns this regex
       
    90     string should contain.
       
    91 
       
    92     @property _START_REGEX
       
    93     @type String
       
    94     @protected
       
    95     @static
       
    96     @final
       
    97      */
       
    98     _START_REGEX: '^' + UNCLOSED_ENTITY + '(%needles)',
       
    99 
       
   100     /**
       
   101     Highlight template which will be used as a replacement for matched
       
   102     substrings. The placeholder `{s}` will be replaced with the matched
       
   103     substring.
       
   104 
       
   105     @property _TEMPLATE
       
   106     @type String
       
   107     @default '<b class="yui3-highlight">{s}</b>'
       
   108     @protected
       
   109     @static
       
   110     @final
       
   111     **/
       
   112     _TEMPLATE: '<b class="' + Y.ClassNameManager.getClassName('highlight') + '">{s}</b>',
       
   113 
       
   114     // -- Public Static Methods ------------------------------------------------
       
   115 
       
   116     /**
       
   117     Highlights all occurrences in the _haystack_ string of the items in the
       
   118     _needles_ array, regardless of where they occur. The returned string will
       
   119     have all HTML characters escaped except for the highlighting markup.
       
   120 
       
   121     @method all
       
   122     @param {String} haystack String to apply highlighting to.
       
   123     @param {String|String[]} needles String or array of strings that should be
       
   124         highlighted.
       
   125     @param {Object} [options] Options object.
       
   126     @param {Boolean} [options.caseSensitive=false] If `true`, matching will
       
   127         be case-sensitive.
       
   128     @param {Boolean} [options.startsWith=false] If `true`, matches must be
       
   129         anchored to the beginning of the string.
       
   130     @return {String} Escaped and highlighted copy of _haystack_.
       
   131     @static
       
   132     **/
       
   133     all: function (haystack, needles, options) {
       
   134         var validNeedles = [],
       
   135             esc, i, len, needle, regex, replacer;
       
   136 
       
   137         if (!options) {
       
   138             options = EMPTY_OBJECT;
       
   139         }
       
   140 
       
   141         // TODO: document options.replacer
       
   142         esc      = options.escapeHTML !== false;
       
   143         regex    = options.startsWith ? Highlight._START_REGEX : Highlight._REGEX;
       
   144         replacer = options.replacer || Highlight._REPLACER;
       
   145         needles  = isArray(needles) ? needles : [needles];
       
   146 
       
   147         // Escape HTML characters and special regular expression characters in
       
   148         // the needles so they can be used in a regex and matched against the
       
   149         // escaped haystack.
       
   150         for (i = 0, len = needles.length; i < len; ++i) {
       
   151             needle = needles[i];
       
   152 
       
   153             if (needle) {
       
   154                 validNeedles.push(Escape.regex(esc ? Escape.html(needle) : needle));
       
   155             }
       
   156         }
       
   157 
       
   158         // Escape HTML characters in the haystack to prevent HTML injection.
       
   159         if (esc) {
       
   160             haystack = Escape.html(haystack);
       
   161         }
       
   162 
       
   163         // No point continuing if there are no needles.
       
   164         if (!validNeedles.length) {
       
   165             return haystack;
       
   166         }
       
   167 
       
   168         return haystack.replace(
       
   169             new RegExp(
       
   170                 regex.replace('%needles', validNeedles.join('|')),
       
   171                 options.caseSensitive ? 'g' : 'gi'
       
   172             ),
       
   173             replacer
       
   174         );
       
   175     },
       
   176 
       
   177     /**
       
   178     Same as `all()`, but case-sensitive by default.
       
   179 
       
   180     @method allCase
       
   181     @param {String} haystack String to apply highlighting to.
       
   182     @param {String|String[]} needles String or array of strings that should be
       
   183       highlighted.
       
   184     @param {Object} [options] Options object. See `all()` for details.
       
   185     @return {String} Escaped and highlighted copy of _haystack_.
       
   186     @static
       
   187     **/
       
   188     allCase: function (haystack, needles, options) {
       
   189         return Highlight.all(haystack, needles,
       
   190                 Y.merge(options || EMPTY_OBJECT, {caseSensitive: true}));
       
   191     },
       
   192 
       
   193     /**
       
   194     Highlights _needles_ that occur at the start of _haystack_. The returned
       
   195     string will have all HTML characters escaped except for the highlighting
       
   196     markup.
       
   197 
       
   198     @method start
       
   199     @param {String} haystack String to apply highlighting to.
       
   200     @param {String|String[]} needles String or array of strings that should be
       
   201       highlighted.
       
   202     @param {Object} [options] Options object.
       
   203     @param {Boolean} [options.caseSensitive=false] If `true`, matching will
       
   204         be case-sensitive.
       
   205     @return {String} Escaped and highlighted copy of _haystack_.
       
   206     @static
       
   207     **/
       
   208     start: function (haystack, needles, options) {
       
   209         return Highlight.all(haystack, needles,
       
   210                 Y.merge(options || EMPTY_OBJECT, {startsWith: true}));
       
   211     },
       
   212 
       
   213     /**
       
   214     Same as `start()`, but case-sensitive by default.
       
   215 
       
   216     @method startCase
       
   217     @param {String} haystack String to apply highlighting to.
       
   218     @param {String|String[]} needles String or array of strings that should be
       
   219       highlighted.
       
   220     @return {String} Escaped and highlighted copy of _haystack_.
       
   221     @static
       
   222     **/
       
   223     startCase: function (haystack, needles) {
       
   224         // No options passthru for now, since it would be redundant. If start()
       
   225         // ever supports more options than caseSensitive, then we'll start
       
   226         // passing the options through.
       
   227         return Highlight.start(haystack, needles, {caseSensitive: true});
       
   228     },
       
   229 
       
   230     /**
       
   231     Highlights complete words in the _haystack_ string that are also in the
       
   232     _needles_ array. The returned string will have all HTML characters escaped
       
   233     except for the highlighting markup.
       
   234 
       
   235     @method words
       
   236     @param {String} haystack String to apply highlighting to.
       
   237     @param {String|String[]} needles String or array of strings containing words
       
   238       that should be highlighted. If a string is passed, it will be split
       
   239       into words; if an array is passed, it is assumed to have already been
       
   240       split.
       
   241     @param {Object} [options] Options object.
       
   242     @param {Boolean} [options.caseSensitive=false] If `true`, matching will
       
   243         be case-sensitive.
       
   244     @return {String} Escaped and highlighted copy of _haystack_.
       
   245     @static
       
   246     **/
       
   247     words: function (haystack, needles, options) {
       
   248         var caseSensitive,
       
   249             mapper,
       
   250             template = Highlight._TEMPLATE,
       
   251             words;
       
   252 
       
   253         if (!options) {
       
   254             options = EMPTY_OBJECT;
       
   255         }
       
   256 
       
   257         caseSensitive = !!options.caseSensitive;
       
   258 
       
   259         // Convert needles to a hash for faster lookups.
       
   260         needles = YArray.hash(
       
   261             isArray(needles) ? needles : WordBreak.getUniqueWords(needles, {
       
   262                 ignoreCase: !caseSensitive
       
   263             })
       
   264         );
       
   265 
       
   266         // The default word mapping function can be overridden with a custom
       
   267         // one. This is used to implement accent-folded highlighting in the
       
   268         // highlight-accentfold module.
       
   269         mapper = options.mapper || function (word, needles) {
       
   270             if (needles.hasOwnProperty(caseSensitive ? word : word.toLowerCase())) {
       
   271                 return template.replace(/\{s\}/g, Escape.html(word));
       
   272             }
       
   273 
       
   274             return Escape.html(word);
       
   275         };
       
   276 
       
   277         // Split the haystack into an array of words, including punctuation and
       
   278         // whitespace so we can rebuild the string later.
       
   279         words = WordBreak.getWords(haystack, {
       
   280             includePunctuation: true,
       
   281             includeWhitespace : true
       
   282         });
       
   283 
       
   284         return YArray.map(words, function (word) {
       
   285             return mapper(word, needles);
       
   286         }).join('');
       
   287     },
       
   288 
       
   289     /**
       
   290     Same as `words()`, but case-sensitive by default.
       
   291 
       
   292     @method wordsCase
       
   293     @param {String} haystack String to apply highlighting to.
       
   294     @param {String|String[]} needles String or array of strings containing words
       
   295       that should be highlighted. If a string is passed, it will be split
       
   296       into words; if an array is passed, it is assumed to have already been
       
   297       split.
       
   298     @return {String} Escaped and highlighted copy of _haystack_.
       
   299     @static
       
   300     **/
       
   301     wordsCase: function (haystack, needles) {
       
   302         // No options passthru for now, since it would be redundant. If words()
       
   303         // ever supports more options than caseSensitive, then we'll start
       
   304         // passing the options through.
       
   305         return Highlight.words(haystack, needles, {caseSensitive: true});
       
   306     }
       
   307 };
       
   308 
       
   309 Y.Highlight = Highlight;
       
   310 
       
   311 
       
   312 }, '@VERSION@', {"requires": ["array-extras", "classnamemanager", "escape", "text-wordbreak"]});