Roo/htmleditor/FilterWord.js
[roojs1] / Roo / htmleditor / FilterWord.js
1 /**
2  * @class Roo.htmleditor.FilterWord
3  * try and clean up all the mess that Word generates.
4  * 
5  * This is the 'nice version' - see 'Heavy' that white lists a very short list of elements, and multi-filters 
6  
7  * @constructor
8  * Run a new Span Filter
9  * @param {Object} config Configuration options
10  */
11
12 Roo.htmleditor.FilterWord = function(cfg)
13 {
14     // no need to apply config.
15     this.replaceDocBullets(cfg.node);
16     
17     this.walk(cfg.node);
18     
19     
20 }
21
22 Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
23 {
24     tag: true,
25      
26     
27     /**
28      * Clean up MS wordisms...
29      */
30     replaceTag : function(node)
31     {
32          
33         // no idea what this does - span with text, replaceds with just text.
34         if(
35                 node.nodeName == 'SPAN' &&
36                 !node.hasAttributes() &&
37                 node.childNodes.length == 1 &&
38                 node.firstChild.nodeName == "#text"  
39         ) {
40             var textNode = node.firstChild;
41             node.removeChild(textNode);
42             if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
43                 node.parentNode.insertBefore(node.ownerDocument.createTextNode(" "), node);
44             }
45             node.parentNode.insertBefore(textNode, node);
46             if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
47                 node.parentNode.insertBefore(node.ownerDocument.createTextNode(" ") , node);
48             }
49             
50             node.parentNode.removeChild(node);
51             return false; // dont do chidren - we have remove our node - so no need to do chdhilren?
52         }
53         
54    
55         
56         if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
57             node.parentNode.removeChild(node);
58             return false; // dont do chidlren
59         }
60         //Roo.log(node.tagName);
61         // remove - but keep children..
62         if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)) {
63             //Roo.log('-- removed');
64             while (node.childNodes.length) {
65                 var cn = node.childNodes[0];
66                 node.removeChild(cn);
67                 node.parentNode.insertBefore(cn, node);
68                 // move node to parent - and clean it..
69                 this.replaceTag(cn);
70             }
71             node.parentNode.removeChild(node);
72             /// no need to iterate chidlren = it's got none..
73             //this.iterateChildren(node, this.cleanWord);
74             return false; // no need to iterate children.
75         }
76         // clean styles
77         if (node.className.length) {
78             
79             var cn = node.className.split(/\W+/);
80             var cna = [];
81             Roo.each(cn, function(cls) {
82                 if (cls.match(/Mso[a-zA-Z]+/)) {
83                     return;
84                 }
85                 cna.push(cls);
86             });
87             node.className = cna.length ? cna.join(' ') : '';
88             if (!cna.length) {
89                 node.removeAttribute("class");
90             }
91         }
92         
93         if (node.hasAttribute("lang")) {
94             node.removeAttribute("lang");
95         }
96         
97         if (node.hasAttribute("style")) {
98             
99             var styles = node.getAttribute("style").split(";");
100             var nstyle = [];
101             Roo.each(styles, function(s) {
102                 if (!s.match(/:/)) {
103                     return;
104                 }
105                 var kv = s.split(":");
106                 if (kv[0].match(/^(mso-|line|font|background|margin|padding|color)/)) {
107                     return;
108                 }
109                 // what ever is left... we allow.
110                 nstyle.push(s);
111             });
112             node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
113             if (!nstyle.length) {
114                 node.removeAttribute('style');
115             }
116         }
117         return true; // do children
118         
119         
120         
121     },
122     
123     styleToObject: function(node)
124     {
125         var styles = node.getAttribute("style").split(";");
126         var ret = {};
127         Roo.each(styles, function(s) {
128             if (!s.match(/:/)) {
129                 return;
130             }
131             var kv = s.split(":");
132              
133             // what ever is left... we allow.
134             ret[kv[0]] = kv[1];
135         });
136         return ret;
137     }
138     
139     
140     replaceDocBullets : function(doc)
141     {
142         var listpara = doc.getElementsByClassName('MsoListParagraph');
143         while(listpara.length) {
144             this.replaceDocBullet(listpara.item(0));
145             //code
146         }
147     },
148     
149     replaceDocBullet : function(p)
150     {
151         // gather all the siblings.
152         var ns = p,
153             parent = p.parentNode,
154             items = []; 
155         while (ns) {
156             if (!ns.className.match(/MsoListParagraph/)) {
157                 break;
158             }
159             items.push(ns);
160             ns = ns.nextSibling;
161             
162         }
163         var ul = parent.ownerDocument.createElement('ul'); // what about number lists...
164         
165         items.forEach(function(n) {
166             parent.removeChild(n);
167             var spans = n.getElementsByTagName('span');
168             n.removeChild(spans.item(0)); // remove the fake bullet.
169             
170         });
171         
172         
173         
174         
175     }
176     
177     
178     
179 });