Index: editors/yui.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/editors/yui.inc,v
retrieving revision 1.6.2.3
diff -u -p -r1.6.2.3 yui.inc
--- editors/yui.inc	6 Feb 2010 18:17:49 -0000	1.6.2.3
+++ editors/yui.inc	8 Feb 2010 14:11:15 -0000
@@ -46,6 +46,14 @@ function wysiwyg_yui_editor() {
     'load callback' => 'wysiwyg_yui_load',
     'settings callback' => 'wysiwyg_yui_settings',
     'plugin callback' => 'wysiwyg_yui_plugins',
+    'plugin settings callback' => 'wysiwyg_yui_plugin_settings',
+    'proxy plugin' => array(
+      'drupal' => array(
+        'load' => TRUE,
+        'proxy' => TRUE,
+      ),
+    ),
+    'proxy plugin settings callback' => 'wysiwyg_yui_proxy_plugin_settings',
     'versions' => array(
       '2.7.0' => array(
         'js files' => array('yui.js'),
@@ -230,8 +238,7 @@ function wysiwyg_yui_button_setting($edi
   static $plugins;
 
   if (!isset($plugins)) {
-    // @todo Invoke all enabled plugins, not just internals.
-    $plugins = wysiwyg_yui_plugins($editor);
+    $plugins = wysiwyg_get_plugins($editor['name']);
   }
 
   // Return a simple separator.
@@ -267,6 +274,41 @@ function wysiwyg_yui_button_setting($edi
 }
 
 /**
+ * Build a JS settings array of native external plugins that need to be loaded separately.
+ */
+function wysiwyg_yui_plugin_settings($editor, $profile, $plugins) {
+  $settings = array();
+  foreach ($plugins as $name => $plugin) {
+    if (!empty($plugin['load'])) {
+      // Add path for native external plugins; internal ones are loaded
+      // automatically.
+      if (empty($plugin['internal']) && isset($plugin['path'])) {
+        $settings[$name] = base_path() . $plugin['path'];
+      }
+    }
+  }
+  return $settings;
+}
+
+/**
+ * Build a JS settings array for Drupal plugins loaded via the proxy plugin.
+ */
+function wysiwyg_yui_proxy_plugin_settings($editor, $profile, $plugins) {
+  $settings = array();
+  foreach ($plugins as $name => $plugin) {
+    // Populate required plugin settings.
+    $settings[$name] = $plugin['dialog settings'] + array(
+      'title' => $plugin['title'],
+      'icon' => base_path() . $plugin['icon path'] . '/' . $plugin['icon file'],
+      'iconTitle' => $plugin['icon title'],
+      // @todo These should only be set if the plugin defined them.
+      'css' => base_path() . $plugin['css path'] . '/' . $plugin['css file'],
+    );
+  }
+  return $settings;
+}
+
+/**
  * Return internal plugins for this editor; semi-implementation of hook_wysiwyg_plugin().
  */
 function wysiwyg_yui_plugins($editor) {
@@ -291,4 +333,3 @@ function wysiwyg_yui_plugins($editor) {
     ),
   );
 }
-
Index: editors/js/yui.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/editors/js/yui.js,v
retrieving revision 1.1.6.1
diff -u -p -r1.1.6.1 yui.js
--- editors/js/yui.js	6 Feb 2010 22:34:24 -0000	1.1.6.1
+++ editors/js/yui.js	8 Feb 2010 14:11:16 -0000
@@ -2,12 +2,45 @@
 
 /**
  * Attach this editor to a target element.
+ *
+ * Since buttons must be added before the editor is rendered, we add plugins
+ * buttons on attach event rather than in init.
  */
 Drupal.wysiwyg.editor.attach.yui = function(context, params, settings) {
   // Apply theme.
   $('#' + params.field).parent().addClass('yui-skin-' + settings.theme);
+
+  // Load plugins stylesheet.
+  for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+    settings.extracss += ' @import "'+Drupal.settings.wysiwyg.plugins[params.format].drupal[plugin].css+'"; ';
+  }
+
   // Attach editor.
   var editor = new YAHOO.widget.Editor(params.field, settings);
+
+  // Allow plugins to act on setEditorHTML().
+  editor.WYSIWYGSetEditorHTML = editor.setEditorHTML;
+  editor.setEditorHTML = function(incomingHTML) {
+    var params = { type: 'WYSIWYG.setEditorHTML', target: this, content: incomingHTML };
+    this.fireEvent('WYSIWYG.setEditorHTML', params);
+    this.WYSIWYGSetEditorHTML(params.content);
+  }
+
+  // Allow plugins to act on getEditorHTML().
+  editor.WYSIWYGGetEditorHTML = editor.getEditorHTML;
+  editor.getEditorHTML = function() {
+    var params = { type: 'WYSIWYG.getEditorHTML', target: this, content: this.WYSIWYGGetEditorHTML() };
+    this.fireEvent('WYSIWYG.getEditorHTML', params);
+    return params.content;
+  }
+
+  // Load plugins.
+  editor.on('toolbarLoaded', function() {
+    for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+      Drupal.wysiwyg.editor.instance.yui.addPlugin(plugin, editor, Drupal.settings.wysiwyg.plugins[params.format].drupal[plugin], Drupal.settings.wysiwyg.plugins.drupal[plugin]);
+    }
+  });
+
   editor.render();
 };
 
@@ -18,17 +51,85 @@ Drupal.wysiwyg.editor.attach.yui = funct
  */
 Drupal.wysiwyg.editor.detach.yui = function(context, params) {
   if (typeof params != 'undefined') {
-    var instance = YAHOO.widget.EditorInfo.getEditorById(params.field);
+    var instance = YAHOO.widget.EditorInfo._instances[params.field];
     if (instance) {
       instance.destroy();
+      delete YAHOO.widget.EditorInfo._instances[params.field];
     }
   }
   else {
     for (var e in YAHOO.widget.EditorInfo._instances) {
       // Save contents of all editors back into textareas.
       var instance = YAHOO.widget.EditorInfo._instances[e];
-      instance.destroy();
+      if (instance) {
+        instance.destroy();
+        delete YAHOO.widget.EditorInfo._instances[e];
+      }
     }
   }
 };
 
+/**
+ * Instance methods for YUI Editor.
+ */
+Drupal.wysiwyg.editor.instance.yui = {
+  plugins: [],
+
+  addPlugin: function (plugin, editor, settings, pluginSettings) {
+    if (typeof Drupal.wysiwyg.plugins[plugin] != 'object') {
+      return;
+    }
+
+    var instanceId = editor._configs.id.value;
+    var button = editor.toolbar.getButtonByValue(plugin);
+    $(button._button).parent().css('background', 'transparent url(' + settings.icon + ') no-repeat center');
+
+    editor.toolbar.on(plugin + 'Click', function (e) {
+      editor._createCurrentElement('span');
+      var data = { format: 'html', node: editor.currentElement[0], content: $(editor.currentElement[0]).html() };
+      Drupal.wysiwyg.plugins[plugin].invoke(data, pluginSettings, instanceId);
+    });
+
+    editor.on('editorContentLoaded', function (e) {
+      e.target.setEditorHTML(e.target._getEditorHTML());
+    });
+
+    editor.on('afterNodeChange', function (e) {
+      if (typeof Drupal.wysiwyg.plugins[plugin].isNode == 'function') {
+        if (Drupal.wysiwyg.plugins[plugin].isNode(e.target._getSelectedElement())) {
+          this.toolbar.selectButton(plugin);
+        }
+      }
+    });
+
+    editor.on('WYSIWYG.setEditorHTML', function (e) {
+      if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
+        e.content = Drupal.wysiwyg.plugins[plugin].attach(content, pluginSettings, instanceId);
+        e.content = Drupal.wysiwyg.editor.instance.yui.prepareContent(e.content);
+      }
+    });
+
+    editor.on('WYSIWYG.getEditorHTML', function (e) {
+      if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
+        e.content = Drupal.wysiwyg.plugins[plugin].detach(e.content, pluginSettings, instanceId);
+      }
+    });
+  },
+
+  prepareContent: function (content) {
+    var editor = YAHOO.widget.EditorInfo._instances[this.field];
+    content = editor.cleanHTML(content);
+    return content;
+  },
+
+  insert: function (content) {
+    var editor = YAHOO.widget.EditorInfo._instances[this.field];
+    editor.execCommand('inserthtml', content);
+  },
+
+  getContent: function () {
+    var editor = YAHOO.widget.EditorInfo._instances[this.field];
+    return editor.getEditorHTML();
+  }
+
+};
