'use strict'; var utils = require('./utils'); var numbers = require('./numbers'); module.exports = function makeJuiceClient(juiceClient) { juiceClient.ignoredPseudos = ['hover', 'active', 'focus', 'visited', 'link']; juiceClient.widthElements = ['TABLE', 'TD', 'TH', 'IMG']; juiceClient.heightElements = ['TABLE', 'TD', 'TH', 'IMG']; juiceClient.tableElements = ['TABLE', 'TH', 'TR', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'THEAD', 'TBODY', 'TFOOT']; juiceClient.nonVisualElements = [ 'HEAD', 'TITLE', 'BASE', 'LINK', 'STYLE', 'META', 'SCRIPT', 'NOSCRIPT' ]; juiceClient.styleToAttribute = { 'background-color': 'bgcolor', 'background-image': 'background', 'text-align': 'align', 'vertical-align': 'valign' }; juiceClient.excludedProperties = []; juiceClient.juiceDocument = juiceDocument; juiceClient.inlineDocument = inlineDocument; function inlineDocument($, css, options) { options = options || {}; var rules = utils.parseCSS(css); var editedElements = []; var styleAttributeName = 'style'; var counters = {}; if (options.styleAttributeName) { styleAttributeName = options.styleAttributeName; } rules.forEach(handleRule); editedElements.forEach(setStyleAttrs); if (options.inlinePseudoElements) { editedElements.forEach(inlinePseudoElements); } if (options.applyWidthAttributes) { editedElements.forEach(function(el) { setDimensionAttrs(el, 'width'); }); } if (options.applyHeightAttributes) { editedElements.forEach(function(el) { setDimensionAttrs(el, 'height'); }); } if (options.applyAttributesTableElements) { editedElements.forEach(setAttributesOnTableElements); } if (options.insertPreservedExtraCss && options.extraCss) { var preservedText = utils.getPreservedText(options.extraCss, { mediaQueries: options.preserveMediaQueries, fontFaces: options.preserveFontFaces, keyFrames: options.preserveKeyFrames }); if (preservedText) { var $appendTo = null; if (options.insertPreservedExtraCss !== true) { $appendTo = $(options.insertPreservedExtraCss); } else { $appendTo = $('head'); if (!$appendTo.length) { $appendTo = $('body'); } if (!$appendTo.length) { $appendTo = $.root(); } } $appendTo.first().append(''); } } function handleRule(rule) { var sel = rule[0]; var style = rule[1]; var selector = new utils.Selector(sel); var parsedSelector = selector.parsed(); if (!parsedSelector) { return; } var pseudoElementType = getPseudoElementType(parsedSelector); // skip rule if the selector has any pseudos which are ignored for (var i = 0; i < parsedSelector.length; ++i) { var subSel = parsedSelector[i]; if (subSel.pseudos) { for (var j = 0; j < subSel.pseudos.length; ++j) { var subSelPseudo = subSel.pseudos[j]; if (juiceClient.ignoredPseudos.indexOf(subSelPseudo.name) >= 0) { return; } } } } if (pseudoElementType) { var last = parsedSelector[parsedSelector.length - 1]; var pseudos = last.pseudos; last.pseudos = filterElementPseudos(last.pseudos); sel = parsedSelector.toString(); last.pseudos = pseudos; } var els; try { els = $(sel); } catch (err) { // skip invalid selector return; } els.each(function() { var el = this; if (el.name && juiceClient.nonVisualElements.indexOf(el.name.toUpperCase()) >= 0) { return; } if (pseudoElementType) { var pseudoElPropName = 'pseudo' + pseudoElementType; var pseudoEl = el[pseudoElPropName]; if (!pseudoEl) { pseudoEl = el[pseudoElPropName] = $('').get(0); pseudoEl.pseudoElementType = pseudoElementType; pseudoEl.pseudoElementParent = el; pseudoEl.counterProps = el.counterProps; el[pseudoElPropName] = pseudoEl; } el = pseudoEl; } if (!el.styleProps) { el.styleProps = {}; // if the element has inline styles, fake selector with topmost specificity if ($(el).attr(styleAttributeName)) { var cssText = '* { ' + $(el).attr(styleAttributeName) + ' } '; addProps(utils.parseCSS(cssText)[0][1], new utils.Selector('