diff -u b/editors/ckeditor.inc b/editors/ckeditor.inc
--- b/editors/ckeditor.inc
+++ b/editors/ckeditor.inc
@@ -121,46 +121,37 @@
}
/**
- * Implements the 'settings form callback' callback for CKEditor.
+ * Enhances the editor profile settings form for CKEditor.
*
- * This callback:
- * - Changes the description on the 'CSS Classes' element.
- * - Defines an element validator on the 'CSS Classes' element.
- * or
- * - Hides the 'CSS Classes' element if the CKEditor version is too old.
+ * Adds support for CKEditor's advanced stylesSets, which are a more advanced
+ * implementation and combination of block formats and font styles that allow
+ * to adjust the HTML element, attributes, and CSS styles at once.
*
- * @param array $form
- * An associative array containing the structure of the form.
- * @param array $form_state
- * A keyed array containing the current state of the form.
+ * @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Styles
+ * @see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html#.stylesSet
*/
function wysiwyg_ckeditor_settings_form(&$form, &$form_state) {
$editor = wysiwyg_get_editor($form['editor']['#value']);
if (version_compare($editor['installed version'], '3.2.1', '>=')) {
- $form['css']['css_classes']['#description'] = t('Optionally define CSS classes for the "Font style" dropdown list.
Enter one class on each line in the format: !format. Example: !example
If left blank, CSS classes are automatically imported from all loaded stylesheet(s).',
- array('!format' => '[title]=[element].[class]
', '!example' => 'My heading=h1.header1'));
- $form['css']['css_classes']['#element_validate'][] = 'wysiwyg_ckeditor_settings_form_css_classes_validate';
+ // Replace CSS classes element description to explain the advanced syntax.
+ $form['css']['css_classes']['#description'] = t('Optionally define CSS classes for the "Font style" dropdown list.
Enter one class on each line in the format: !format. Example: !example
If left blank, CSS classes are automatically imported from loaded stylesheet(s).', array(
+ '!format' => '[label]=[element].[class]
',
+ '!example' => 'Title=h1.title
',
+ ));
+ $form['css']['css_classes']['#element_validate'][] = 'wysiwyg_ckeditor_settings_form_validate_css_classes';
}
else {
- // Do not show elements that do not work in the currently installed version.
+ // Versions below 3.2.1 do not support Font styles at all.
$form['css']['css_classes']['#access'] = FALSE;
}
}
/**
- * Implements a form validator for the CSS Classes element of the settings form.
- *
- * @param array $element
- * An associative array containing the form element to validate.
- * @param array $form_state
- * A keyed array containing the current state of the form.
- * @param array $form
- * An associative array containing the structure of the form.
+ * #element_validate handler for CSS classes element altered by wysiwyg_ckeditor_settings_form().
*/
-function wysiwyg_ckeditor_settings_form_css_classes_validate($element, &$form_state, $form) {
- $errors = wysiwyg_ckeditor_parse_styles_set($element['#value'], TRUE);
- if (!empty($errors)) {
- form_error($element, t('Incorrect syntax for the CSS Classes. See the description for how to use this option.'));
+function wysiwyg_ckeditor_settings_form_validate_css_classes($element, &$form_state) {
+ if (wysiwyg_ckeditor_settings_parse_styles($element['#value']) === FALSE) {
+ form_error($element, t('The specified CSS classes are syntactically incorrect.'));
}
}
@@ -233,10 +224,11 @@
}
}
- // Get additional styles, supported in versions 3.2.1 and above.
- if (!empty($config['css_classes']) && version_compare($editor['installed version'], '3.2.1', '>=')) {
- $styles = wysiwyg_ckeditor_parse_styles_set($config['css_classes']);
- if (!empty($styles)) {
+ // Parse and define the styles set for the Styles plugin (3.2.1+).
+ // @todo This should be a plugin setting, but Wysiwyg does not support
+ // plugin-specific settings yet.
+ if (!empty($config['buttons']['default']['Styles']) && version_compare($editor['installed version'], '3.2.1', '>=')) {
+ if ($styles = wysiwyg_ckeditor_settings_parse_styles($config['css_classes'])) {
$settings['stylesSet'] = $styles;
}
}
@@ -302,6 +294,51 @@
}
/**
+ * Parses CSS classes settings string into a stylesSet JavaScript settings array.
+ *
+ * @param string $css_classes
+ * A string containing CSS class definitions to add to the Style dropdown
+ * list, separated by newlines.
+ *
+ * @return array|false
+ * An array containing the parsed stylesSet definition, or FALSE on parse
+ * error.
+ *
+ * @see wysiwyg_ckeditor_settings_form()
+ * @see wysiwyg_ckeditor_settings_form_validate_css_classes()
+ *
+ * @todo This should be a plugin setting, but Wysiwyg does not support
+ * plugin-specific settings yet.
+ */
+function wysiwyg_ckeditor_settings_parse_styles($css_classes) {
+ $set = array();
+ $input = trim($css_classes);
+ if (empty($input)) {
+ return $set;
+ }
+ // Handle both Unix and Windows line-endings.
+ foreach (explode("\n", str_replace("\r", '', $input)) as $line) {
+ $line = trim($line);
+ // [label]=[element].[class][.[class]][...] pattern expected.
+ if (!preg_match('@^.+= *[a-zA-Z0-9]+(\.[a-zA-Z0-9_ -]+)*$@', $line)) {
+ return FALSE;
+ }
+ list($label, $selector) = explode('=', $line, 2);
+ $classes = explode('.', $selector);
+ $element = array_shift($classes);
+
+ $style = array();
+ $style['name'] = trim($label);
+ $style['element'] = trim($element);
+ if (!empty($classes)) {
+ $style['attributes']['class'] = implode(' ', array_map('trim', $classes));
+ }
+ $set[] = $style;
+ }
+ return $set;
+}
+
+/**
* Build a JS settings array of native external plugins that need to be loaded separately.
*/
function wysiwyg_ckeditor_plugin_settings($editor, $profile, $plugins) {
@@ -400,52 +436,0 @@
-/**
- * Converts the CSS classes string to an array of js settings.
- *
- * The CSS classes are edited in element CSS Classes, fieldset CSS
- * of page admin/config/content/wysiwyg/profile/{filter}/edit.
- *
- * This function can also be used to just validate the CSS classes. This could
- * be done in 2 separate functions, both optimized for their specific use case,
- * but that would lead to more code than this single function and (more or less)
- * the same logic and knowledge about the syntax in 2 places.
- *
- * @param string $css_classes
- * A list of classes to add to the style drop down.
- * @param bool $validate
- * TRUE to only validate, FALSE (default) to parse.
- *
- * @return array
- * An array with the parsed css styles or line numbers that contain incorrect
- * syntax.
- */
-function wysiwyg_ckeditor_parse_styles_set($css_classes, $validate = FALSE) {
- $css_styles = array();
- $errors = array();
-
- // Handle both Unix and Windows line-endings.
- $lines = explode("\n", str_replace("\r", '', $css_classes));
- $line_no = 0;
- foreach ($lines as $line) {
- $line_no++;
- $line = trim($line);
- if (!empty($line)) {
- // [name]=[element].[class] pattern expected.
- $line_parts = explode('=', $line);
- if (count($line_parts) === 2) {
- $selector_parts = explode('.', $line_parts[1]);
- if (count($selector_parts) === 2) {
- $style['name'] = trim($line_parts[0]);
- $style['element'] = trim($selector_parts[0]);
- $style['attributes']['class'] = trim($selector_parts[1]);
- if (!empty($style['name']) && !empty($style['element']) && !empty($style['attributes']['class'])) {
- // This line is correct. Add it to the list and continue the loop to
- // prevent it being added to the list of errors.
- $css_styles[] = $style;
- continue;
- }
- }
- }
- $errors[] = $line_no;
- }
- }
- return $validate ? $errors : $css_styles;
-}