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 | */
|
---|