mozilla
Your Search Results

    Template:MDN:Common

    <% var MDN = module.exports = {
        
        /**
         * Return an HTML link using the given url, text, and title.
         */
        link: function (url, text, title) {
            var e = MDN.htmlEscapeArgs(['url', 'text', 'title'], arguments);
            return [
                '<a href="', e.url, '" title="', e.title, '">',
                e.text,
                '</a>'
            ].join('');
        },
        
        /**
         * Given a set of names and a corresponding list of values, apply HTML
         * escaping to each of the values and return an object with the results
         * associated with the names.
         */
        htmlEscapeArgs: function (names, args) {
            var e = {};
            names.forEach(function (name, idx) {
                e[name] = kuma.htmlEscape(args[idx]);
            });
            return e;
        },
        
        /**
         * Given a set of strings like this:
         *     { "en-US": "Foo", "de": "Bar", "es": "Baz" }
         * Return the one which matches the current locale.
         */
        localString: function (strings) {
            var lang = env.locale;
            if (!(lang in strings)) lang = 'en-US';
            return strings[lang];
        },
        
        getLocalString: function (strings, key) {
            var lang = env.locale;
            if (!(lang in strings[key])) lang = 'en-US';
            return strings[key][lang];
        },
        
        /**
         * Given a string, replaces all placeholders outlined by $1$, $2$, etc.
         * within it.
         * 
         * The number within the placeholder indicates the index within the
         * replacement array starting by 1.
         * 
         * Example:
         *   replacePlaceholders("$1$ $2$, $1$ $3$", ["hello", "world", "editor"])
         *   => "hello world, hello editor"
         */
        replacePlaceholders: function (string, replacements) {
            function replacePlaceholder(placeholder, offset, string) {
              var index = placeholder.substring(1, placeholder.length - 1) - 1;
              return index < replacements.length ? replacements[index] : '';
            }
    
            return string.replace(/\$\d+\$/g, replacePlaceholder);
        },
    
        /**
         * Given a string, escapes all quotes within it.
         */
        escapeQuotes: function(a) {
            var b = "";
            for (var i = 0, len = a.length; i < len; i++) {
                var c = a[i];
                if (c=="\"") c = "&quot;";
                b += c;
            }
            return b.replace(/(<([^>]+)>)/ig, "");
        },
    
        /**
         * Accepts a relative URL or an attachment object
         * Returns the content of a given file.
         */
        getFileContent: function(fileObjOrUrl) {
            var url = fileObjOrUrl.url || fileObjOrUrl;
            if(!url) return '';
            
            var result = '',
                base_url = '';
            
            // New file urls include attachment host, so we don't need to prepend it
            var fUrl = kuma.url.parse(url);
            if (!fUrl.host) {
                var p = kuma.url.parse(env.url, true),
                    base_url = p.protocol + '//' + p.host;
            }
            url = base_url + url;
            return cacheFn('kuma:get_attachment_content:' + md5(url.toLowerCase()), 3600, function(next) {
                try {
                    request({
                        method: 'GET',
                        headers: { 'Cache-Control': env.cache_control },
                        url: url
                    }, function(err, resp, body) {
                        if(resp && 200 == resp.statusCode) {
                            next(body);
                        }
                        else if(err) {
                            next(null);
                        }
                    });
                } catch(e) {
                    next("error: " + e);
                }
            });
        },
    
        /**
         * #### cacheFnIgnoreCacheControl
         * Cache a function, and use cached results no matter what 
         * Cache-Control we get from a shift-refresh.
         */
        cacheFnIgnoreCacheControl: function (key, tm_out, to_cache) {
            var result = null,
                err_result = null,
                f = new Future(),
                mc = memcached;
            mc.get(key, function (err, c_result) {
                if (c_result) {
                    result = c_result;
                    f['return']();
                } else {
                    try {
                        to_cache(function (val) {
                            mc.set(key, val, tm_out, function (err, c_result) {
                                result = val;
                                f['return']();
                            });
                        });
                    } catch (e) {
                        err_result = e;
                        result = '';
                        f['return']();
                    }
                }
            });
            f.wait();
            if (err_result) { throw err_result; }
            return result;
        },
        
        // #### memcacheSet(key, value, timeout)
        //
        // Store a value in memcache with the given key and timeout (in seconds)
        memcacheSet: function (key, value, tmout) {
            var result = null,
                err_result = null,
                f = new Future(),
                mc = memcached;
            mc.set(key, value, tmout, function (err, c_result) {
                err_result = err;
                result = c_result;
                f['return']();
            });
            f.wait();
            if (err_result) { throw err_result; }
            return result;
        },
        
        // #### memcacheGet(key)
        //
        // Fetch the value for a key from memcache
        memcacheGet: function (key) {
            var result = null,
                err_result = null,
                f = new Future(),
                mc = memcached;
            mc.get(key, function (err, c_result) {
                err_result = err;
                result = c_result;
                f['return']();
            });
            f.wait();
            if (err_result) { throw err_result; }
            return result;
        },
        
        // #### defaults(object, *defaults)
        //
        // Fill in undefined properties in object with values from the defaults 
        // objects, and return the object. As soon as the property is filled, 
        // further defaults will have no effect.
        //
        // Stolen from http://underscorejs.org/#defaults
        defaults: function (obj) {
            Array.prototype.slice.call(arguments, 1).forEach(function(source) {
                if (source) {
                    for (var prop in source) {
                        if (obj[prop] === void 0) obj[prop] = source[prop];
                    }
                }
            });
            return obj;
        },
            
        // #### fetchJSONResource
        // Fetch an HTTP resource with JSON representation, parse the JSON and 
        // return a JS object.
        fetchJSONResource: function (url, opts) {
            opts = MDN.defaults(opts || {}, {
                headers: { 'Cache-Control': env.cache_control, 
                           'Accept': 'application/json',
                           'Content-Type': 'application/json' },
            });
            return JSON.parse(MDN.fetchHTTPResource(url, opts));
        },
        
        // #### fetchHTTPResource
        // Fetch an HTTP resource, return the response body.
        fetchHTTPResource: function (url, opts) {
            opts = MDN.defaults(opts || {}, {
                method: 'GET',
                headers: { 'Cache-Control': env.cache_control, 
                           'Accept': "text/plain",
                           'Content-Type': "text/plain" },
                url: url,
                cache_key: 'kuma:http_resource:' + md5(url.toLowerCase()),
                cache_timeout: 3600,
                ignore_cache_control: false
            });
            var to_cache = function (next) {
                try {
                    var req = request.get(opts);
                    req.on('response', function(res) {
                        var chunks = [];
                        var content_length = 0;
                        res.on('error', function(chunk) {
                            next(null);
                        });
                        res.on('data', function(chunk) {
                            chunks.push(chunk);
                            content_length += chunk.length;
                        });
                        res.on('end', function() {
                            var buffer = new Buffer(content_length);
                            var offset = 0;
                            for (var i=0; i<chunks.length; i++) {
                                chunks[i].copy(buffer, offset);
                                offset += chunks[i].length;
                            }
                            var encoding = res.headers['content-encoding'];
                            if (encoding == 'gzip') {
                                zlib.gunzip(buffer, function(err, decoded) {
                                    next(decoded && decoded.toString());
                                });
                            } else if (encoding == 'deflate') {
                                zlib.inflate(buffer, function(err, decoded) {
                                  next(decoded && decoded.toString());
                                })
                            } else {
                                next(buffer.toString());
                            }
                        });
                    });                 
                    req.on('error', function(err) { next(null); });                
                } catch (e) {
                    next(null);
                }            
            };
            if (opts.ignore_cache_control) {
                return MDN.cacheFnIgnoreCacheControl(opts.cache_key, opts.cache_timeout, to_cache);
            } else {
                return cacheFn(opts.cache_key, opts.cache_timeout, to_cache);
            }
        },
        
        /* Returns the appropriate string (usually a comma+space) for usage in a enumeration list for the current locale */
        listSeparator: function() {
            var listSeparators = { "en-US": ", ", "ar": "،", "fa": "،", "ja": "、", "ko": "·", "mn": "᠂", "ur": "،", "zh−TW": "、" };
            return mdn.localString(listSeparators);
        },
        
        /*
         * FILE READING
         *
         * Utilities to read various files.
         */
    
        CSVToArray: function( strData, strDelimiter ) {
          // Check to see if the delimiter is defined. If not,
          // then default to comma.
          strDelimiter = (strDelimiter || ",");
        
          // Create a regular expression to parse the CSV values.
          var objPattern = new RegExp(
            (
              // Delimiters.
              "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
        
              // Quoted fields.
              "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
        
              // Standard fields.
              "([^\"\\" + strDelimiter + "\\r\\n]*))"
            ),
            "gi"
            );
        
        
          // Create an array to hold our data. Give the array
          // a default empty first row.
          var arrData = [[]];
        
          // Create an array to hold our individual pattern
          // matching groups.
          var arrMatches = null;
        
        
          // Keep looping over the regular expression matches
          // until we can no longer find a match.
          while (arrMatches = objPattern.exec( strData )){
        
            // Get the delimiter that was found.
            var strMatchedDelimiter = arrMatches[ 1 ];
        
            // Check to see if the given delimiter has a length
            // (is not the start of string) and if it matches
            // field delimiter. If id does not, then we know
            // that this delimiter is a row delimiter.
            if (
              strMatchedDelimiter.length &&
              (strMatchedDelimiter != strDelimiter)
              ){
        
              // Since we have reached a new row of data,
              // add an empty row to our data array.
              arrData.push( [] );
        
            }
        
        
            // Now that we have our delimiter out of the way,
            // let's check to see which kind of value we
            // captured (quoted or unquoted).
            if (arrMatches[ 2 ]){
        
              // We found a quoted value. When we capture
              // this value, unescape any double quotes.
              var strMatchedValue = arrMatches[ 2 ].replace(
                new RegExp( "\"\"", "g" ),
                "\""
                );
        
            } else {
        
              // We found a non-quoted value.
              var strMatchedValue = arrMatches[ 3 ];
        
            }
        
        
            // Now that we have our value string, let's add
            // it to the data array.
            arrData[ arrData.length - 1 ].push( strMatchedValue );
          }
        
          // Return the parsed data.
          return( arrData );
        },
        
        loadArrayFromCSV: function(url, separator) {
            url = url.replace(/&amp;/i, "&");
            var html = MDN.fetchHTTPResource(url, {
                headers: { 'Cache-Control': env.cache_control, 
                           'Accept': 'text/csv',
                           'Content-Type': 'text/csv' },
            });
            return MDN.CSVToArray(html, separator);
        },
        
        /* http://www.bugzilla.org/docs/4.2/en/html/api/Bugzilla/WebService/Bug.html#search */
        bzSearch: function (query) {
            /* Fix colon (":") encoding problems */
            query = query.replace(/&amp;/g, "&");
            query = encodeURI(query);
            query = query.replace(/&/g, "%26");
            var url = 'https://bugzilla.mozilla.org/jsonrpc.cgi?method=Bug.search&params=' + query;
            var resource = MDN.fetchJSONResource(url);
            return resource.result;
        }
    } %>
    Search for pages that use Template:MDN:Common to see example use cases and how many pages use this macro.

    Document Tags and Contributors

    Last updated by: fscholz,