/** * @param {!Tag} tag The original tag * @param {!Object} hosts Map of [host => siteId] * @param {!Object} sites Map of [siteId => siteConfig] * @param {string} cacheDir */ function (tag, hosts, sites, cacheDir) { /** * Filter a MEDIA tag * * This will always invalidate the original tag, and possibly replace it with the tag that * corresponds to the media site * * @param {!Tag} tag The original tag * @param {!Object} hosts Map of [host => siteId] * @param {!Object} sites Map of [siteId => siteConfig] */ function filterTag(tag, hosts, sites) { // Always invalidate this tag tag.invalidate(); if (tag.hasAttribute('url')) { var url = tag.getAttribute('url'), siteId = getSiteIdFromUrl(url, hosts); if (sites[siteId]) { var attributes = getAttributes(url, sites[siteId]); if (!empty(attributes)) { createTag(siteId.toUpperCase(), tag).setAttributes(attributes); } } } } /** * Add named captures from a set of regular expressions to a set of attributes * * @param {!Object} attributes Associative array of strings * @param {string} string Text to match * @param {!Array} regexps List of [regexp, map] pairs * @return {boolean} Whether any regexp matched */ function addNamedCaptures(attributes, string, regexps) { var matched = false; regexps.forEach(function(pair) { var regexp = pair[0], map = pair[1], m = regexp.exec(string); if (!m) { return; } matched = true; map.forEach(function(name, i) { if (m[i] > '' && name > '') { attributes[name] = m[i]; } }); }); return matched; } /** * Create a tag for a media embed * * @param {string} tagName Tag's name * @param {!Tag} tag Reference tag * @return {!Tag} New tag */ function createTag(tagName, tag) { var startPos = tag.getPos(), endTag = tag.getEndTag(), startLen, endPos, endLen; if (endTag) { startLen = tag.getLen(); endPos = endTag.getPos(); endLen = endTag.getLen(); } else { startLen = 0; endPos = tag.getPos() + tag.getLen(); endLen = 0; } return addTagPair(tagName, startPos, startLen, endPos, endLen, tag.getSortPriority()); } /** * @param {!Object} attributes * @return {boolean} */ function empty(attributes) { for (var attrName in attributes) { return false; } return true; } /** * Return a set of attributes for given URL based on a site's config * * @param {string} url Original URL * @param {!Object} config Site config * @return {!Object} Attributes */ function getAttributes(url, config) { var attributes = {}; addNamedCaptures(attributes, url, config[0]); return attributes; } /** * Return the siteId that corresponds to given URL * * @param {string} url Original URL * @param {!Object} hosts Map of [hostname => siteId] * @return {string} URL's siteId, or an empty string */ function getSiteIdFromUrl(url, hosts) { var m = /^https?:\/\/([^\/]+)/.exec(url.toLowerCase()), host = m[1] || ''; while (host > '') { if (hosts[host]) { return hosts[host]; } host = host.replace(/^[^.]*./, ''); } return ''; } filterTag(tag, hosts, sites); }