inliner.js
[app.webkitpdf] / inliner.js
1 /**
2  *
3  * Based on...
4  * CSS Inline Transform v0.1
5  * http://tikku.com/css-inline-transformer-simplified
6  * 
7  * Copyright 2010-2012, Nirvana Tikku
8  * Dual licensed under the MIT or GPL Version 2 licenses.
9  * https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt
10  * 
11  * This tool leverages the jQuery library.
12  * 
13  * Compatibility only tested with FireFox 3.5+, Chrome 5+
14  * 
15  * @author Nirvana Tikku
16  * @dependent jQuery 1.4
17  * @date Wed Mar 31 14:58:04 2010 -0500
18  * @updated Sat Mar 10 16:21:20 2012 -0500
19  * 
20  */
21
22 (function(){
23     
24     //
25     // private methods
26     //
27     /**
28      * @param stylesArray - the array of string 
29      *                  "{name}:{value};" pairs that are to be broken down
30      *
31      */
32     function createCSSRuleObject (stylesArray) {
33         var cssObj = {};
34         for(_s in stylesArray){
35                 var S = stylesArray[_s].split(":");
36                 if(S[0].trim()==""||S[1].trim()=="")continue;
37                 cssObj[S[0].trim()] = S[1].trim();
38         }
39         return cssObj;
40     }
41
42     /**
43      * @param $out - the tmp html content
44      * 
45      */
46     function interpritAppendedStylesheet ($out) { 
47         var stylesheet = $out[0].styleSheets[0]; // first stylesheet
48         for(r in stylesheet.cssRules){
49                 try{
50                         var rule = stylesheet.cssRules[r]; 
51                         if(!isNaN(rule))break; // make sure the rule exists
52                         var $destObj = $out.find(rule.selectorText);
53                         var obj = rule.cssText.replace(rule.selectorText, '');
54                         obj = obj.replace('{','').replace('}',''); // clean up the { and }'s
55                         var styles = obj.split(";"); // separate each 
56                         $destObj.css(createCSSRuleObject(styles)); // do the inline styling
57                 } catch (e) { }
58         }
59     };
60     
61     
62         function isPatternRelevant (newHTML, pattern, relevantPatterns) {
63             if( newHTML.indexOf(pattern) > -1 )
64                 relevantPatterns.push(new RegExp(pattern,"i"));
65         };
66
67     /**
68      * The main method - inflinify
69      *  this utilizes two text areas and a div for final output -  
70      *          (1) css input textarea for the css to apply
71      *          (2) html content for the css to apply TO
72      */
73     function inlinify () {
74         
75         interpritAppendedStylesheet(document); // apply styles to the document just created
76         $tmpDoc.find("style").remove(); // sanitize all style tags present prior to the transformation
77         
78         var newHTML = $tmpDoc.find("html").html();
79         tmpWindow.close();
80         
81         var relevantPatterns = [];
82         isPatternRelevant(newHTML, "href=\"", relevantPatterns);
83         isPatternRelevant(newHTML, "src=\"", relevantPatterns);
84         return sanitize( newHTML, relevantPatterns );
85     };
86     
87     function sanitize(html, patterns){
88         var ret = html;
89         for(var i=0; i<patterns.length; i++){
90             ret = san(ret, patterns[i])
91         }  
92         return ret;
93     };
94
95     /**
96      * This method will take HTML and a PATTERN and essentially
97      * sanitize the following chars within the HTML with that 
98      * pattern through a filter: 
99      *      Currently this only applies to &amp;' -> &
100      */
101     function san(html, pattern){
102     
103         var ret = "";
104         var remainingString;
105         var hrefIndex;
106         for(var i=0; i<html.length; i++){
107                 remainingString = html.substring(i);
108                 hrefIndex = remainingString.search(pattern);
109                 if( hrefIndex === 0 ){
110                     // actually sanitize the pattern, i.e. href="[sanitize-candidate]"
111                     // must be encapsulated within quotes, "
112                (function(){
113                    // get the start of what we will sanitize
114                    var startIndex = remainingString.indexOf("\"");
115                    // and the end 
116                    var endIndex = remainingString.indexOf("\"",startIndex+1);
117                    // get the data to sanitize
118                    var newHREF = html.substring(i+startIndex+1, i+endIndex+1);
119                    // here we actually perform the replacement
120                    newHREF = newHREF.replace(/&amp;/g, '&');
121                    // add the pattern + the new data + a closing quote
122                    var regExpStartLen = "/".length;
123                    var regExpFlagsLen = "/i".length;
124                    ret += String(pattern).substring( regExpStartLen, String(pattern).length - regExpFlagsLen)
125                         + newHREF;
126                    i += endIndex;
127                })();
128                continue;
129                 } else { 
130                     // if we have another href, copy everything until that href index
131                     if( hrefIndex > 0 ) {
132                         ret += html.substring(i, hrefIndex);
133                         i = hrefIndex-1;
134                     } else { 
135                         // otherwise just add the remaining chars and stop trying to sanitize
136                         ret += html.substring(i);
137                         break;
138                     }
139                 }
140         }
141         return ret;
142         
143     };
144     
145     //
146     // public methods
147     //
148     doInline = function(input) {
149         return inlinify(input);
150     }
151     
152 })();