Bugfix : prendre le innerHTML du body du document n'est pas une bonne idée, dans...
[ckeditor.git] / skins / ckeditor / _source / plugins / stylesheetparser / plugin.js
1 /*
2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
4 */
5
6 /**
7 * @stylesheetParser plugin.
8 */
9
10 (function()
11 {
12 // We want to extract only the elements with classes defined in the stylesheets:
13 function parseClasses( aRules, skipSelectors, validSelectors )
14 {
15 // aRules are just the different rules in the style sheets
16 // We want to merge them and them split them by commas, so we end up with only
17 // the selectors
18 var s = aRules.join(' ');
19 // Remove selectors splitting the elements, leave only the class selector (.)
20 s = s.replace( /(,|>|\+|~)/g, ' ' );
21 // Remove attribute selectors: table[border="0"]
22 s = s.replace( /\[[^\]]*/g, '' );
23 // Remove Ids: div#main
24 s = s.replace( /#[^\s]*/g, '' );
25 // Remove pseudo-selectors and pseudo-elements: :hover :nth-child(2n+1) ::before
26 s = s.replace( /\:{1,2}[^\s]*/g, '' );
27
28 s = s.replace( /\s+/g, ' ' );
29
30 var aSelectors = s.split( ' ' ),
31 aClasses = [];
32
33 for ( var i = 0; i < aSelectors.length ; i++ )
34 {
35 var selector = aSelectors[ i ];
36
37 if ( validSelectors.test( selector ) && !skipSelectors.test( selector ) )
38 {
39 // If we still don't know about this one, add it
40 if ( CKEDITOR.tools.indexOf( aClasses, selector ) == -1 )
41 aClasses.push( selector );
42 }
43 }
44
45 return aClasses;
46 }
47
48 function LoadStylesCSS( theDoc, skipSelectors, validSelectors )
49 {
50 var styles = [],
51 // It will hold all the rules of the applied stylesheets (except those internal to CKEditor)
52 aRules = [],
53 i;
54
55 for ( i = 0; i < theDoc.styleSheets.length; i++ )
56 {
57 var sheet = theDoc.styleSheets[ i ],
58 node = sheet.ownerNode || sheet.owningElement;
59
60 // Skip the internal stylesheets
61 if ( node.getAttribute( 'data-cke-temp' ) )
62 continue;
63
64 // Exclude stylesheets injected by extensions
65 if ( sheet.href && sheet.href.substr(0, 9) == 'chrome://' )
66 continue;
67
68 var sheetRules = sheet.cssRules || sheet.rules;
69 for ( var j = 0; j < sheetRules.length; j++ )
70 aRules.push( sheetRules[ j ].selectorText );
71 }
72
73 var aClasses = parseClasses( aRules, skipSelectors, validSelectors );
74
75 // Add each style to our "Styles" collection.
76 for ( i = 0; i < aClasses.length; i++ )
77 {
78 var oElement = aClasses[ i ].split( '.' ),
79 element = oElement[ 0 ].toLowerCase(),
80 sClassName = oElement[ 1 ];
81
82 styles.push( {
83 name : element + '.' + sClassName,
84 element : element,
85 attributes : {'class' : sClassName}
86 });
87 }
88
89 return styles;
90 }
91
92 // Register a plugin named "stylesheetparser".
93 CKEDITOR.plugins.add( 'stylesheetparser',
94 {
95 requires: [ 'styles' ],
96 onLoad : function()
97 {
98 var obj = CKEDITOR.editor.prototype;
99 obj.getStylesSet = CKEDITOR.tools.override( obj.getStylesSet, function( org )
100 {
101 return function( callback )
102 {
103 var self = this;
104 org.call( this, function( definitions )
105 {
106 // Rules that must be skipped
107 var skipSelectors = self.config.stylesheetParser_skipSelectors || ( /(^body\.|^\.)/i ),
108 // Rules that are valid
109 validSelectors = self.config.stylesheetParser_validSelectors || ( /\w+\.\w+/ );
110
111 callback( ( self._.stylesDefinitions = definitions.concat( LoadStylesCSS( self.document.$, skipSelectors, validSelectors ) ) ) );
112 });
113 };
114 });
115
116 }
117 });
118 })();
119
120
121 /**
122 * A regular expression that defines whether a CSS rule will be
123 * skipped by the Stylesheet Parser plugin. A CSS rule matching
124 * the regular expression will be ignored and will not be available
125 * in the Styles drop-down list.
126 * @name CKEDITOR.config.stylesheetParser_skipSelectors
127 * @type RegExp
128 * @default /(^body\.|^\.)/i
129 * @since 3.6
130 * @see CKEDITOR.config.stylesheetParser_validSelectors
131 * @example
132 * // Ignore rules for body and caption elements, classes starting with "high", and any class defined for no specific element.
133 * config.stylesheetParser_skipSelectors = /(^body\.|^caption\.|\.high|^\.)/i;
134 */
135
136 /**
137 * A regular expression that defines which CSS rules will be used
138 * by the Stylesheet Parser plugin. A CSS rule matching the regular
139 * expression will be available in the Styles drop-down list.
140 * @name CKEDITOR.config.stylesheetParser_validSelectors
141 * @type RegExp
142 * @default /\w+\.\w+/
143 * @since 3.6
144 * @see CKEDITOR.config.stylesheetParser_skipSelectors
145 * @example
146 * // Only add rules for p and span elements.
147 * config.stylesheetParser_validSelectors = /\^(p|span)\.\w+/;
148 */